There is a table location containing city and name columns.
Query is:
$count=$this->Location->find("all",array("conditions" => array("Location.city" => '$city',"Location.area" => '$location')));
If condition becomes true, it has to show an error message.
In Model
role=>"unique"
option is there, but it is for only one column.
But in above query its depends on two columns. How to write validation for this?
Have you tried to read the documentation?
You can validate that a set of fields are unique by providing multiple fields and set $or to false:
public $validate = array(
'email' => array(
'rule' => array('isUnique', array('email', 'username'), false),
'message' => 'This username & email combination has already been used.'
)
);
Make sure to include the original field in the list of fields when making a unique rule across multiple fields.
If a listed field isn’t included in the model data, then it’s treated as a null value. You may consider marking the listed fields as required.
You can simple define a validation for the city field in the City model.
public $validate = array(
/* Other fields */
...................
'city' => array(
'rule' => array('isUnique', array('city', 'area'), false),
'message' => 'City and area combination already exists.'
)
);
Related
Tables
User(id)
Profile(id, *user_id*, type)
Attribute(id, *attribute_name_id*, value)
AttributeName(id, name)
ProfileAttribute(id, *profile_id*, *attribute_id*)
Relationships
The relationships are set up correctly (and go both ways, hasMany/belongsTo).
User hasMany Profile
Profile hasMany ProfileAttribute
Attribute hasMany ProfileAttribute
(could be written Profile hasMany Attribute through ProfileAttribute)
AttributeName hasMany Attribute
Goal
For a specified User id, with a find() in the User model, I only want the following fields, laid out as such:
$results[Profile.type][AttributeName.name][Attribute.value]
Is it even possible to retrieve results arranged like this? I've been playing around with Find and Containable for hours, but, first time trying to do anything complicated like this with Cake, I can't get the hang of it.
Thanks!
EDIT
I'm getting these results now, all that I need, but nowhere near the desired format above -can it be done as part of the find, or does it need to be sorted after?
Yep, it's possible. You just have to specify fields on containable:
$this->User->find('all', array(
'conditions' => array('User.id' => $id),
'fields' => array('id'),
'contain' => array(
'Profile' => array(
'fields' => array('id','type'),
'ProfileAttribute' => array(
'fields' => array('id'),
'AttributeName' => array(
'fields' => array('id','name'),
'Attribute' => array(
'fields' => array('id','value')
)
)
)
)
)
);
Be wary that when you use contain and fields options, you have to specify the id so it can make the association (check the docs)
EDIT: I don't know if you can group contained data as the docs didn't say anything about that, but probably you can, as they accept some parameters as in the main query. You can try it, adding group to any contained data that you want to group
Here is Yet another cakePHP question! I have table called blood_groups which has blood_group_id and group fields.. Then I have another table called donors, which has several fields such as name, surname etc. Another field included inside this table is the foreign key 'blood_group_id' which will need to map to the blood_group table on retrieval. in the donor registration view, i want to be able to retrieve the values from the blood_groups table, and display them using the formHelper (with their respective id's).
I have gone through CAKE doc, and I understand that I would need to create the association between my models, but I am struggling to figure this one out. Should I create $hasOne association inside the Donor Model (considering that the Donor table has the fk of the other table). And how would I go about retrieving the options of blood_groups from the blood_groups Model?
Should It work like this?(and are any other prerequisites involved?) :
In my DonorController -
$this->set('blood_groups', $this->Donor->Blood_Group->find('all'));
in Views/Donor/add.ctp
echo $this->Form->input('blood_group_id');
Accessing data through associations is fine. But for radios or checkboxes you want to do a find('list). Your model and variable name does not match the CakePHP convention, there should be no underscore.
Properly named this should be already enough to populate the input.
// controller
$this->set('bloodGroups', $this->Donor->BloodGroup->find('list'));
// view
echo $this->Form->input('blood_group_id');
If you don't follow the conventions for some reason:
echo $this->Form->input('blood_group_id', array(
'options' => $bloodGroups
));
See:
Linking Models Together
The Form Helper
Create one function in BloodGroup Model
function getDonors(){
$options = array(
// 'conditions' => array('Donor.blood_group_id'=>$id),
'joins' => array(
array(
'alias' => 'Donor',
'table' => 'donors',
'type' => 'LEFT',
'conditions' => array(
'Donor.blood_group_id = BloodGroup.blood_group_id',
),
)
),
'fields' => array('Donor.name','Donor.surname','Donor.blood_group_id',
'BloodGroup.blood_group_id')
);
$returnData = $this->find('all',$options);
return $returnData;
}
Now from controller call this function
App::import('model','BloodGroup');
$BloodGroup = new BloodGroup;
$donorList = $BloodGroup->getDonors();
$this->set('donorList',$donorList);
In view file you will get list of donors in $donorList.
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.
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.
I have a list of ordered items, ordered according to the int field order.
I'm creating a gallery in CakePHP 1.2 that has a prev and next button and those should link to the previous and next item according to their ordering, not according to their id.
In order to get this result I've included the 'order' parameter to the find function, and populated it with 'Item.order'=>'DESC'. Still the result is an id ordered list.
My question is: what do I do wrong?
My controller:
$this->Item->id = 16;
$neighbours = $this->Item->find('neighbors', array(
'order' => array('Item.order'=>'DESC'),
'fields' => array('id','name')
));
My Solution
I've tried a different approach. My code now does the job and looks as follows:
$order = $this->Item->findById(6);
$neighbours = $this->Item->find('neighbors', array(
'field' => 'order',
'value' => $order['Item']['order']
));
By setting the parameter 'field' to the field will be the ordering field, and set the 'value' parameter to the order value of you current Item you'll get the prev and next.
Yeah the problem was that you weren't including the order field in your fields array.
$neighbours = $this->Item->find('neighbors', array(
'order' => 'order DESC',
'fields' => array('id', 'name', 'order')
));
Unless you have related models with conflicting field names you don't need to include the Item. model prefix (though I usually do anyway to avoid such errors.) You're original syntax would work if you had included [Item.]order in "fields"
Finally, your solution is not optimal, you're making two SQL queries when you don't need to. and 'field' is not a query option as far as I'm aware which actually means you're returning all of the fields in the table.
I was having problems with this. Basically I have a list of questions that need to be randomly ordered (once only) per user session.
I was setting the order of the model to something like this:
'FIELD(TestQuestion.id, 3, 1, 5)';
This worked fine for normal queries, but finding neighbors is stymied by line 2897 in Model.php:
$query['order'] = $field . ' DESC';
So to get around it, I did the following:
Add a virtual field called 'examination_order', and set the order to that:
$this->TestQuestion->virtualFields['examination_order'] = 'FIELD(TestQuestion.id, 3, 1, 5)';
$this->TestQuestion->order = array(
$this->TestQuestion->alias . '.examination_order'
);
In the find neighbors call, set the 'field' to 'examination_order', with the value set to the index as found previously:
$neighbors = $this->TestQuestion->find(
'neighbors',
array(
'field' => 'examination_order',
'value' => $testQuestion[$this->TestQuestion->alias]['examination_order'],
'conditions' => $conditions
)
);