Validating non-model select box CakePHP - cakephp

In the following from a have a select box which is not related to any database fields:
echo $this->Form->create('Event');
echo $this->Form->input('customer_id', array('label' => __('Customer')));
echo $this->Form->input('service_id', array('label'=>__('Service')));
echo $this->Form->select('user_id', $users, array('multiple'=>true));
echo $this->Form->end(__('Save'));
In the Event model I have a validation rule which is as follows:
var $validate = array(
'user_id'=>array(
'notempty'=> array(
'rule'=>'notEmpty',
'message'=> 'Vælg en medarbejder'
)
))
THe problem is that this validation rule is never called. What may the problem be?
Here is the dump of data after from submition:
array(
'customer_id' => '107',
'service_id' => '195',
'user_id' => '',
...
)
The rule has just been tested on edit and it works perfectly, together with the remaining rules. The problem is that none of the rules are fired on create.

You need to validates manually. Try this in your Controller.
$this->Event->set($this->request->data);
if ($this->Event->validates()) {
//Save your data by calling $this->Event->save($this->request->data);
} else {
// didn’t validate logic
$errors = $this->ModelName->validationErrors;
}

Validation doesn't apply on select(), hidden(), radio() etc. You should always go through Form::input() like:
$this->Form->input(
'user_id',
array(
'type'=>'select',
'options'=>$users,
'multiple'=>true, ....));
Then the validation will be called as expected ;)

Related

CakePHP one form for multiple models does not validate properly

So I have two models, that are Company and User. Here are the relations:
Company:
public $hasMany = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'company_id',
)
User:
public $belongsTo = array(
'Company' => array(
'className' => 'Company',
'foreignKey' => 'company_id',
)
And there is a form were both instances are being created. The problem is that only the Company fields are being validated and User is not. Even though the validation rules for just creating or editting a User work perfect. Here is the form in question:
echo $this->Form->create('Company', array('action'=>'register'));?>
echo $this->Form->input('Company.name', array('label'=>__('Company name*')));
echo $this->Form->input('Company.address', array('label'=>__('Address*')));
echo $this->Form->input('Company.city', array('label'=>__('City*')));
echo $this->Form->input('User.0.name', array('label'=>__('Name*')));
echo $this->Form->input('User.0.email', array('label'=>__('Email*')));
echo $this->Form->input('User.0.email_confirmation', array('label'=>__('Email confirmation')));
echo $this->Form->end(array('label'=>'Save', 'onclick'=>'disableSubmit(this)'));
I am fully aware of the validate only option, but I wonder what is the proper way to make validation work.
Any help or guidance is much appreciated.
As requested, I provide the Model logic as well:
public function registerCompany($data){
unset($this->User->validate['company_id']);
if($this->saveAll($data, array('validate'=>'only'))){
if($this->saveAssociated($data)){
return true;
}
}else{
return false;
}
}
Here are some of the validation rules of User model, there are two different validation types for REST service and for web client, so this is for the web client only. NOTE: it works all good on single user create/edit:
$this->validate = array(
'name'=>array(
'Insert user name'=>array(
'rule'=>'notEmpty',
'message'=>'Insert user name',
'last'=>false
)
)
Use this to validate:
Suppose you are saving the data from "Company Controller".
if( $this->Company->saveAll(array('validate'=>only)){
//your save logic here
} else {
//here form has some validation errors.
debug($this->Company->validationErrors);
}
Try this any reply....
Same you can do with "User"
if( $this->User->saveAll(array('validate'=>only)){
//your save logic here
} else {
//here form has some validation errors.
debug($this->User->validationErrors);
}
And
In form use this for user data:
echo $this->Form->input('User.name', array('label'=>__('Name*')));
saveAll is a wrapper of saveMany and saveAssociated. So you don't have to call both methods.
Then, according to the Cake's doc, to unset a validation you should use the syntax : $this->Model->AssociatedModel->validate...
Should look like this :
public function registerCompany($data){
unset($this->Company->User->validate['company_id']);
if($this->Company->saveAssociated($this->request->data)){
return true;
}else{
return false;
}
}

Cakephp 2.3.9 custom message in model validation not working

I am doing model validation in my admin panel login so there is only two fields username and password. Validation is working but custom message which I have written in my model is not shown.
Model
public $validate = array(
'username' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'Please Enter Your Username'
)
),
'password' => array(
'required' => array(
'rule' => array ('notEmpty'),
'message' => 'Please Enter Your Password'
)
)
);
Controller
function login(){
$this->layout = 'admin_login';
if ($this->request->is('post')) {
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirect());
}
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
View
echo $this->Form->create('Admin',array('autocomplete'=>"off"));
echo '<div style="width:294px;float:left;position:relative;">';
echo $this->Form->input('username' , array('label' => '', 'placeholder' =>'Enter your username','div' => false));
echo $this->Form->input('password' , array('label' => '', 'value' =>'', 'div' => false,'placeholder'=>'Enter Your Password'));
echo '</div>';
echo '<div style="padding-left:0px;">';
echo $this->Form->end(__('Login' ,true));
I have already tried a few things like which is mentioned in this link, but it's not working for me.
CakePHP : Validation message not displaying
That looks like a message from the browser and not CakePHP.
CakePHP now adds a required attribute which modern browsers can use to trigger an error.
You can do one of three things here:
One: Set up your form to leave validation to the server:
$this->Form->create(array('novalidate'=>true));
Two: Set a custom validation message in the browser: http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#dom-cva-setcustomvalidity
Three: tolerate it
You get that message because the "username" field is flagged as "required". Maybe you've not defined it in the Form->input() function, but the "required" flag has been automatically added from the Model (due to your validation rules). As timstermatic said, it's a browser validation message caused by the required attribute.
To solve this issue (and show the CakePHP validation message) you've to force for avoiding the addition of the "required" flag on your field:
$this->Form->input('username', array('required' => FALSE));
This will override the Model automatic additions. Happy coding ;)
*Edited => It's important to clarify that the inline override removes only the required flag on the field: you'll take advantage of the Model validation anyway (just because if an empty field is sent to the server, it will not pass the validation rule you entered.
keep this code it will bypass the html5 validation and add your custom validations
view
echo $this->form->create('Post',array('action'=>'add'));
echo $this->form->input('title');
echo $this->form->input('body');
echo $this->form->submit('Save Post',array('formnovalidate'=>true));
echo $this->form->end();//Creates ending form tag
Model
var $validate=array(
'title'=>array(
'title_must_not_be_empty'=>array('rule'=>'notEmpty','message'=>'Please enter a title),
'title_must_be_unique'=>array('rule'=>'isUnique','message'=>'Title name already exists')
),
'body'=>array(
'body_must_not_be_empty'=>array(
'rule'=>'notEmpty',
'message'=>'Please enter body'
)
)
);
This will work just the way you want

Cakephp HABTM: View generating drop down instead of multi value selectbox

I am trying to work with HABTM association between Profiles and Qualifications tables.
Model: Profile.php
App::uses('AppModel', 'Model');
class Profile extends AppModel {
public $hasAndBelongsToMany = array(
'Qualification' => array(
'className' => 'Qualification',
'joinTable' => 'profile_qualifications',
'foreignKey' => 'profile_id',
'associationForeignKey' => 'qualification_id',
'unique' => 'keepExisting'
)
);
}
Model: Qualification.php
App::uses('AppModel', 'Model');
class Qualification extends AppModel {
public $hasAndBelongsToMany = array(
'Profile' => array(
'className' => 'Profile',
'joinTable' => 'profile_qualifications',
'foreignKey' => 'qualification_id',
'associationForeignKey' => 'profile_id',
'unique' => 'keepExisting',
)
);
}
Controller: ProfilesController.php
App::uses('AppController', 'Controller');
class ProfilesController extends AppController {
public function edit() {
$this->Profile->id = $this->Auth->user('profile_id');
if ($this->request->is('post') || $this->request->is('put')) {
if ($this->Profile->save($this->request->data)) {
$this->Session->setFlash(__('The profile has been saved'));
$this->redirect(array('action' => 'view'));
} else {
$this->Session->setFlash(__('The profile could not be saved. Please, try again.'));
}
} else {
$this->request->data = $this->Profile->read(null, $this->Auth->user('profile_id'));
}
$salutations = $this->Profile->Salutation->find('list', array('fields' => array('Salutation.id', 'Salutation.abbr_name')));
$qualifications = $this->Profile->Qualification->find('list', array('fields' => array('Qualification.id', 'Qualification.abbr_name')));
$this->set(compact('salutations', 'qualifications'));
}
}
Vew: edit.ctp
<div class="profiles form">
<?php echo $this->Form->create('Profile'); ?>
<fieldset>
<legend><?php echo __('My Profile'); ?></legend>
<?php
echo $this->Form->input('salutation_id');
echo $this->Form->input('first_name');
echo $this->Form->input('middle_name');
echo $this->Form->input('last_name');
echo $this->Form->input('qualification'); /* gives drop down not multi select */
echo $this->Form->input('bio');
echo $this->Form->input('email');
echo $this->Form->input('mobile');
echo $this->Form->input('phone');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>
The edit view thus generated contains drop down to select a single value at a time for Qualifications attribute.
I want to know how can I generate a view with multi value selection box for qualifications ?
Moreover, what is the mistake in my code right now ?
First time poster, long time user.
I stumbled across this question today, and ended up using the subsequent solution which indeed does work quite nicely. However, I left myself wondering "why wouldn't CakePHP pickup on the HABTM relationship properly?" Especially considering (at least in my case) that the majority of the files had been baked in the cake console.
If we dive a little deeper into the issue, we discover that the problem is actually quite simple. A closer look at this snippet in the PostsController.php reveals how Cake builds in the HABTM relationship to the function, and uses $this->set() in order to pass it to the view (IMPORTANT: using lower-case plural versions "salutations"):
$salutations = $this->Profile->Salutation->find('list', array('fields' => array('Salutation.id', 'Salutation.abbr_name')));
$qualifications = $this->Profile->Qualification->find('list', array('fields' => array('Qualification.id', 'Qualification.abbr_name')));
$this->set(compact('salutations', 'qualifications'));
According to the Cake Cook Book, in order to take advantage of this HABTM in the front end when using the form helper is to specify the variable in singular form & title case (ie: "Salutation")
Snippet from the cook book:
Assuming that User hasAndBelongsToMany Group. In your controller, set a camelCase plural variable (group -> groups in this case, or ExtraFunkyModel -> extraFunkyModels) with the select options. In the controller action you would put the following:
$this->set('groups', $this->User->Group->find('list'));
And in the view a multiple select can be created with this simple code:
echo $this->Form->input('Group');
Should solve your issue without any necessary field tweaking.
Cheers!
Bake on.
Perhaps you need further configuration of your input:
echo $this->Form->input('Qualification',array(
'label' => 'Qualifications',
'type' => 'select',
'multiple' => true, // or 'checkbox' if you want a set of checkboxes
'options' => $qualifications,
'selected' => $html->value('Qualification.Qualification'),
));
I've used this blog post whenever I've come up against HABTM associations. It seems to me that a set of checkboxes maybe desired by default over a select input - maybe someone with greater CakePHP insight can chime in here?
Change
echo $this->Form->input('qualification');
to
echo $this->Form->input('qualification', array(
'multiple' => true
));
The CakePHP manual has more information on the form helper input options.

Validation problems with multiple checkboxes (HABTM) on CakePHP form

Short version
I have some HABTM checkboxes on a form. Validation is working correctly (at least one checkbox needs to be checked for validation to pass) but the CakePHP error message divs aren't being generated as they should be.
Long Version
I have a from which allows users to fill in their name and email address and then choose from a list of brochures (checkboxes) they'd like to receive.
The form looks like this:
<?php
echo $this->Form->create('Request',array('action' => 'index'));
echo $this->Form->input('id');
echo $this->Form->input('name');
echo $this->Form->input('email');
echo $this->Form->input('Brochure',array(
'label' => __('Information Required:',true),
'type' => 'select',
'multiple' => 'checkbox',
'options' => $list,
'selected' => $this->Html->value('Brochure.Brochure'),
));
echo $this->Form->submit('Submit');
echo $this->Form->end();
?>
In my controller, $list is set as like this:
$this->Request->Brochure->find('list',array('fields'=>array('id','name')));
After reading the 2nd answer (posted by user448164) in HABTM form validation in CakePHP on Stack Overflow, I set my Request model up like this:
<?php
class Request extends AppModel {
var $name = 'Request';
function beforeValidate() {
foreach($this->hasAndBelongsToMany as $k=>$v) {
if(isset($this->data[$k][$k]))
{
$this->data[$this->alias][$k] = $this->data[$k][$k];
}
}
}
var $validate = array(
'name' => array(
'rule' => 'notEmpty',
'message' => 'Please enter your full name'
),
'email' => array(
'rule' => 'email',
'message' => 'Please enter a valid email address'
),
'Brochure' => array(
'rule' => array('multiple', array('min' => 1)),
'message' => 'Please select 1'
),
);
?>
This actually works 99% well. If none of the checkboxes are checked, validation fails as it should do. However, the only problem is that Cake isn't setting the "error" class on the <div>, nor is it creating the <div class="error-message">Please select 1</div> as it should.
For name and email, there is no problem - the error divs are being created properly.
So, to clarify, validation is working for my HABTM checkboxes. The only problem is that the error divs aren't being generated.
I'm posting this here as this is actually a much better question than the related question you found.
I was banging my head against a wall trying to handle the same problem of getting the validation error to show up in the page. I'm using CakePHP v1.2 and I hit a similar problem although I have actually split out the HABTM into the individual tables i.e. Request->BrochuesRequest->Brochure. This is because I can't have it deleting and re-adding the joining table rows at will.
Firstly I think the accepted answer from your linked question assumes that you are doing a save / saveAll when the beforeValidate call is triggered, however I was doing it through a validates call. The difference is that you need to call the Request->set method first. It was an article by Jonathan Snook on Multiple Validation Sets pointed me to that issue.
The second issue is actually getting the error message to appear was down to the $field value you use when calling invalidate. For ages I was including the model as well as the field assuming that this was how it matched the invalidate call to the input, i.e. you have $form->input('BrochuresRequest.brochures_id') so you need $this->BrochuresRequest->invalidate('BrochuresRequest.brochures_id').
However that is wrong you just want $this->BrochuresRequest->invalidate('brochures_id').
<?php
// requests/add view
echo $form->input('BrochuresRequest.brochures_id', array('multiple' => true));
// requests_controller
function add() {
if (!empty($this->data)) {
$this->Request->create();
// critical set to have $this->data
// for beforeValidate when calling validates
$this->Request->set($this->data);
if ($this->Request->validates()) {
$this->Request->saveAll($this->data);
}
}
}
// request model
function beforeValidate() {
if (count($this->data['BrochuresRequest']['brochures_id']) < 1) {
$this->invalidate('non_existent_field'); // fake validation error on Project
// must be brochures_id and not BrochuresRequest.brochures_id
$this->BrochuresRequest->invalidate('brochures_id', 'Please select 1');
return false;
}
return true;
}
?>
A few of the other things that I picked up on the way through:
You don't need a separate $form->error in the view
I couldn't for the life of me get the 'multiple' validation rule to work in the model
The accepted answer checks for an isset but I believe that this isn't required and masked the problem of there being no $this->data being passed through.
The beforeValidate should return false if you want it to prevent any save action.

CakePHP - radio button not showing error message

I'm unable to get the error message to show up when creating a radio form using the CakePHP form helper.
This is what I have now.
$options=array('active'=>'Active','inactive'=>'Inactive');
echo $form->input('Status', array(
'type' => 'radio',
'id' => 'EntryStatus',
'name' => 'data[Entry][status]',
'options' => $options
));
What am I missing?
I'm using CakePHP 1.2.7 and this is what I have in the validation
'status' => array(
'notempty' => array(
'rule' => 'notempty',
'required' => true,
'message' => 'yo'
)
)
Tried the answer from Form helper for creating Radio button in Cakephp and it's giving me a select option form instead.
Thanks,
Tee
had same problem, and i fount this, and it works:
http://book.cakephp.org/view/204/Form-Element-Specific-Methods
you need
if ($form->isFieldError('gender')){
echo $form->error('gender');
}
... in your code. this works in case that your field is named as gender.
I had the same issue and I added:
<?php echo $form->error('currentStatus');?>
below the radio button and it worked fine.
Try taking a look at $form->input('Status' ... (capital 'Status') versus the DB column name (which might or might not be capitalized versus 'name' => 'data[Entry][status]' (not capital 'status').
Cake's form helper is picky about inserting error messages when it can't figure out what things go to what.
Have you tried using the explicit $form->radio() method instead of the general input() method?
You need to manually add in an error form helper.
echo $form->error('status');
You need to add error condition in case of radio button
<?php
$options=array('active'=>'Active','inactive'=>'Inactive');
echo $form->input('Status', array(
'type' => 'radio',
'id' => 'EntryStatus',
'options' => $options
)
);
if ($form->isFieldError('Status')){
echo $form->error('Status');
}
?>

Resources