cakephp date 'dmy' validdation is not working - cakephp

I want to validate with dmy format. Here is what I wrote in my model:
'birthdate' => array(
'date' => array(
'rule' => array('date','dmy'),
'message' => 'Solo data valida',
'allowEmpty' => true,
)
)
However, when I submit the form with the date, I get an error.

One thing you should verify is the value of "birthday" DIRECTLY PRIOR to validation. Try debugging $this->request->data in your controller before calling $this->Model->save, or $this->Model->validate. It's quite possible that you are transforming that date value before you pass it to validation, and thus it could be failing.
For instance, I typically use a beforeSave, and afterFind callback to transform dates going into and coming from MySQL, or you may have something in your appController or beforeFilter callback that's inadvertently transforming the data.

Related

Saving a model with no data in CakePHP (just create id in db)

My CakePHP Cart model/table has only one field: id.
It hasMany LineItems.
I am not having success saving the Cart model alone:
$this->Cart->create();
$this->Cart->save();
Or, by passing it a $data array structured as follows and using saveAssociated():
$data = array(
'Cart' => array(),
'LineItem' => array(
array(
'item_id' => $item_id,
'qty' => $qty,
'price_option_id' => $price_option_id
)
)
);
If I add a useless_field to the Cart table/model, and pass some data in it saves. So obviously the problem lies in my having a model with a table with just a single id field and not passing in any other data to save. It won't create what it must be assuming is an 'empty' record.
I have passed 'validate' => false into the saveAssociated call but it doesn't make a difference (and there are no validations for this model to ignore).
Is there a way to do this? Am I missing something? Please enlighten me!
CakePHP tables require created and modified fields, or for you to define your own fields (ie you can call them whatever you want but they do the same thing).
In this instance you would use
$this->Cart->set($data);
$this->Cart->saveAll();

CakePHP validation on => 'create', on => 'update'

I'm hoping you cakephp experts can answer this re Cake 2.1 and data validation in the model.
Cake gives you an "on" key for use in the validate array. I understand what the docs say about this but my question is, what's the point of these two items.
Let's say I have a validation rule for when a record is created. The validation passes and the record is created.
Then the user goes and edits that record and changes it to something that no longer passes that particular validation. But since I've got my validation set to run on create only, the validation passes and the record is updated with invalid data. It seems to me like this would apply to any on create / on update rules. If a user wanted to bypass validation, just create a valid record, then go and edit it so it's now invalid.
Can someone perhaps help me understand when it might make sense to use on update and on create?
This is most useful in conduction with the required rule. You should set certain fields that are minimally required to be required 'on' => 'create'. This makes the rule fail if those fields don't exist in the data set and the record cannot be created, but allows you to update existing records without having to pass that field each and every time.
For example:
'email' => array(
'required' => array(
'on' => 'create',
'rule' => 'notEmpty',
'message' => 'Enter your email address',
'required' => true,
'last' => true
),
'notempty' => array(
'rule' => 'notEmpty',
'message' => 'Enter your email address',
'allowEmpty' => false,
'last' => true
),
'email' => array(
'rule' => 'email',
'message' => 'Not a valid email address',
'last' => true
)
)
I found it really useful in cooperation with profile pictures. You need one to be uploaded on create (if it is needed), but on update i can remain empty => no update to picture will be done.
'on' => null will do the job
EDIT :
Ok, let's say you have a Profile model.
If you have a Date of Birth field, you would probably use a rule that would be enforced for both addition and edition.
You might also add a delete_picture checkbox in your form that a user should select in order to delete their profile picture. When adding, you have no profile picture so this field is only relevant at edition time and you would then use on => update.
Let's say you also have a group field that is set when you create the object but that is meant to never be changed. You would then use on => create.

Having trouble with the CakePHP data validation

i'm currently having some issues by using the cakePHP data validation.
I've tried to use the rule with the argument 'on' => 'created' but it didn't seems to work.
My objective is to check during the creation of the user, to check if the mail is not already existing in my database.
But when it's a edit, i don't want to check this, i mean, if the user don't change the mail, obviously this mail is already existing in the database, but it's just the same then before...
So i don't want to check if the mail, have not been changed.
'mail' => array(
'valid_mail' => array(
'rule' => array('email', true),
'message' => 'Veuillez insérer un email valide.'
),
'isUnique_mail' => array(
'rule' => 'isUnique',
'on' => 'create',
'message' => 'Ce mail est déjà utilisé.'
)
)
Hope you guys understand my problem.
Part of your problem might be that you're not specifying the ID of the record that needs to be saved using $this->Model->id = $id so when you call the save (or saveAll) function, it's trying to insert a record.
The isUnique validation function actually will filter out the ID of the current record when updating if it's been set using $this->Model->id. You can see this at the bottom of the function (line 2446).
Personally, I'd leave the isUnique validation on all the time to prevent users from changing their emails to one that already exists once they've registered.

What is the best way to process complex datatypes in CakePHP?

My Goal: Replace the Default Cake Datepicker
I hate the default CakePHP FormHelper date-picker select elements and I'd like to use jQuery UI Datepicker widget instead. In order to degrade gracefully, I want to have a date field (enabled with the widget) and a time-picker select box constrained to 15-minute increments.
In case I explained that poorly, here is what it looks like:
My Ideal Solution
To minimize repetition, I want to put the HTML in a layout Element and process it using a Behavior function. This way I could do something like the following:
view.ctp
echo $this->element( 'datepicker', array( 'data' => $data ) );
model.php
$actsAs = array( 'Datepicker' );
function beforeSave( $options ){
$this->parseDatepickers(); //behavior function would alter $this->data
return true;
}
The Problem
Unfortunately, by the time it gets to the beforeSave (or beforeValidate) callback, the datepicker & timepicker fields have been destroyed by the model's deconstruct function. deconstruct seems to be looking for dates & times to be reported the way FormHelper creates them.
In short, it's looking for:
[date_field] => Array
(
[year] => 2011
[month] => 11
[day] => 11
[hour] => 8
[min] => 00
[meridian] => pm
)
but instead it's finding:
[date_field] => Array
(
[datepicker] => 11/11/2011
[timepicker] => 8:00 pm
)
And because it doesn't find the structure it expects, I end up with this:
[date_field] =>
I know I can have jQuery update hidden inputs with the appropriately-named fields, but this wouldn't degrade well.
Current Workaround
What I'm doing, for the moment, is washing the data through my behavior function prior to saving -- but this doesn't feel like the right way to do it:
$this->request->data = $this->Event->fixDates( $this->data );
$this->Event->save( $this->data );
So...............
What is the best way to do this? Putting it in beforeSave or beforeValidate seems like "the Cake way", but deconstruct kills me. Do I need to extend AppModel and override deconstruct? That seems ugly too.
I normally make my date fields as text fields in the view to override the default Form Helper output and then use jQuery date picker (or whatever your alternative picker would be) to set the date:
echo $this->Form->input('date', array('type' => 'text', 'class' => 'datepicker'));
This would output a typical tag rather than all the drop downs.
Then, in my model's beforeSave function, I change the format to MySQL formatted date:
$this->data['Model']['date'] = date('Y-m-d G:i:s', strtotime($this->data['Model']['date']));
(remember to return true in beforeSave)
This works with a proper datetime datatype in the database and it sounds like what you are trying to do.

CakePHP AutoComplete Question

I am working on a book review application and I am using autoComplete to search for titles in when creating a review. The review model has an associated book_id field and the relationship is setup as the review hasOne book and a book hasMany reviews.
I am trying to pass the Book.id (into the book_id field), but I want to display Book.name for the user to select from. With the default setup (accomplished via CakePHP's tutorial), I can only pass Book.name. Is it possible to display the name and pass the id?
Also, I am passing it via the following code in the create() action of the review controller:
$this->data['Review']['book_id'] = $this->data['Book']['id'];
Is that the proper way to do it in CakePHP? I know in Ruby on Rails, it is automatic, but I can't seem to make it work automagically in CakePHP. Finally, I am not using the generator because it is not available in my shared hosting environment... so if this is the wrong way, what do I need other than associates in my models to make it happen automatically?
Thanks for the help and I promise this is my question for awhile...
UPDATE- I tried the following, but it is not working. Any ideas why?
function autoComplete() {
$this->set('books', $this->Book->find('all', array(
'conditions' => array(
'Book.name LIKE' => $this->data['Book']['name'].'%'
),
'fields' => array('id','name')
)));
$this->layout = 'ajax';
}
The problem is that when I use the code above in the controller, the form submits, but it doesn't save the record... No errors are also thrown, which is weird.
UPDATE2:
I have determine that the reason this isn't working is because the array types are different and you can't change the array type with the autoComplete helper. As a workaround, I tried the follow, but it isn't working. Can anyone offer guidance why?
function create() {
if($this->Review->create($this->data) && $this->Review->validates()) {
$this->data['Review']['user_id'] = $this->Session->read('Auth.User.id');
$this->Book->find('first', array('fields' => array('Book.id'), 'conditions' => array('Book.name' => $this->data['Book']['name'])));
$this->data['Review']['book_id'] = $this->Book->id;
$this->Review->save($this->data);
$this->redirect(array('action' => 'index'));
} else {
$errors = $this->Review->invalidFields();
}
}
FINAL UPDATE:
Ok, I found that the helper only takes the find(all) type or array and that the "id" field wasn't passing because it only applied to the autoComplete's LI list being generated. So, I used the observeField to obtain the information and then do a database lookup and tried to create a hidden field on the fly with the ID, but that didn't work. Finally, the observeField would only take the characters that I put in instead of what I clicked, due to an apparent Scriptaculous limitation. So, I ended up going to a dropdown box solution for now and may eventually look into something else. Thanks for all of the help anyway!
First of all, $this->data will only contain ['Book']['id'] if the field exists in the form (even if it's hidden).
To select something by name and return the id, use the list variant of the find method, viz:
$selectList = $this->Book->find('list', array(
'fields' => array(
'id',
'name'
)));
$this->set('selectList', $selectList);
In the view, you can now use $selectList for the options in the select element:
echo $form->input('Book.id', array('type' => 'hidden'));
echo $form->input('template_id', array(
'options' => $selectList,
'type' => 'select'
));

Resources