Cake PHP validation, change incoming $data - cakephp

I got a problem with my cake validation.
The user enters e.g. "20€" in a form field and I only want to get the number "20" with stripped out Euro-sign. But the validation methods only allow checking if something is what it´s supposed to be.
I´m about to create a function in my rule-set but I´m struggling going further because what the function returns in cake context is either true or false, not a modified variable like I need ...
'rule-3' => array(
'rule' => 'checkEuro',
'message' => 'don´t need one because it should be a conversion only :-('
)
public function checkEuro($data) {
$data = str_replace('€','',$data);
return preg_replace('/[^0-9]/','', html_entity_decode($data));
}
I hope you can help.
Thanks in advance

If you only need to store the amount itself inside the database and not the euro-sign, you should strip the Euro-sign before validating.
You can do this inside the beforeValidate() callback of your model;
public function beforeValidate(array $options = array())
{
if (!empty($this->data[$this->alias]['FIELDNAME']) {
// Strip the euro-sign
// NOTE: should also take plain, non-entity € into account here?
$this->data[$this->alias]['FIELDNAME'] = str_replace(
'€', '', $this->data[$this->alias]['FIELDNAME']
);
}
return parent::beforeValidate($options);
}
(Of course, replace FIELDNAME with the actual fieldname)
After stripping the currency-symbol, validate the value using the decimal or numeric validation rule
note
If you do want to store the value including the currency-symbol, use the core money validation rule.

Related

Can I pass multiple parameters to a custom validation function in cakephp

I'm using cakephp 2.8.0. I have a custom validator function and I want to pass it 3 parameters. The first is obviously the $check, but the 2nd and 3rd are just some text to validate against. The second parameter comes through fine, but the third parameter always ends up being some array, when it should just be a string. Here's my validation rule and the function:
public $validate = array('commit_positions_funding_explain' => array(
'check_empty_dependent' => array(
'rule' => array('check_empty_dependent', 'commit_positions_auth', '0'),
'message' => 'Please select an option',
)
),);
public function check_empty_dependent($check, $parent, $another){
//$another should be 0 but instead its an array that looks like the
//the validate array
//do some stuff
return true;
}
Any ideas on why that 3rd parameter is not working are greatly appreciated.
It appears that this array value was happening when I didn't pass that third parameter. The parameters for these validation functions cannot be optional. When I made sure that all validation rules calling this function were passing some value for $another, then everything worked fine.

cakephp 2.x limit the number of records(behavior or model callback method)when add new record

I am relativly new in cakephp and i have never been writing behavior.
So i need to limit the number of records of a model,what i know it must be done with beforeSave
Models: Document | DocumentType . Document->DocumentType
I store the maximal number of document in the DocumentType.
Thats why i am bit confused what i need exactly a model behavior or a callback method(beforeSave) by model.
But i dont know how does this will work with the two model.I began the behavior:
class LimiteBehavior extends ModelBehavior
{
public function beforeSave(Model $Model,$options=array())
{
}
i call this by the modell:
public $actsAs=array('Limite');
Is this right or should i pass here extra infos?
But now i am confused because i dont know how to use different models in the behavior now.
I have to count the number of Document model records:
$this->Document->find('count')
I have to check the maximal number of DocumentType:
$this->DocumentType->find->('first',array('fields'=>array('max_record')))
Now i have to compare this in the Behavior.But i don't know more how to do.
Please help.
Update1:
I don't want to let the user more insert new record when the max_record field is equal with the number of current records
I would recommend creating a custom validation rule in your model. This validation rule could check the number of items based on your conditions and fail to save based on that rule.
Read more about custom validation methods in the book.
I would try and make a rule something like this,
<?php
class Document extends AppModel {
public $validate = array(
'document_type_id' => array(
'rule' => 'limitDuplicates',
'message' => __('Maximum number of documents of this type already created')
)
);
public function limitDuplicates($check) {
$max = $this->DocumentType->field('max_record', ['DocumentType.id' => $check['document_type_id']]);
$count = $this->DocumentType->find('count', [
'conditions' => [
'DocumentType.id' => $check['document_type_id']
]
]);
return $count < $max;
}
}

cakephp beforesave question

I follow in book.cake and I don't know I should send something to the parameters.
function beforeSave() {
if (!empty($this->data['Article']['create_dt']) && !empty($this->data['Article']['modified_dt'])) {
$this->data['Article']['create_dt'] = $this->dateFormatBeforeSave($this->data['Article']['create_dt']);
$this->data['Article']['modified_dt'] = $this->dateFormatBeforeSave($this->data['Article']['modified_dt']);
}
return true;
}
I try to search example but don't found.
I need many example
somebody can help me to find big resource
thank for suggest
beforeSave is called automatically by Cake before it saves data. In it, you can do whatever you want to do before each save. Typically this means altering $this->data, which is the data that is about to be saved.
The method is passed one parameter: an array of the form array('validate' => true/false, ('fieldList' => array(...)). This corresponds to the two extra parameters you can supply to save():
$this->Model->save($this->data, false, array('foo', 'bar'));
In this case the array would look like
array('validate' => false, 'fieldList' => array('foo', 'bar')).
You can accept this array by specifying an argument:
public function beforeSave($options) { ... }
$options will look like described above. You can use this information any way you want.
If you don't return true from beforeSave, the save operation will be canceled altogether.
That's all.
try using created and modified magic fields with datetime type in table cake would automatically handle them
i want to mention, that beforeSave() should be used carefully, because it is used on every time when data is saved with this model.
if you forget that it is used, you will get unexpected results.
Happens to me several times... ;)

save() returning false, but with no error in CakePHP

My debug value is set to 2, and it's displaying all the queries, except the one I need.
I have an Items controller method that is calling this method in the User model (Item belongsTo User):
function add_basic($email, $password) {
$this->create();
$this->set(array(
'email' => $email,
'password' => $password
));
if($this->save()) {
return $this->id;
}
else {
return false;
}
}
I have confirmed that $email and $password are being passed into the function correctly (and are populated with legit data). email and password are the names of the fields in the User model.
I have also confirmed that on $this->save() it is returning false, but when I view the page where this occurs, the query is not being printed in the debug, and there is no error being thrown, so I have no idea whats going wrong.
Any ideas on how I can see the error, or why the query doesn't seem to be getting executed?
It's weird, cause right after this, I have another model saving data to it in the exact same fashion, it goes off without a hitch.
This will probably give you the info you need (assuming it's not saving because of invalid data, of course):
if(!$this->save()){
debug($this->validationErrors); die();
}
Have you got a beforeValidate() or beforeSave() method in the model or app model? Ifso, are they returning true? Failing that, use a debugger, set a break point in your IDE at the top of cake/libs/models/model.php save() method and step through the code until it returns false. Failing that add die('here'); calls.
Try this:
if ($this->save()) {
return $this->id;
}
else {
var_dump($this->invalidFields());
return false;
}
#cakePHP 3.6 and above: By default, the request data will be validated before it is converted into entities. If any validation rules fail, the returned entity will contain errors. It can be read by getErrors() method.
The fields with errors will not be present in the returned entity:
Say, you have an entity
use App\Model\Entity\Article;
$entity = $this->ModelName->newEntity([
'id' => 1,
'title' => 'New Article',
'created' => new DateTime('now')
]);
$result = $this->ModelName->save($entity);
\Cake\Log\Log::debug($entity->getErrors());
If you’d like to disable validation when converting request data, set the validate option to false:
$article = $articles->newEntity(
$this->request->getData(),
['validate' => false]
);
Ref: https://book.cakephp.org/3/en/orm/validation.html
Make sure to check your tables:
Does ID have auto increment enabled?
Is id your primary key?
the auto_increment issues killed me.
Easy way to check: if any of your rows have ID = 0, auto_increment is likely disabled.
CakePHP 3.6
$entity = $this->Model->newEntity([
'account_id' => $id,
'gallery_id' => $gallery_id
]);
$result = $this->Model->save($entity);
print_r($entity->getErrors());
The other situation where CakePHP fails to report any $this->Model->validationErrors and no other errors is potentially when $this->request->data isn't as Cake expects and is simply ignoring your data, not saving, no validation errors. For example if your data was provided by DataTables you might see this format $this->request->data[0]['Model']['some_field'].
$this->Model->save($this->request->data[0]) will work however.

Making one of a group of similar form fields required in CakePHP

I have a bunch of name/email fields in my form like this:
data[Friend][0][name]
data[Friend][1][name]
data[Friend][2][name]
etc.
and
data[Friend][0][email]
data[Friend][1][email]
data[Friend][2][email]
etc.
I have a custom validation rule on each one that checks to see if the corresponding field is filled in. Ie. if data[Friend][2][name] then data[Friend][2][email] MUST be filled in.
FYI, heres what one of the two rules look like:
My form validation rule: ( I have an email validation too but that's irrelevant here)
'name' => array(
'checkEmail' => array(
'rule' => 'hasEmail',
'message' => 'You must fill in the name field',
'last' => true
)
)
My custom rule code:
function hasEmail($data){
$name = array_values($data);
$name = $name[0];
if(strlen($name) == 0){
return empty($this->data['Friend']['email']);
}
return true;
}
I need to make it so that one of the pairs should be filled in as a minimum. It can be any as long as the indexes correspond.
I can't figure a way, as if I set the form rule to be required or allowEmpty false, it fails on ALL empty fields. How can I check for the existence of 1 pair and if present, carry on?
Also, I need to strip out all of the remaining empty [Friend] fields, so my saveAll() doesn't save a load of empty rows, but I think I can handle that part using extract in my controller. The main problem is this validation. Thanks.
I would have a look at the Model::beforeValidate callback (API).
Using this callback to output debug information should help you figure out how many times it fires and what data is available to the model on each call.
With this information, you could then create a flag when you find your first matching pair, and tamper with either the Model::validates array or the Model::data array to bypass subsequent validation attempts.
As for your last point, you may be able to use Set::filter to easily remove blank fields from your data set.

Resources