Jump to content
Larry Ullman's Book Forums

My Project Diary


Edward
 Share

Recommended Posts

Thursday, December 6th, 2012

 

Got the activation page working page with basic coding for now, i need to move some of the logic code which is highlighted below into the model using a relevant method. I also used active record to pull out the model instance for the user. When i tried to use Save() to update the model instance it didn't save directly to the database, so i had to use saveAttributes to get it to work, otherwise if i am correct it was trying to save a whole record.

 

public function actionactivate()
{
if(isset($_GET['x'], $_GET['y']))
{
// Load up the active record model with email from $_get['x']
$user = User::model()->find('email=:email', array(':email'=>$_GET['x']));

// Redirect if activation code is already null or no record was found
if ($user === null || $user->activation_code === null || $user->activation_code !== $_GET['y'])
// Redirect to site index page
$this->redirect(Yii::app()->user->returnUrl);
}
else
// Redirect to site index page
 $this->redirect(Yii::app()->user->returnUrl);

$modelUser = new User('activate');

if(isset($_POST['User']))
{
$modelUser->attributes = $_POST['User'];
if($modelUser->validate())
{
		 // TODO Write model method for this code
$user->username = $modelUser->username;
$user->password = $modelUser->password;
$user->activation_code = 'null';
$user->saveAttributes(array('username', 'password', 'activation_code'));
$this->redirect(array('view','id'=>$user->id));
}
}

$this->render('activate',array(
'model'=>$modelUser, 'data'=> array(
'first_name' => $user->first_name,
'email' => $user->email,
'activation_code' => $user->activation_code
)));
}

 

I also worked on the login page which is now working i had to make customizations to the User_Identity Scipt

 

class UserIdentity extends CUserIdentity
{
/**
* Authenticates a user.
* The example implementation makes sure if the username and password
* are both 'demo'.
* In practical applications, this should be changed to authenticate
* against some persistent user identity storage (e.g. database).
* @return boolean whether authentication succeeds.
*/

private $_id;

public function authenticate()
{
// Load model for username and email by active record
$user = User::model()->findByAttributes(array('username'=>$this->username));

if($user === null)
	 $this->errorCode=self::ERROR_USERNAME_INVALID;
else if($user->password !== $user->hashpassword($this->password))
$this->errorCode=self::ERROR_PASSWORD_INVALID;
else
{
$this->_id = $user->id;
$this->username = $user->username;
	 $this->errorCode = self::ERROR_NONE;
}

return $this->errorCode == self::ERROR_NONE;
}

public function getId()
{
 return $this->_id;
}
}

 

Here is my LoginForm model code

 

class LoginForm extends CFormModel
{
public $username;
public $password;
public $rememberMe;
private $_identity;
/**
* Declares the validation rules.
* The rules state that username and password are required,
* and password needs to be authenticated.
*/
public function rules()
{
return array(
// username and password are required
array('username, password', 'required'),
// rememberMe needs to be a boolean
array('rememberMe', 'boolean'),
// password needs to be authenticated
array('password', 'authenticate'),
);
}
/**
* Declares attribute labels.
*/
public function attributeLabels()
{
return array(
'rememberMe'=>'Remember me next time',
);
}
/**
* Authenticates the password.
* This is the 'authenticate' validator as declared in rules().
*/
public function authenticate($attribute,$params)
{
if(!$this->hasErrors())
{
$this->_identity = new UserIdentity($this->username,$this->password);
if(!$this->_identity->authenticate())
// Added two messages in here as only the password textbox was going red, it was better when both were red
$this->addError('username','');
$this->addError('password','Incorrect username or password.');
}
}
/**
* Logs in the user using the given username and password in the model.
* @return boolean whether login is successful
*/
public function login()
{
if($this->_identity === null)
{
$this->_identity = new UserIdentity($this->username,$this->password);
$this->_identity->authenticate();
}
if($this->_identity->errorCode === UserIdentity::ERROR_NONE)
{
$duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days
Yii::app()->user->login($this->_identity,$duration);
return true;
}
else
return false;
}
}

Link to comment
Share on other sites

Antonio i saw that funny coding style you complained about last time in the UserIdentity class:

 

do you remember

 

return !$this->errorCode; (Can also be written as $this->errorCode == self::ERROR_NONE)

 

if you go to CBaseUserIdentity you will find

 

const ERROR_NONE=0;

const ERROR_USERNAME_INVALID=1;

const ERROR_PASSWORD_INVALID=2;

 

So a way i thought of looking at this !$this->errorCode was

 

If something is NOT TRUE it must be FALSE

and

If something is NOT FALSE it must be TRUE

this is almost sounds like a nursery rhyme.

Link to comment
Share on other sites

Yeah, I figured that out. My problem what not really the solution, but the structure of the solution. The logic was more cumbersome than it needed to be. When a user struggles to follow the logic, and it's easy fixable, I would argue that it is bad code. While my code did not use the error codes, it was easier to read and understand.

 

It's really all preference, but simple code is often good code. I think you've improved the login code, but it could be even simpler. I don't like long if-statements and I don't like else when dealing with return values. I would argue this is very easy to read and understand

public function login()
{
   if($this->_identity !== null) { return; } // User already logged in

   // Authenticate credentials
   $this->_identity = new UserIdentity($this->username, $this->password);
   $this->_identity->authenticate();

   // Check authenticate response
   if($this->_identity->errorCode === UserIdentity::ERROR_NONE)
   {
       $duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days
       Yii::app()->user->login($this->_identity, $duration);

       // User was successfully logged in!
       return true;
   }

   // Wrong username/password-combo
   return false;
}

 

Regarding your activation codes, you could optimally create a model for handling that logic, but I think that code looks good enough really.

 

Great progress, Edward. You've come an incredibly long way since you started posting here. Keep it going!

  • Upvote 1
Link to comment
Share on other sites

Yes you could do that check for the not null value but the actual login page on the live site would be blocked via accessRules() which could be added in the site model. So therefore the login page would be disabled for authenticated users. I just added in some nice way of thinking about the confusing return.

 

So a way i thought of looking at this !$this->errorCode was

 

If something is NOT TRUE it must be FALSE

and

If something is NOT FALSE it must be TRUE

this is almost sounds like a nursery rhyme.

Link to comment
Share on other sites

  • 2 months later...

Still working on my project have about 20 databases and 20 models. I struggled with yii at the beginning but now it's okay. Took me about 3 days to work it out. Well i thought i had worked it out until i read more of Larry's YiiBook and realized there was some things i done the PHP way rather than the Yii way so some edits were required. Seems as though i did manage to get about 75% of the main stuff learned by myself.

Link to comment
Share on other sites

Removed login cookies from website and have set a session time out of 15 minutes.

 

Have set encryption keys and moved restricted words array in to config/main.php param array.

 

I have also implemented Yii Booster this is incredibly useful with some editional features provided by clevertech.biz.

Link to comment
Share on other sites

  • 3 weeks later...

Working on changing my activation page to a verify method using Yii routes. I have also decided to have user create their username aswell as contact details on registration page, this cuts out the activation page later on in the website. If users do not verify there accounts within three months, there records will be deleted, and usernames they have orginally taken will be available for others.

Link to comment
Share on other sites

  • 3 weeks later...

Today i have shortened the length of my activation codes to be a string of 10 alphanumerical characters, it seemed a waste of database space to hold a md5 32 characters string, so i used the PHP substr function to cut they md5 generated string to 10. This makes the verification email look a tad better.

 

Another thing i done that i forget to mention was i moved the login form which was part of the site controller over to the user controller, so now to login, you access through user/login. I think this is the way to go, keeping the login related to user. The other advantage was i scrapped the LoginForm model and moved over the methods required into the user model.

Link to comment
Share on other sites

I did think about what you said before i made the change but my verfication works by checking their email against the activation code. Most of the codes would be different, so i don't see how even if someone did have the same activation code as someone else how they would be able to guess the other personal's email. I thought the case would of been highly unlikely that is my reason for shortening it. So do you think that would stand or can you suggest of another way to get a unique 10 alphanumerical code?

Link to comment
Share on other sites

Monday, 25th March 2013

 

There have been many changes to my project since i have started with regards to the way i was coding then debating over using frameworks then learning and starting to use a framework for my project. I did give my project a go using the Yii framework using the knowledge i was able to gather from the Yii Definitive guide but after reading the Yii Book i found out that there was about 20% of the Yii stuff i needed to redo. I also found the Twitter Boostrap css framework which i implemented myself first of all and made my own customizations to Yii widgets, the trouble with this was i was changing files in the main framework folder which is not good to do, as when you upgrade Yii, you will have to change all the files again. Later through the help of others here i found the Yii-Booster extension, this works out better as i can just add in their extension without having to alter the main framework files, so everything would be ready if there was any Yii upgrade.

 

At the moment i am building what i know is correct for my site and trying to use Yii in the correct way. I guess with all of us in the same sitution we have to be patient now and slow down a bit to wait to see how Larry finishes of his Yii Book and to get all the correct knowledge before bashing out our projects. I just try now to do a couple of hours a day on the Coding, i spent about 1 - 2 month trying to plan databases but now realize i need to change some things again, this is one reason i think its better to take the project slow. If you build too much and its wrong you only have to take more of it down. And for me when i have to do the same things again i find my brain seizing up and not wanting to do it.

 

Today i worked on the page after registration that confirms an email was sent to you and you need to click on the link to activate your account. There was a way to breach security if you passed the user id to the registration link page, so i decided to pass the email of the user over to load up the model and again used routes as i discussed with verify.

 

Off the record i just bought "The Walking Dead - Survival Instinct" for PS3 where you play the TV series guy Daryl Dixon along with his brother Meryl, its actually pretty good. Its good for clearing out the brain after some ours of coding and can make you jump as its quite intensive. Well if any of you have the time, i would recommend that game.

Link to comment
Share on other sites

Wednesday, 27th March 2013

 

Last couple of days worked on the "Activation Send Link", "Forgot Password", "Forgot Username", ive only spent a couple of hours on it. It really is amazing working with a framework and an extension. I seem to be on a roll again and since i am using the correct Yii-Booster extension, now i don't see the need to go back and change all the css again, its working great now.

 

Next week i will be starting my item listing page again, the page is extremely complicated as their are so many variables and its pretty much impossible for it to work without adding in jquery. I covered all the variables needed for listing items but some of them which may not be necessary for some members will need to be hidden or optional, i also have dynamic data in the form for a couple of parts, including shipping, images and attributes. My site wouldn't be able to work without fully completing this page, so i plan on just working on this now until its 100% and leaving other parts of the website till its done. I can't put a time on how long its going to take but from what i see it seems to have the hardest coding of my website.

 

I am extremely looking forward to reading Larry's new implementing javascript into Yii chapter and hope it has some useful common how to's. This should be out within the next few weeks, so it will here in perfect time and should be useful for my jquery stuff which needs added. Ah i forgot to mention one cool thing about Yii-Booster is that you can easily add in a WYSIWYG Editor, like Redactor which is new and available to use for Yii projects. This will certainly be another timesaver and benefit of using extensions.

 

Does anyone know what this Globbledegook means?

 

?UTF-8?B?

 

I saw yii using it in their email headers in the contact form, does it mean what i think it does?

Link to comment
Share on other sites

Thanks for that Larry, now it makes more sense.

 

Thursday, 28th March 2013

 

Today i had this thought to put extra comments inside a controller. We need to push all we can out of the controller into the model's beforeValidate, afterValidate, beforeSave and afterSave methods. So i thought here that it would be a good idea to put a note of what we were doing in the controller like this:

 

$modelUser->validate();
// Generate password reset code - User::afterValidate()
// Send email with password reset link - User::afterValidate()

 

Yesterday i was adding in new routes in my config/main.php script

 

'user/emailusername/<email:.+>'=>'user/emailusername',
'user/registrationlink/<x:.+>'=>'user/registrationlink',
'<controller:\w+>/<id:\d+>'=>'<controller>/view',
'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
'user/verify/<x:.+>/<y:\w+>'=>'user/verify',
'user/resetpassword/<x:.+>/<y:\w+>'=>'user/resetpassword',

 

It appears that the order of which the routes are placed in Yii matters to how your site performs, i had to place two routes above the route '<controller:\w+>/<id:\d+>'=>'<controller>/view', otherwise they would not work and show the standard ugly urls.

 

Just over the past few days my computer fan has been making these strange noises like vroom, vrooooooom, vrooooooooooooom, its in a repeatitive manner, and the noise has become very irritating. I have a HP desktop, its probably 2 - 3 years old.

Link to comment
Share on other sites

Saturday, 30th March 2013

 

Took a day of yesterday but got back onto it today, Ive just tested through and improved my code on the Forgotten Password, Forgotten Username and Password Reset Page. All of these including the Verfication and Registration Link page took up 8 new actions in my User controller, there were quite a lot of buggy issues that could arise from this area. So far everything is looking quite good. Currently i am not on any live server i was with RackSpace but they were costing the Bomb, so i decided to build locally for now. I will need to test my email with links later on the live server. I am also thinking of building an email class to handle system emails but that is a job that can be done later on.

 

So now i will be starting the Item page again next. I will also need to rethink my shipping options and try to breakdown things into the simplest universal form in which they can be used by any particular person selling products. ;)

Link to comment
Share on other sites

Saturday, 6th April 2013

 

Done bits and bobs of code in the week, managed to get together my final database plan for the listing of Items and reduce shipping from three to one table. I spent time also in the week reading the Yii chapters on Role Based Authentication, Extensions and got half way through the JS chapter. All the chapters have been good, the javascript chapter looks as though it covers most of what i need for my item page, thanks Larry.

 

This week i was checking out on 3d games programming something i used to do in 2d about 16 years ago. I was searching for 3d game engines and found a few like UDK, Unity3d and CryEngine. I have decided to give Unity3d a go and have been working through the Stealth game tutorials. With Unity3d you have an IDE about like you have with the new adobe CS6. A lot of the work can be done visually for the 3d game environment you only have small scripts for editing or adding classes that can be written in C#, Javascript (the other one) or Boo. Basically Unity3d is similar to Yii but only about 50% of what it seems so far seems to be visually done rather than coding. Well i guess i am not into hard game logic yet! The good thing about Unity3d as well is they have an assets store, so you can buy character model, or vehicles or props whatever you need. I like web programming but if you try the Unity3d yourself you will see its a lot more fun. Now i just want to get my Yii coding done so i can spend all night on it. :)

 

Here is some sample Unity C# Code

 

using UnityEngine;
using System.Collections;

public class DoneAlarmLight : MonoBehaviour
{
	public float fadeSpeed = 2f;			// How fast the light fades between intensities.
	public float highIntensity = 2f;		// The maximum intensity of the light whilst the alarm is on.
	public float lowIntensity = 0.5f;		// The minimum intensity of the light whilst the alarm is on.
	public float changeMargin = 0.2f;		// The margin within which the target intensity is changed.
	public bool alarmOn;					// Whether or not the alarm is on.
	
	
	private float targetIntensity;			// The intensity that the light is aiming for currently.
	
	
	void Awake ()
	{
		// When the level starts we want the light to be "off".
		light.intensity = 0f;
		
		// When the alarm starts for the first time, the light should aim to have the maximum intensity.
		targetIntensity = highIntensity;
	}
	
	
	void Update ()
	{
		// If the light is on...
		if(alarmOn)
		{
			// ... Lerp the light's intensity towards the current target.
			light.intensity = Mathf.Lerp(light.intensity, targetIntensity, fadeSpeed * Time.deltaTime);
			
			// Check whether the target intensity needs changing and change it if so.
			CheckTargetIntensity();
		}
		else
			// Otherwise fade the light's intensity to zero.
			light.intensity = Mathf.Lerp(light.intensity, 0f, fadeSpeed * Time.deltaTime);
	}
	
	
	void CheckTargetIntensity ()
	{
		// If the difference between the target and current intensities is less than the change margin...
		if(Mathf.Abs(targetIntensity - light.intensity) < changeMargin)
		{
			// ... if the target intensity is high...
			if(targetIntensity == highIntensity)
				// ... then set the target to low.
				targetIntensity = lowIntensity;
			else
				// Otherwise set the targer to high.
				targetIntensity = highIntensity;
		}
	}
}

Link to comment
Share on other sites

Hi Edward,

It's an awesome and helpful document of an e-commerce project to a newbie web developer who are struggling at the beginning phase of their career which is the best guide to them for how to start and complete projects.

It's sure that everyone here who follow your thread definitely learn web development because you are providing a simple way of development as you already read lots of books about web development mostly Larry Ullman's books are great.

Hope you will complete full documentation of your project without any dis-continued. Finally, I would like to thank you for doing such a great work.

  • Upvote 1
Link to comment
Share on other sites

Thanks, since my last post on the 6th of April ive made a breakthrough basically the biggest jump since i started ive done about 300 lines of js, jquery and implementing and customizing plugins in js. I need a bit more time and ill come in to update a little bit. But to be honest things are getting a little personal with this project so i can chat about it but only briefly, that is me being the selfish man of which i am.

 

I really like Unity3d, haven't had a chance to use it again since my last post. I did make a flashing rotating alarm system where the lights flashed between blue and red, its really fun unlike our webdesign. Later this year i will definetly being buying a Mac desktop and laptop it seems to be the way to go and the other reason is that Unity3d was developed by Mac so considering the things i like doing it seems to fit better now.

 

I would really love to see your project that you build in codeignitor Antonio.

 

Done is better than perfect the reason being there are too many lines of code in an application making it impossible to be perfect!

Link to comment
Share on other sites

Sunday, 28th April 2013

 

I can't believe it the end of the month already.  Well this month i have cleared up most of my worries, my item listing page which i have worked on this month is probably 60% complete. There has just been a massive amount of work to do and it has not been easy, i have debugged through 100's of bugs which unexpectedly came up out of the blue. It was the first time i had used everything together at the same time HTML, CSS, Javascript, JQuery, PHP, Yii Framework. I used to be scared of Javascript and JS as i had never used it before but now i like it very much, it was actually very easy to use pretty much the same as PHP.

 

Things covered this month:

 

1. I installed Flash SWFUpload into the Yii framework which is used by YouTube and WordPress projects. I had a horrible time trying to install this from scratch into Yii and later found an extension which lead to another extension of this extension for Yii. You have probably seen this cool guy before but his work was very useful to get started with:

 

http://www.ramirezcobos.com/2010/11/06/how-to-use-swfuploads-yii-extension/

 

I have written some of the javascript handlers but still have remaining work to complete. Which is: For my site you can upload 12 pictures but of those pictures must be the default image that someone will see on your listing. So in order to get the default image each image must be attached to a radio button. Also each image is attached to a hidden input field which holds the value of the temporary image file location. And then its easy to add remove image with basic javascript. Images need to be resized using the PHP GD Library, i am expecting JPG, JPEG, GIF and PNG. BMP are not accepted as GD library has no function for resizing.

 

2. I worked with dynamic tabler data for attributes and values for products and also shipping options which were done via the client side with js and Jquery. I also had to collect and redraw data in the views files, i have done this successfully. For the tabler data i used the javascript var uid = new Date().getTime() to get the clock value for example 1367087682298, i also had to have a server side PHP equivalent of this function so i used round(microtime(true) * 1000), which works perfectly. The unique clock values where added to id's and name's if this was not done form data would be lost.

 

An example of one of the input's:

 

<select class="span6" name="Shipping[1367087683027][service_type]" id="Shipping_service_type_1367087683027">

 

 

3. I implemented a CKEditor into my listings page and removed harmfull attributes of it. I still have to remove image pasting into this but is should be a small job with js.

 

4. I also worked on a js dynamic item returns statement.

 

So on this item listing form i still have the images part ot finish off and the dynamic ajax category loader which i will need to build manually and will be starting next, also their is the final collection of data and validation. I am really looking foward to working with Javascript objects and json, the category loader i will be building is the same as what ebay have if you have ever gone in their to list products and have to select a category. The only difference between theirs and mine is mine will come up in a modal window with the background dimmed out.

 

Just wanted to briefly comment on on last thing, i have got about 700 lines of code (300 lines being JS and JQuery) in my item listing views file :ph34r: and probably about 100 (expecting about 200) lines in my controller action so far and their is code all over the place in the related models. But i am telling you without the JS code its impossible to make the page work the way it does. I do plan on disabling pages of the site that need JS enabled to be quite frank, nobody should be listing products unless their are on a laptop of pc anyway. If you are working and taking orders on a website you should be on the appropriate device. I will try to cover the best i can for people using mobile devices for buying products, something which i love to do myself, so understand the buyers needs here.

 

Okay i hope some of this is useful for others, stay tuned.

Link to comment
Share on other sites

Sunday, 28th April 2013 (2)

 

You may be wondering why i am typing a 2nd Sunday the 28th update, well i typed the first very early hours of the morning, now its about 10.10pm Sunday night so this is the 2nd. 

 

I just had to come on to tell you because today i got my first iMac and yes i am typing this post with it right now. It really is quite amazing the screen is so clear and all the cables and desktop are now gone. Its just a tiny little keyboard, small magic mouse and apple iMac monitor on my desk. I now have loads of space around me this is really great. Really i feel like i can take over the world now, just kidding  :) . Today was the first time i also saw the box for a apple iMac it really is quite unique even when i walked out the Apple shop other people also starred at the box like they had never seen something quite like that before. I felt like a celebrity and tried to rush to the car rather shy of all the acknowledgement.

 

I have a few problems now, the first one is i have to get all the files from my old computer over to this one. The second problem is my adobe CD is for installation on windows, so i will have to get one for Mac. This means i have no dreamweaver IDE, i do have a zend studio IDE license so i will have to download and use that for temporary. The third problem is i will have to download and configure MAMP, i was using XAMMP before. One thing i am sad about is i will no longer be able to play the old DOS games like Alone in the Dark or Feary Take Adventure. But i guess its time to move forward and put the skeletons into the closest.

 

As soon as i get Adobe installed i will take a picture to show you my new setup.

 

Well ill have to see what i can get done tomorrow, will it be possible to work on the ajax dynamic category loader or will it be a day trying to get everything configured. Whatever it will be i am extremely happy and love my iMac as much as i love Larry Ullman.

 

Its actually my birthday next week so this was an early present for it. Okay ill see you guys later..

  • Upvote 2
Link to comment
Share on other sites

Xampp works on OSX as well, but even better, OSX comes with Apache, PHP and Ruby pre-installed. All you have to do is to activate it, and maybe do some symlinking so you can run php in the command line without using the runnable path. Just search for how to do that. Simple!

 

MySQL and PHPMyAdmin is also pretty easy to install. Search for guides there as well.

 

I really love my Air for development. I prefer it greatly over my stationary windows machine. Looking forward to pictures. :)

  • Upvote 1
Link to comment
Share on other sites

 Share

×
×
  • Create New...