The following is the validation rule
public function rules()
{
return array(
// username and password are required
array('oldPassword', 'required'),
array('oldPassword', 'authenticate'),
....
);
}
public function authenticate($attribute,$params)
{
$this->userModel=User::model()->findByPk(Yii::app()->user->id);
if($this->userModel!=null){
if(!$this->userModel->validatePassword($this->oldPassword))
$this->addError($attribute, "Incorrect current password");
}
}
Everything works fine but the problem lies here... when I keep the oldPassword blank both the validation error for "required" & "authentication' are shown whereas I want to show the error msg for the first one,if not blank then the later.
Add a condition in authenticate() to only validate if oldPassword is not empty:
public function authenticate($attribute, $params) {
if ($this->oldPassword) {
...
}
}
Related
I'm having trouble displaying the validation errors of a form using a custom validator.
The errors does exist as the debug method shows, it just won't be displayed in the form.
I'd like to be able to show the error message under (or above, or anywhere) the field.
What I've tried
Well, the documentation does state:
When using View\Helper\FormHelper::control(), errors are rendered by
default, so you don’t need to use isFieldError() or call error()
manually.
Nevertheless, I added the following in the form (just below the email control), which didn't do anything more. No message displayed.
if ($this->Form->isFieldError('email')) {
echo $this->Form->error('email', 'Yes, it fails!');
}
I've also found several questions and answers about this issue on SO, but they look outdated (from '09 to '13) and do not seem to correspond to today's CakePHP syntax.
What I've done
Users/forgot_password.ctp
<?= $this->Form->create() ?>
<?= $this->Form->control('email', ['type' => 'email']) ?>
<?= $this->Form->button(__('Reset my password')) ?>
<?= $this->Form->end() ?>
UsersController.php
(notice the specific validation set, as explained in documentation)
public function forgotPassword()
{
if ($this->request->is('post')) {
$user = $this->Users->newEntity($this->request->getData(), ['validate' => 'email']);
if ($user->errors()) {
debug($user->errors()); // <- shows the validation error
$this->Flash->error(__('An error occurred.'));
} else {
// ... procedure to reset password (which works fine!) and redirect to login...
return $this->redirect(['action' => 'login']);
}
}
}
UsersTable.php
public function validationEmail(Validator $validator)
{
$validator
->email('email')
->notEmpty('email', __('An email address is required.'));
return $validator;
}
What it looks like
Update
Thanks to #ndm comment, here is the correct way to display the error.
In UsersController.php:
public function forgotPassword()
{
// user context for the form
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity(§user, $this->request->getData(), ['validate' => 'email']); <- validation done on patchEntity
if ($user->errors()) {
$this->Flash->error(__('An error occurred.'));
} else {
// ... procedure to reset password and redirect to login...
return $this->redirect(['action' => 'login']);
}
}
// pass context to view
$this->set(compact('user'));
}
And in the view forgotPassword.ctp:
<?= $this->Form->create($user) ?>
//modify your function as below
public function forgotPassword()
{
if ($this->request->is('post')) {
$user = $this->Users->newEntity($this->request->getData(), ['validate' => 'email']);
if ($user->getErrors()) {
debug($user->getError('email')); // <- shows the validation error
$this->Flash->error(__($user->getError('email')['_empty']));
} else {
// ... procedure to reset password (which works fine!) and redirect to login...
return $this->redirect(['action' => 'login']);
}
}
}
I have a Yii form accept first name, last name and email from user. Using an add more link, users can add multiple rows of those three elements.
For email validation, unique and required are set in model rules and everything works fine. I am using JavaScript to create addition row on clicking add more link.
Problem
On the first row my values are John, Newman, johnnewman#gmail.com and the second row, i'm entering Mathew, Heyden, johnnewman#gmail.com. In this case email address is duplicated. None of the validation rules (require and unique) is capable of validating this. Can some one suggest a better method to validate this ?
Update:
I created a custom validation function and i guess this is enough to solve my problem. Can someone tell me how to access the whole form data / post data in a custom validation function ?
public function uniqueOnForm($attribute){
// This post data is not working
error_log($_REQUEST, true);
$this->addError($attribute, 'Sorry, email address shouldn\'t be repeated');
}
You can try this:
<?php
public function rules()
{
return array(
array('first_name', 'checkUser')
);
}
public function checkUser($attribute)
{
if($this->first_name == $this->other_first_name){
$this->addError($attribute, 'Please select another first name');
}
}
?>
You can also look into this extension
You can write custom validator:
//protected/extensions/validators
class UniqueMailValidator extends CValidator
{
/**
* #inheritdoc
*/
protected function validateAttribute($object, $attribute)
{
$record = YourModel::model()->findAllByAttributes(array('email' => $object->$attribute));
if ($record) {
$object->addError($attribute, 'Email are exists in db.');
}
}
}
// in your model
public function rules()
{
return array(
array('email', 'ext.validators.UniqueMailValidator'),
...
Or better try to use THIS
public function rules(){
return array(
//other rules
array('email', 'validEmail'),
)
}
public function validEmail($attribute, $params){
if(!empty($this->email) && is_array($this->email)){
$isduplicate = $this->isDuplicate($this->email);
if($isduplicate){
$this->addError('email', 'Email address must be unique!');
}
}
}
private function isDuplicate($arr){
if(count(array_unique($arr)) < count($arr)){
return true;
}
else {
return false;
}
}
because you are using tabular input (multiple row) , so make sure input field as an array. might be like this :
<?php echo $form->textField($model, 'email[]'); ?>
on my profile update form i have fullname password and confirm password fields . currently my validations are works only for
empty fields and password mismatch. but how can i add password charactor limits validations as well ?
password should be min:5 and max 15 charactors.
please advice.
public function changePasswordPost()
{
$user = Auth::user();
if (Input::get('password')) {
if (Input::get('password') !== Input::get('confirm_password')) {
return Redirect::route('admin-change-password')->with('error', 'Password field is not identical to Confirm Password.');
}
$user->update();
return Redirect::route('admin-change-password')->with('success', 'You have successfully updated login details.');
}
return Redirect::route('admin-change-password')->with('error', 'Input Missing');
}
You need to do something like this:
use Validator;
public function changePasswordPost(Request $request)
{
$user = Auth::user();
if ($request->get('password')) {
if (($request->get('password') !== $request->get('confirm_password')) ||
(Validator::make($request->all(), ['password' => 'min:5|max:15'])->fails())) {
return redicrect()->route('admin-change-password')->with('error', 'Password field is not identical to Confirm Password.');
}
$user->update();
return redirect()->route('admin-change-password')->with('success', 'You have successfully updated login details.');
}
return redirect()->route('admin-change-password')->with('error', 'Input Missing');
}
I haven't tested this code but the point is that you need to use Validator class from laravel. Note that I have changed some of the stuff to use laravel-5.1 friendly API.
Note that you can get cleaner code by adding Validation before you do anything. Something like this:
public function changePasswordPost(Request $request)
{
/**
* This basically captures your password matching
* and password length cases in a compact way so
* you don't need all the if statements.
*/
$validation = Validator::make($request->all(),
['password' => 'required|min:5|max:15',
'confirm_password' => 'required|same:password']);
if ($validation->fails())
{
response()->redirect('admin-change-password')->with('error', 'bad input');
}
/**
* Here you do the rest of the processing like updating the database.
*/
}
Working with Laravel 5 I'm facing an issue to where it routes to auth/login by default. When you login, it redirects to login causing an error. When I'm able to actually use http://localhost/login it actually routes to home like it should. Anything new that would be causing it behave like this?
HomeController shown below:
<?php namespace app\Http\Controllers;
class HomeController extends Controller {
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard to the user.
*
* #return Response
*/
public function index()
{
return view('home');
}
public function showLogin()
{
// show the form
return view('login');
}
public function doLogin()
{
// validate the info, create rules for the inputs
$rules = array(
'email' => 'required|email', // make sure the email is an actual email
'password' => 'required|alphaNum|min:3' // password can only be alphanumeric and has to be greater than 3 characters
);
// run the validation rules on the inputs from the form
$validator = Validator::make(Input::all(), $rules);
// if the validator fails, redirect back to the form
if ($validator->fails()) {
return Redirect::to('login')
->withErrors($validator) // send back all errors to the login form
->withInput(Input::except('password')); // send back the input (not the password) so that we can repopulate the form
} else {
// create our user data for the authentication
$userdata = array(
'email' => Input::get('email'),
'password' => Input::get('password')
);
// attempt to do the login
if (Auth::attempt($userdata)) {
// validation successful!
// redirect them to the secure section or whatever
// return Redirect::to('secure');
// for now we'll just echo success (even though echoing in a controller is bad)
echo 'SUCCESS!';
} else {
// validation not successful, send back to form
return Redirect::to('login');
}
}
}
public function doLogout()
{
Auth::logout(); // log the user out of our application
return Redirect::to('login'); // redirect the user to the login screen
}
}
I figured it out to be that constructor.
public function __construct()
{
$this->middleware('auth');
}
I removed that and changed the view to 'auth/login' and it works like a charm.
I have a Input validation to change user password, when i tried to submit the form i got always an error that the new password and confirm password are not matched even, this is my post action :
public function doChangePassword()
{
if(Auth::check())
{
$validator = Validator::make(Input::all(), User::$updatePasswordRules);
// if the validator fails, redirect back to the form
if ($validator->fails()) {
return Redirect::to('change-password')->with('message', 'The following errors occurred')->withErrors($validator)->withInput();
} else {
// store
$user = User::find(Auth::user()->id);
if(Auth::user()->password==Input::get('new_password')){
$user->password = Hash::make(Input::get('new_password'));
$user->save();
}
else{
return Redirect::to('change-password')->with('message', 'The password is not correct');
}
// redirect
Session::flash('message', 'Successfully updated password!');
return Redirect::to('login');
}
}
else{
return Redirect::to('login');
}
}
this is my rules :
public static $updatePasswordRules = array(
'password'=>'required|alpha_num|between:6,12',
'new_password'=>'required|alpha_num|between:6,12|confirmed',
'password_confirmation'=>'required|alpha_num|between:6,12'
);
so please if someone has an idea i will be very appreciative
It's because Laravel expects (for your specific case) confirmed field to be named new_password_confirmation
From doc "The field under validation must have a matching field of foo_confirmation. For example, if the field under validation is password, a matching password_confirmation field must be present in the input."
Thus rules should look like (also change input name in form):
public static $updatePasswordRules = array(
'password'=>'required|alpha_num|between:6,12',
'new_password'=>'required|alpha_num|between:6,12|confirmed',
'new_password_confirmation'=>'required|alpha_num|between:6,12'
);
Or you can do it with same validation rule (if don't want to update form inputs):
public static $updatePasswordRules = array(
'password'=>'required|alpha_num|between:6,12',
'new_password'=>'required|alpha_num|between:6,12|same:password_confirmation',
'password_confirmation'=>'required|alpha_num|between:6,12'
);