i'm not able to catch and show validation errors into my CakePHP controller class.
I've this model:
public $validate = array(
'username' => array(
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'Your custom message here',
'allowEmpty' => false,
'required' => true,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
'alphaNumeric' => array(
'rule' => array('alphaNumeric'),
'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
'maxLength' => array(
'rule' => array('maxLength', 50),
'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
));
and this is how i try to catch validation message into controller while save a new element into array:
public function add() {
if ($this->request->is('post')) {
$this->Admin->set($this->request->data);
//$this->Admin->create();
if ($this->Admin->validates()) {
// it validated logic
if ($this->Admin->save($this->request->data)) {
$this->Session->setFlash(__('The admin has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The admin could not be saved. Please, try again.'));
}
} else {
// didn't validate logic
$errors = $this->Admin->validationErrors;
debug($errors);
}
}
}
but it doesn't work. If i pass an empty field an alert with a default message is showed into add.ctp page. If i insert a duplicate, no message is showed.
You don't need
$this->Admin->set($this->request->data);
$this->Admin->validates(){}
because if you are using "save"
$this->Admin->save($this->request->data)
is validating already. That should do the job.
Related
my controller class
class BlistsController extends AppController{
public $components = array('session');
public function index(){
$data = $this->Blist->find('all');
$this->set('var_Blist', $data);
}
public function add(){
print_r($this->request->data);
if($this->request->is(array ('post', 'put'))){
$this->Blist->create();
if($this->Blist->save($this->request->data)){
$this->session->setFlash("book added successfully");
$this->reirect('index');
}
else{
$this->session->setFlash("Unable to add book");
}
}
}
}
I used this code in my home pc. its working fine. but the same code is not working in my workplace. is there any enable need in the wamp.
when i print the print_r($this->request->data)
it shows
Array ( [Blist] => Array ( [F_bookId] => [F_name] => sadfasdf [F_author] => asdfasdf ) )
the field "F_bookId" is auto increment at the database table.
Therefore it not showing at the display page.
App::uses('AppModel', 'Model');
/**
* Blist Model
*
*/
class Blist extends AppModel {
/**
* Primary key field
*
* #var string
*/
public $primaryKey = 'F_bookId';
/**
* Display field
*
* #var string
*/
public $displayField = 'F_name';
/**
* Validation rules
*
* #var array
*/
public $validate = array(
'F_bookId' => array(
'notEmpty' => array(
'rule' => array('notEmpty'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'F_name' => array(
'notEmpty' => array(
'rule' => array('notEmpty'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'F_author' => array(
'notEmpty' => array(
'rule' => array('notEmpty'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
);
}
Add.ctp
<h1> Add Book Details </h1>
<?php
echo $this->Form->create('Blist');
echo $this->Form->input('F_bookId');
echo $this->Form->input('F_name');
echo $this->Form->input('F_author');
echo $this->Form->end('Add Book');
?>
the final code which is working fine..
public function add(){
$data = $this->request->data;//getting the values from the input fields
//get the last record
$lastRecordId = $this->Blist->find('first', array('order' =>array('F_bookId' => 'DESC')));
//Split the book id, to generate a new book id
$temp = str_split($lastRecordId['Blist']['F_bookId'], '4');
$data['Blist']['F_bookId'] = ($temp[0]. ((String)((int)$temp[1]+1)));
if($this->request->is(array ('post', 'put'))){
$this->Blist->create();
if($this->Blist->save($data)){
$this->session->setFlash("book added successfully");
$this->redirect('add');
}
else{
debug($this->Blist->validationErrors);
$this->session->setFlash("Unable to add book");
}
}
}
Your id is auto-created by the auto increment feature of your database. There is no need to validate the user input for F_BookId since there is none and if you set the rule notEmpty on that field validation will trigger an error.
remove this part from your $validate array:
'F_bookId' => array(
'notEmpty' => array(
'rule' => array('notEmpty'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
This should let your save your books.
On a sidenote: You might want to read about naming conventions concerning CakePHP to make your life easier: http://book.cakephp.org/2.0/en/getting-started/cakephp-conventions.html
Recently I've been learning AJAX and jQuery, to validate my forms rather than using validations on refresh. I have the form submission with AJAX working correctly - sending the form successfully without a page refresh - however when the form is submitted and passed through the validations within User.php, if any errors are returned these are shown in a separate form, not the original form from which the data was submitted.
EDIT : The errors just keep on coming - The "implode(',', $error)" works, but I've found it doesn't work in chrome. I'm sure there's a quick fix for this but I can't seem to find one that works.
create.ctp
<?php echo $this->Html->script('jquery', FALSE); ?>
<?php echo $this->Html->script('validation', FALSE); ?>
<div id="success"></div>
<div class="users form">
<h2>Create User</h2>
<?php echo $this->Form->create('User'); ?>
<fieldset>
<?php
echo $this->Form->input('username', array('id'=>'username'));
echo $this->Form->input('password', array('id'=>'password'));
echo $this->Form->input('confirmpw', array('label'=>'Confirm Password', 'id'=>'confirmpw', 'type'=>'password'));
echo $this->Form->input('tos', array('type'=>'checkbox', 'id'=>'tos', 'label'
=>__('I confirm I have read the Terms and Conditions', true), 'hidden'=>false, 'value'=>'yes'));
?>
</fieldset>
<?php
echo $this->Js->submit('Send', array(
'before'=>$this->Js->get('#sending')->effect('fadeIn'),
'success'=>$this->Js->get('#sending')->effect('fadeOut'),
'update'=>'#success'
));
echo $this->Form->end();
?>
<div id="sending" style="display: none; background-color: lightblue;">Sending...</div>
<?php
?>
</div>
validation.js
$(document).ready(function() {
$('#username').blur(function(){
$.post(
'/practice/Users/validate_form',
{ field: $('#username').attr('id'), value: $('#username').val() },
handleUsernameValidation
);
});
function handleUsernameValidation(error) {
if (error.length > 0) {
if ($('#username-notEmpty').length == 0) {
$('#username').after('<div id="username-notEmpty" class="error-message">' + error + "</div>");
}
}
else {
$('#username-notEmpty').remove();
}
}
}
)
UsersController.php
public function create() {
if ($this->request->is('post')) {
$this->User->create();
if ($this->User->save($this->request->data)) {
if ($this->RequestHandler->isAjax()) {
$this->render('/Messages/success', 'ajax');
}
else {
$this->Session->setFlash(__('The user has been saved'));
$this->redirect(array('action' => 'index'));
}
}
}
}
public function validate_form() {
if ($this->RequestHandler->isAjax()) {
$field = $this->request->data['field'];
$value = $this->request->data['value'];
$this->request->data['User'][$field] = $value;
$this->User->set($this->request->data);
if ($this->User->validates()) {
$this->autoRender = FALSE;
}
else {
$error = $this->validateErrors($this->User);
$this->set('error', $error[$this->request->data['field']]);
}
}
}
validate_form.ctp
<?php echo implode(',', $error); ?>
User.php
public $validate = array(
'username' => array(
'notempty' => array(
'rule' => array('notempty'),
'message' => 'Field cannot be empty.',
'allowEmpty' => false,
'required' => true,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
'alphanumeric' => array(
'rule' => array('alphanumeric'),
'message' => 'Only alphanumeric characters allowed.',
'allowEmpty' => false,
'required' => true,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
'maxlength' => array(
'rule' => array('maxlength', '15'),
'message' => 'Login name limit is 15 characters.',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
'minlength' => array(
'rule' => array('minlength', '6'),
'message' => 'Login name must be more than 6 characters.',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
'isUnique' => array(
'rule' => array('isUnique'),
'message' => 'This username is not available, please pick a different name.',
),
),
'password' => array(
'notempty' => array(
'rule' => array('notempty'),
'message' => 'Field cannot be empty.',
'allowEmpty' => false,
'required' => true,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
'maxlength' => array(
'rule' => array('maxlength', '15'),
'message' => 'Password limit is 15 characters.',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
'minlength' => array(
'rule' => array('minlength', '6'),
'message' => 'Password must be more than 6 characters.',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'confirmpw' => array(
'maxlength' => array(
'rule' => array('maxlength', '15'),
'message' => 'Password limit is 15 characters.',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
'minlength' => array(
'rule' => array('minlength', '6'),
'message' => 'Password must be more than 6 characters.',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
'notEmpty' => array(
'rule' => array('notempty'),
'message' => 'Passwords do not match, please try again.'
),
'equalToField' => array(
'rule' => array('equalToField', 'password'),
'message' => 'Passwords do not match, please try again.',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
'on' => 'create', //Limit validation to 'create' or 'update' operations
)
),
'tos' => array(
'comparison' => array(
'rule' => array('comparison', '==', 'yes'),
'required' => true,
'message' => 'Please agree to the Terms and Conditions.'
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
);
function equalToField($check, $otherfield) {
$fname = '';
foreach ($check as $key => $value) {
$fname = $key;
break;
}
return $this->data[$this->name][$otherfield] === $this->data[$this->name][$fname];
}
Thanks.
As far as I remember validateErrors returned array of error messages for each fields.
Can you please try this in validate_form.ctp
<?php echo implode(',', $error); ?>
Or if it not work, let's try
<?php echo var_export($error); ?>
and see what kind of variable that' the $error contains.
I have a login form (login.ctp) in my Members View. But when I give the url as /login, than instead of showing the login of Members view, its showing login page of users view.
/Views/login.ctp file
<div class="members form">
<?php echo $this->Session->flash('auth'); ?>
<?php echo $this->Form->create('Member'); ?>
<fieldset>
<legend><?php echo __('Please enter your username and password'); ?></legend>
<?php echo $this->Form->input('username');
echo $this->Form->input('password');
?>
</fieldset>
<?php echo $this->Form->end(__('Login')); ?>
</div>
App controller file
class AppController extends Controller {
//...
public $components = array(
'Session',
'Auth' => array(
'loginRedirect' => array('controller' => 'members', 'action' => 'home'),
'logoutRedirect' => array('controller' => 'members', 'action' => 'index')
)
);
public function beforeFilter() {
$this->Auth->allow('index', 'view');
}
//...
}
My routes.php file
Router::connect('/', array('controller' => 'members', 'action' => 'index'));
Router::connect('/login', array('controller' => 'members', 'action' => 'login'));
I have cleared all the cookies. Where is the mistake?
One more thing, I have even tried deleting user controllers, but if I delete user controllers I get the following error...
Error: UsersController could not be found.
This is my login function from MembersController.php
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->redirect($this->Auth->redirect());
} else {
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
}
//code in member model.
class Member extends AppModel {
/**
* Validation rules
*
* #var array
*/
public $validate = array(
'firstname' => array(
'notempty' => array(
'rule' => array('notempty'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'lastname' => array(
'notempty' => array(
'rule' => array('notempty'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'email' => array(
'email' => array(
'rule' => array('email'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'password' => array(
'notempty' => array(
'rule' => array('notempty'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'age' => array(
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'address' => array(
'notempty' => array(
'rule' => array('notempty'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'phone' => array(
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'created_on' => array(
'datetime' => array(
'rule' => array('datetime'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
);
function beforeSave() {
if(isset($this->data[$this->alias]['password']))
$this->data[$this->alias]['password'] = Security::hash($this->data[$this->alias]['password'], null, true);
return true;
}
}
Try modifying your components array to this:
public $components = array(
'Session',
'Auth' => array(
'loginRedirect' => array('controller' => 'members', 'action' => 'home'),
'logoutRedirect' => array('controller' => 'members', 'action' => 'index'),
'Form' => array(
'userModel' => 'Member'
),
)
);
Or try this in beforeFilter():
// Pass settings in using 'all'
$this->Auth->authenticate = array(
AuthComponent::ALL => array('userModel' => 'Member'),
'Form',
'Basic'
);
EDIT
Tested Code and process
AppController Code
<?php
class AppController extends Controller
{
public $components = array
(
'Session',
'Auth' => array
(
'loginRedirect' => array('controller' => 'members', 'action' => 'home'),
'logoutRedirect' => array('controller' => 'members', 'action' => 'index')
)
);
public function beforeFilter()
{
$this->Auth->allow('index', 'view');
$this->Auth->fields = array('username' => 'email', 'password' => 'password');
$this->Auth->userModel = 'Member';
}
}
all of your code is working fine all you need to do is just set Auth->userModel to Member.
MemberController
<?php
class MembersController extends AppController
{
var $name = 'Members';
function beforeFilter()
{
parent::beforeFilter();
}
}
?>
And in Member controller define beforeFilter as above.
I'm not sure why I keep receiving all the errors instead of just the invalid fields even when I fill out some of the required fields properly.
Submissions Controller:
public function submit() {
$this->set('title_for_layout', 'Submit - ');
if ($this->request->is('ajax')) {
if (!empty($this->request->data)) {
$this->Submission->set($this->request->data);
if ($this->Submission->invalidFields($this->request->data)) {
$formErrors = $this->Submission->validationErrors;
} else {
$formErrors = null;
}
} else {
$formErrors = null;
}
$this->set(compact('formErrors'));
}
/Submissions/json/submit.ctp:
<?php
$toReturn = array(
'formErrors' => $formErrors
);
echo json_encode($toReturn);
Submission model:
var $validate = array(
'title' => array(
'title' => array(
'rule' => 'notEmpty',
'required' => true,
'allowEmpty' => false,
'message' => 'Please enter a title'
),
'minLength' => array(
'rule' => array('minLength', 5),
'message' => 'Please make your title longer (e.g. IJL John F. Kennedy donated his presidential salary to charity)'
),
'maxLength' => array(
'rule' => array('maxLength', 300),
'message' => 'Your title needs to be shorter'
),
),
'description' => array(
'shortDescription' => array(
'rule' => array('shortDescription'),
'message' => 'Your description needs to be longer'
),
'longDescription' => array(
'rule' => array('longDescription'),
'message' => 'Your description needs to be shorter'
),
),
'source' => array(
'source' => array(
'rule' => 'notEmpty',
'required' => true,
'allowEmpty' => false,
'message' => 'Enter a valid source URL (e.g. http://en.wikipedia.org/wiki/Penguins)'
),
'website' => array(
'rule' => 'url',
'message' => 'Enter a valid source URL (e.g. http://en.wikipedia.org/wiki/Penguins)'
),
),
'category' => array(
'category' => array(
'rule' => 'notEmpty',
'required' => true,
'allowEmpty' => false,
'message' => 'Please choose a category'
)
)
);
Form values that are getting serialized and sent:
Errors I'm getting in a json response:
Pulling hair out over here :|
You seem to have got a little muddle up with validates() and invalidFields()
invalidFields() returns the invalid fields after a validates(), see: http://book.cakephp.org/2.0/en/models/data-validation/validating-data-from-the-controller.html
So your code should look something like this:
$this->Submission->set($this->request->data);
if (!$this->Submission->validates()) {
$formErrors = $this->Submission->invalidFields();
} else {
$formErrors = null;
}
First, set the data to the model:
$this->ModelName->set($this->request->data);
Then, to check if the data validates, use the validates method of the model, which will return true if it validates and false if it doesn’t:
if ($this->ModelName->validates()) {
// it validated logic
} else {
// didn't validate logic
$errors = $this->ModelName->validationErrors;
}
Validating Data from the Controller
I am creating a message controller that allows the user send messages to other users. Here is my database structure
users
id
username
password
messages
id
to_id
from_id
subject
message
the to_id and from_id both reference the id column in users. Here is my model for messages
message
<?php
class Message extends AppModel {
var $name = 'Message';
var $displayField = 'subject';
var $validate = array(
'id' => array(
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'to_id' => array(
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
'allowEmpty' => false,
'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'from_id' => array(
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
'allowEmpty' => false,
'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
);
var $belongsTo = array(
'Sender' => array(
'className' => 'User',
'foreignKey' => 'to_id'
),
'Recipient' => array(
'className' => 'User',
'foreignKey' => 'from_id'
)
);
}
Then here is my view
<div class="messages form">
<?php echo $this->Form->create('Message');?>
<fieldset>
<legend><?php __('Add Message'); ?></legend>
<?php
echo $this->Form->input('to_id');
echo $this->Form->input('from_id');
echo $this->Form->input('subject');
echo $this->Form->input('message');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit', true));?>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<li><?php echo $this->Html->link(__('List Messages', true), array('action' => 'index'));?></li>
</ul>
</div>
It displays a drop down box, but no users in it. I have atleast 5 users in the users table
even if i add prefix like so
echo $this->Form->input('Sender.to_id');
echo $this->Form->input('Recipient.from_id');
still doesn't work
Like stated by Mark it doesn't work if you don't stick to convention. Rename the foreignkeys, Sender => sender_id, Recipient => recipient_id
You have to make the lists in the controller first
in the message controller
$senders = $this->Message->Sender->find('list');
$recipients = $this->Message->Recipient->find('list');
$this->set(compact('senders', 'recipients'));
Then in the view
echo $this->Form->input('recipient_id');
echo $this->Form->input('sender_id');