Showing a manually-set error in Zend_Form - zend-form

When a visitor enters their email address into a form, I want to check that it's unique. So I have a simple email form:
class Form_Register extends Zend_Form
{
public function __construct($options = null)
{
parent::__construct($options);
$this->setName('register');
$email = new Zend_Form_Element_Text('Email');
$email->setLabel('Your email address:')
->setRequired(true)
->addFilter('StripTags')
->addFilter('StringTrim')
->addValidator('EmailAddress')
->addErrorMessage('Please check that email address is correct.');
$submit = new Zend_Form_Element_Submit('submit');
$submit->setAttrib('id', 'submitbutton');
$this->addElements(array($email, $submit));
}
}
And then if the request is a post, I check if the email is unique. I'm adding an error message to the element when it's not unique, but it doesn't appear in my view.
if ($this->getRequest()->isPost())
{
$formData = $this->_request->getPost();
// check if email is unique
$isUnique = FALSE;
if ( NULL != $member )
{
$form->Email->addErrors(array('That email is already in use.'))
->markAsError();
}
$form->populate($formData);
$this->view->form = $form;
My view just echos the form:
<?php echo $this->form ?>

My solution to this problem was to use Zend_Form_Decorator_Callback.

I think your IF statement is wrong. Make sure that your code is going inside IF loop.
Try something like this:
if ( NULL != $member )
{
echo "inside IF loop";
} else {
echo "oops missed the loop";
}

Related

yii generatepasswordhash not working

For some strange reasons, i am finding it difficult to login with yii->$app->generatePasswordhash($password.) I have a backedn where i register users and also change password. Users can login successfully when i created them but when i edit user password, the system keeps telling me invalid username or password. Below is my code.
//Model
Class Adminuser extends ActiveRecord
{
public $resetpassword
public function activateuser($id,$newpassword)
{
//echo Yii::$app->security->generatePasswordHash($newpassword); exit;
$user = Adminuser::find()->where(['id' =>$id])->one();
$user->status = self::SET_STATUS;
$user->password_reset_token = null;
$user->password = Admin::genPassword($this->resetpassword); // this returns yii::$app->security->generatePasswordHash($password)
return $user->save();
}
}
//controller action
public function actionActivate($id)
{
$model = new Adminuser();
$model->scenario = 'adminactivate';
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
if($model->activateuser($id,$model->password))
{
//send a mail
Yii::$app->session->setFlash('success', 'New user has been activated.');
return $this->redirect(['index']);
}
else
$errors = $model->errors;
}
return $this->render('activate', [
'model' => $model,
]);
}
Please i need help
Your activateuser() method has $newpassword as an incoming parameter. Anyway you are using $this->resetpassword in Admin::genPassword(). Looks like that is the reason of the problem and all your passwords are generated based on null value. So try to use $user->password = Admin::genPassword($newpassword); instead.

Creating nested form in yii

following this link I am trying to create a register form and connect the form to tables "user" and "profile". In my controller I have copied the same code as follows:
public function actionRegistration()
{
$form = new CForm('application.views.user.registerForm');
$form['user']->model = new Users;
$form['profile']->model = new Profile;
if($form->submitted('register') && $form->validate())
{
$user = $form['user']->model;
$profile = $form['profile']->model;
if($user->save(false))
{
$profile->userID = $user->id;
$profile->save(false);
$this->redirect(array('/user/login'));
}
}
var_dump($form->submitted('register'));
$this->render('registration', array('form'=>$form));
}
I actually don't know what is $form->submitted('register') for and why it returns false!
Can anyone explain me what is that and what is 'register' value which is passed to the submitted function!? Also why it should return false while posting the form?
the traditional way to get form data is
$model = new User;
if(isset($_POST["register"])){ //get the form data
...
$model->attributes=$_POST["register"]; //set model's attributes
...
}
for more examples you can go: http://www.yiiframework.com/doc/blog/1.1/en/comment.create

How do you add more error codes for user login on YII?

In yii I can use:
self::ERROR_USERNAME_INVALID;
I want another one:
self::ERROR_USER_BANNED;
That must give the error:
Sorry, but you cannot login because you account has been blocked.
How do I set this up?
Add it directly to your protected/components/UserIdentity.php :
class UserIdentity extends CUserIdentity {
const ERROR_USER_BANNED = -1; // say -1 you have to give some int value
public function authenticate() {
// ... code ...
if (/* condition to check for banning */) { // you might want to put this check right after any other username checks, and before password checks
$this->errorCode=self::ERROR_USER_BANNED;
$this->errorMessage='Sorry, but you cannot login because your account has been blocked.'
return $this->errorCode;
}
}
}
The default way with LoginForm.php model :
Add a new validator rule, say to your username field:
public function rules() {
return array(
// ... other rules ...
array('username','isBanned')
);
}
// the isbanned validator
public function isBanned($attribute,$params) {
if($this->_identity===null)
$this->_identity=new UserIdentity($this->username,$this->password);
if($this->_identity->authenticate() === UserIdentity::ERROR_USER_BANNED){
$this->addError($attribute,$this->_identity->errorMessage);
}
Ofcourse you could have declared another function in UserIdentity to check just for banning, and call that function from the isBanned validator, instead of having things in the authenticate function.
add following in UserIdentity.php
const ERROR_USER_BANNED = 12 ; #or whateve int value you prefer
public function getErrorMessageX() #or whatever method name
{
switch ($this->errorCode)
{
case self::ERROR_USER_BANNED:
return 'sorry, your account has been banned'; # custom error msg
case self::ERROR_USERNAME_INVALID:
return 'User does not exists';
case self::ERROR_PASSWORD_INVALID:
return 'Password does not match';
case self::ERROR_ACCOUNT_NOT_CONFIRMED: #this one is mine:)
return 'This Account needs confirmation';
}
}
now in LoginForm.php
public function authenticate( )
{
$this->_identity = new UserIdentity($this->username,$this->password);
if( $this->_identity->authenticate() === FALSE )
$this->addError('username', $this->_identity->errorMessageX); #here
#some more code
return !$this->_identity->errorCode;
}

How to set default action dynamically in Yii

i want to change default action of a controller depends on which user is logged in.
Ex. There are two users in my site : publisher and author and i want to set publisher action as default action when a publisher is logged in, and same for author.
what should i do? when can I check my roles and set their relevant actions?
Another way to do this would be setting the defaultAction property in your controller's init() method. Somewhat like this:
<?php
class MyAwesomeController extends Controller{ // or extends CController depending on your code
public function init(){
parent::init(); // no need for this call if you don't have anything in your parent init()
if(array_key_exists('RolePublisher', Yii::app()->authManager->getRoles(Yii::app()->user->id)))
$this->defaultAction='publisher'; // name of your action
else if (array_key_exists('RoleAuthor', Yii::app()->authManager->getRoles(Yii::app()->user->id)))
$this->defaultAction='author'; // name of your action
}
// ... rest of your code
}
?>
Check out CAuthManager's getRoles(), to see that the returned array will have format of 'role'=>CAuthItem object, which is why i'm checking with array_key_exists().
Incase you don't know, the action name will be only the name without the action part, for example if you have public function actionPublisher(){...} then action name should be: publisher.
Another, simpler, thing you can do is keep the default action the same, but that default action simply calls an additional action function depending on what kind of user is logged in. So for example you have the indexAction function conditionally calling this->userAction or this->publisherAction depending on the check for who is logged in.
I think you can save "first user page" in user table. And when a user is authenticated, you can load this page from database. Where you can do this? I think best place is UserIdentity class. After that, you could get this value in SiteController::actionLogin();
You can get or set "first page" value:
if (null === $user->first_page) {
$firstPage = 'site/index';
} else {
$firstPage = $user->first_page;
}
This is a complete class:
class UserIdentity extends CUserIdentity
{
private $_id;
public function authenticate()
{
$user = User::model()->findByAttributes(array('username' => $this->username));
if ($user === null) {
$this->errorCode = self::ERROR_USERNAME_INVALID;
} else if ($user->password !== $user->encrypt($this->password)) {
$this->errorCode = self::ERROR_PASSWORD_INVALID;
} else {
$this->_id = $user->id;
if (null === $user->first_page) {
$firstPage = 'site/index';
} else {
$firstPage = $user->first_page;
}
$this->errorCode = self::ERROR_NONE;
}
return !$this->errorCode;
}
public function getId()
{
return $this->_id;
}
}
/**
* Displays the login page
*/
public function actionLogin()
{
$model = new LoginForm;
// if it is ajax validation request
if (isset($_POST['ajax']) && $_POST['ajax'] === 'login-form') {
echo CActiveForm::validate($model);
Yii::app()->end();
}
// collect user input data
if (isset($_POST['LoginForm'])) {
$model->attributes = $_POST['LoginForm'];
// validate user input and redirect to the previous page if valid
if ($model->validate() && $model->login())
$this->redirect(Yii::app()->user->first_page);
}
// display the login form
$this->render('login', array('model' => $model));
}
Also, you can just write right code only in this file. In SiteController file.

stop further execution after zend form is not valid and populate the form

if the form is not valid then populate the form and stop further execution of code. How to establish this.
Here's what I usually do in my controller:
public function editAction()
{
$model = $this->_findModelFromRequestParams();
$form = new Form_MyModelForm();
$form->populate($model->toArray());
//display the form for the first time and return
if ( ! $this->_request->isPost()) {
$this->view->form = $form;
return;
}
//populate the form with the POST values, and validate.
//If NOT valid, display the form again
if ( ! $form->isValid($this->_request->getPost())) {
$this->view->form = $form;
return;
}
try {
$formData = $form->getValues();
//save the new values here...
//set a flash message and redirect to the view page
$this->_redirect('/model/view/id/' . $model->id);
} catch (Exception $e) {
//there was some sort of error, so set a flash message with the error
//and display the form again. $form is already populated with values
//since we called $form->isValid(), which populated the form
$this->view->form = $form;
}
}