Jonathon Posted March 5, 2013 Share Posted March 5, 2013 Right, I'm trying to put together some code to register a user in Yii. I just wanted some feedback on it for problems or general logic within the whole Yii framework. This is what I did. I created a new file called register.php <?php /* @var $this SiteController */ /* @var $model RegistrationForm */ /* @var $form CActiveForm */ $this->pageTitle=Yii::app()->name . ' - Register'; /*$this->breadcrumbs=array( 'Login', );*/ $this->layout = 'sidebar'; ?> <div class="search"> <div class="form-center span5"> <h1>Register</h1> <div class="form"> <?php $form=$this->beginWidget('CActiveForm', array( 'id'=>'registration-form', 'enableClientValidation'=>true, 'clientOptions'=>array( 'validateOnSubmit'=>true, ), )); ?> <div class="row"> <?php echo $form->textField($model,'first_name', array('placeholder'=>'First Name')); ?> <?php echo $form->error($model,'first_name'); ?> </div> <div class="row"> <?php echo $form->textField($model,'last_name', array('placeholder'=>'Last Name')); ?> <?php echo $form->error($model,'last_name'); ?> </div> <div class="row"> <?php echo $form->textField($model,'email', array('placeholder'=>'Your Email')); ?> <?php echo $form->error($model,'email'); ?> </div> <div class="row"> <?php echo $form->passwordField($model,'pass', array('placeholder'=>'Password')); ?> <?php echo $form->error($model,'pass'); ?> </div> <div class="row buttons"> <?php echo CHtml::submitButton('Submit', array('class'=>'btn btn-primary')); ?> </div> <?php $this->endWidget(); ?> </div><!-- form --> </div> </div> saved it in my views/site folder. Then I created a RegisterForm.php that I basically copied from the LoginForm.php and edited. <?php /** * RegistrationForm class. * RegistrationForm is the data structure for submitting * user data. It is used by the 'registration' action of 'SiteController'. */ class RegistrationForm extends CFormModel { public $first_name; public $last_name; public $email; public $pass; public $active; /** * Declares the validation rules. * The rules state that first name, last name, email and pass are required, * email must be valid email. * email must be unique using User class. */ public function rules() { return array( // username and password are required array('first_name, last_name, email, pass', 'required'), // trim date for first names, further validation? strip_tags? array('first_name, last_name, email, pass', 'filter', 'filter' => 'trim'), // email must be valid email array('email', 'email'), // email must be unique and use User class array('email', 'unique', 'className' => 'User'), // default for date created ); } /** * Declares attribute labels. */ public function attributeLabels() { return array( 'first name'=>'First Name', 'last_name'=>'Last Name', 'email'=>'Email', 'password'=>'Password', ); } } And saved that in my models folder. Thenin my site controller I added the following action /* * Displays and handles the registration process */ public function actionRegister() { $model=new RegistrationForm; $newUser = new User; // if it is ajax validation request if(isset($_POST['ajax']) && $_POST['ajax']==='registration-form') { echo CActiveForm::validate($model); Yii::app()->end(); } // collect user input data if(isset($_POST['RegistrationForm'])) { $model->attributes=$_POST['RegistrationForm']; if ($model->validate()) { $newUser->first_name = $model->first_name; $newUser->last_name = $model->last_name; $newUser->email = $model->email; $newUser->pass = hash_hmac('sha256', $model->pass, Yii::app()->params['encryptionKey']); $newUser->active = md5(uniqid(rand(), true)); $newUser->date_modified = NULL; $newUser->date_created = new CDbExpression('NOW()'); //$newUser->live = 1; if($newUser->save()) { // Everything saved, redirect $this->redirect(array('site/index')); } } } // display the register form $this->render('register',array('model'=>$model)); } It does work, but I wanted an opinion of it it has any potential security flaws/issues or if the logic is in the wrong files/locations etc. You may see some of my own questions in there like "strip_tags()?" for example. Also I wondered about the rules() Those rules are in the RegistrationForm.php but I also have rules() in my User model. This would appear to be a wrong thing to be occurring. However, I wasn't sure what the best way to fix this was? Thanks in advance Jonathon Link to comment Share on other sites More sharing options...
Larry Posted March 6, 2013 Share Posted March 6, 2013 Personally, I would just use the User model and its create view. As it stands, you're duplicating all the functionality in two models, one of which will only ever be used once per site user. Also, I'd take some of that functionality (such as assignments to active, date_modified, and date_created) and put it in the model. And your RegistrationForm model wouldn't need the "active" attribute, as it's not used by that model. That being said, you did a great job creating the MVC components from scratch. Link to comment Share on other sites More sharing options...
Jonathon Posted March 6, 2013 Author Share Posted March 6, 2013 Hi Larry,Thanks for the nice words. I forgot about the create functions that come built into Yii, so I'm glad you pointed that out to me. I should really have twigged when I realised I had two sets of rules(). Anyway, thanks, I had a re-jig of things and came up with the following.User Model /* * function to register new user internal variables */ public function newUserRegistrationVariables() { // Internally assigned variables $this->active = md5(uniqid(rand(), true)); $this->date_modified = NULL; $this->date_created = new CDbExpression('NOW()'); return array($this->active, $this->date_modified, $this->date_created); } } User Controller public function actionCreate() { // new User model $model=new User; // Bring internal registration variables from model() $registrationInternalVariables = $model->newUserRegistrationVariables(); // Uncomment the following line if AJAX validation is needed // $this->performAjaxValidation($model); if(isset($_POST['User'])){ $model->attributes=$_POST['User']; // Validate date from form using rules() if ($model->validate()) { $model->first_name; $model->last_name; $model->email; $model->pass = hash_hmac('sha256', $model->pass, Yii::app()->params['encryptionKey']); $model->active = $registrationInternalVariables[0]; $model->date_modified = $registrationInternalVariables[1]; $model->date_created = $registrationInternalVariables[2]; if($model->save()) { // Everything was saved ok return success message Yii::app()->user->setFlash('register-success','Thank you! An activation email has been sent to your email address.'); } } } $this->render('create',array( 'model'=>$model, )); } So I hope that's a secure and better way to go about itThanksJonathon Link to comment Share on other sites More sharing options...
Larry Posted March 8, 2013 Share Posted March 8, 2013 That's definitely better. The only thing left to change would be to make the newUserRegistrationVariables() method a beforeSave() method so it automatically sets those values. You can use isNewRecord to only do it for new registrations. There's an example in the book in Chapter 5, I believe. Link to comment Share on other sites More sharing options...
Jonathon Posted March 9, 2013 Author Share Posted March 9, 2013 Thanks Larry Link to comment Share on other sites More sharing options...
saritha Posted March 8, 2016 Share Posted March 8, 2016 (edited) I am getting the fatal error that the class 'yii ' is not found CHttpException The system is unable to find the requested action "Reg.php". please help me out to solve Edited March 8, 2016 by saritha Link to comment Share on other sites More sharing options...
Larry Posted March 15, 2016 Share Posted March 15, 2016 What version of Yii are you using? Can you provide some more context for what's going on when you get this error? Link to comment Share on other sites More sharing options...
SohaibKtb Posted March 30, 2019 Share Posted March 30, 2019 CException Property "RegisterForm.pass" is not defined. /opt/lampp/htdocs/yii1.1/framework/web/helpers/CHtml.php(2760) 2748 $name=substr($attribute,0,$pos); 2749 $value=$model->$name; 2750 foreach(explode('][',rtrim(substr($attribute,$pos+1),']')) as $id) 2751 { 2752 if((is_array($value) || $value instanceof ArrayAccess) && isset($value[$id])) 2753 $value=$value[$id]; 2754 else 2755 return null; 2756 } 2757 return $value; 2758 } 2759 else 2760 return $model->$attribute; 2761 } 2762 2763 /** 2764 * Appends {@link errorCss} to the 'class' attribute. 2765 * @param array $htmlOptions HTML options to be modified 2766 */ 2767 protected static function addErrorCss(&$htmlOptions) 2768 { 2769 if(empty(self::$errorCss)) 2770 return; 2771 2772 if(isset($htmlOptions['class'])) Link to comment Share on other sites More sharing options...
Recommended Posts