2 fileds in a table associated to the same table - cakephp

how can I display values from an over a JOIN table associated table in cakePHP?
I tried the following:
echo $post['Post']['user_id'] // displays e.g. '4'
but then I only get the id not the defined $displayfield of the user model.
It works when I use the association in an input field like:
echo $this->Form->input('user_id', array( 'label' => 'User'); // displays 'Mr. Oizo'
The virtualField is defined in the user model as follows:
public $virtualFields = array(
'VirtualName' => 'CONCAT(User.Name, " ", User.Vorname)'
);
public $displayField = 'VirtualName';
Can anyone help me ?
Best regards
dan

If you have the relationships defined between models correctly, you would display the User virtual field like this in your view:
echo $post['User']['VirtualName']

Related

how to validate country name in cakephp

I have two tables, profiles and regions.
in regions table I have list of all countries name. and in profiles table I have profile for my users and one of the field in that table in 'country'
Previously I was giving users an input box to enter country name but recently I noticed that few people are entering wrong information there. One guy entered 'jupiter' as his country name.
now what I wanna do is in my Profile model is something like this:
'country must exist' => array(
'rule' => 'countryValidation',
'message' => 'There is no such country'
)
public function countryValidation($check) {
$country = strtolower($this->data['Profile']['country']);
$countries = array();
$regions = $this-Region->find('all');
foreach($regions as $region){
array_push($countries, strtolower($region['Region']['country']));
}
return in_array($country,$countries);
}
and I am sure that the problem here is with
$regions = $this-Region->find('all');
What's the correct way to validate country?
BTW, I can't give a drop down list of country because it mess up with my layout/website design.
What you're looking to do is a bad idea, as you can't guarantee that end users will spell the names of the countries correctly etc.......
At any rate, create a custom function in your model
public function myFunction($countryName){
return in_array($countryName,$countriesList);
}
where $countriesList is an array of country names.
In the model validation you can do the following
public $validate = array(
'country' => array(
'rule' => 'myFunction',
'message' => 'Insert custom message here'
)
);
EDIT:
Then I would create a custom find function in the Region model, and call it from the current model to retrieve an array of results for validation. Something like:
$countriesList = $this->Region->customFunction();
or $countriesList = $this->Region->find('list);
Check this to use a model in another model
App::uses('Model', 'Region');
$Region = new Region();
$regions = $Region->find('all');

Editing associated models data in cakephp

I'm using CakePHP 2.3.6. I have some Models in my project, which are associated and I defined the association explicitly. Now, I have an Edit form, where I retrieve all the models data, and trying to edit those data in the corresponding models. But, edition is not happening, instead, new rows are created in the associated tables.
Here is my associations among the models :
in the model User.php :
public $hasMany=array('Education'=>array(
'className'=>'Education
'foreignKey'=>'user_id'
),
'Experience'=>array(
'className'=>'Experience',
'foreignKey'=>'user_id'
),
'Employment'=>array(
'className'=>'Employment',
'foreignKey'=>'user_id'
),
'ProfessionalQualification'=>array(
'className'=>'ProfessionalQualification',
'foreignKey'=>'user_id'
)
)
in the model Education.php :
public $belongsTo=array('User'=>array(
'className'=>'User',
'foreignKey'=>'user_id'
)
)
in the model Experience.php
public $belongsTo=array('User'=>array(
'className'=>'User',
'foreignKey'=>'user_id'
)
)
in the model Employment.php :
public $belongsTo=array('User'=>array(
'className'=>'User',
'foreignKey'=>'user_id'
)
)
in the model ProfessionalQualification.php :
public $belongsTo=array('User'=>array(
'className'=>'User',
'foreignKey'=>'user_id'
)
)
Now, in the Edit form (View/Users/edit.ctp) :
echo $this->Form->create('User');
echo $this->Form->input('User.name');
echo $this->Form->input('User.username');
echo $this->Form->input('User.password');
echo $this->Form->input('User.address');
echo $this->Form->input('User.phone');
echo $this->Form->input('Education.0.degree');
echo $this->Form->input('Education.0.passing_year');
echo $this->Form->input('Experience.0.title');
echo $this->Form->input('Experience.0.description');
echo $this->Form->input('Employment.0.company');
echo $this->Form->input('Employment.0.description');
echo $this->Form->input('ProfessionalQualification.0.certificate');
echo $this->Form->input('ProfessionalQualification.0.description');
echo $this->Form->submit('Save');
echo $this->Form->end();
in the UsersController.php controller :
public function edit(){
$this->set('title_for_layout','Edit CV');
if(!AuthComponent::user('id'))
throw new NotFoundException(__('Invalid User'));
$user=$this->User->findById(AuthComponent::user('id'));
if(!$user)
throw new NotFoundException(__('Invalid User'));
if($this->request->is('post') || $this->request->is('put')){
if(!$this->User->saveAll($this->request->data)){
$this->Session->setFlash('Sorry, your info could not be saved. Please, try again.');
$this->redirect(array('action'=>'edit'));
}
}
if(!$this->request->data)
$this->request->data=$user;
}
Here, I am trying saveAll() function on User model. I Also tried using save() & saveAssociated() functions, but same result. It doesn't change the corresponding rows in the tables, instead, it creates a new row in all tables, accept the users table, this table successfully gets the new values and updates the values.
What should I do ? Please help me.
Thanks
Here is a way to make it works (in theory) but I'm not sure it's the best and, it's not "secure": Adding the id for related field in your form, with hidden field, like so:
echo $this->Form->create('User');
echo $this->Form->hidden('User.id');
echo $this->Form->input('User.name');
/* ... */
echo $this->Form->hidden('Education.0.id');
echo $this->Form->input('Education.0.degree');
/* ... */
echo $this->Form->hidden('Employment.0.id');
echo $this->Form->input('Employment.0.company');
/* ... */
echo $this->Form->submit('Save');
echo $this->Form->end();
You should check in your controller that the id of your associated models match the id of your main model, if not people will be able to edit associated model not linked with their user model.
Edit: This is an edit for further explanation about the discussion in comment.
When you have hasMany relationship, like so:
public $hasMany = array('Experience') ; // In User class
You have to specify ID when saving the relation, if not the Cake engine cannot infer that you want to update a model instead of saving one.
$data = array(
'User' => array(
'id' => 33,
'name' => 'Holt'
),
'Experience' => array(
array(
/* 'id' => 45, */
'name' => 'PHP'
)
)
) ;
$this->User->saveAssociated($data) ;
Here, you know that the User you're refering to is Holt with the id 33, and so you know that the experiences in the following array refers to this user. But, if you don't specify the id field in the Experience array, how the engine would know which experience you're refering to?
If the relation was a belongsTo, it's easy to infer that's the Experience related to user Holt (there is only one Experience per user according to relation belongsTo or hasOne), and by the way you wouldn't have a nested array.
There are different ways to tell the engine you want to update a model, the 2 I use are:
Setting the id value in the data array (like above)
Setting the $this->Model->id value in your controller: This value is implicitely set when you do a $this->Model->read or a $this->Model->find (like you do)
What I'm sure, is that the first option works for associated model (like in the above data array if you uncomment the id), I'm not sure that the second works for associated model, like doing $this->User->Experience->id = ..., you can try it, I cannot check it right now.

CakePHP - Retrieving a list of options from another table, to use with form helper/ before Instering

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.

How to insert multiple entrys

iam new to cake and want to set up a order process where the user could send some recommendations (friends mail adr) to get a discount. each recommendation reduces the price. so i want to have up to 5 recommendation inserts in one step.
recommendation table is like (id, order_id, email)
i extend the order model with recommendations
class Order extends AppModel {
public $hasMany = array(
'Recommendation' => array(
'className' => 'Recommendation',
)
);
in the order controller i have to use the saveall method.
now, how should the order add view look like. if i use
echo $this->Form->input('Recommendation.mail');
it will only save one recommendation, or ? But i would like to have up to 5 of them on one page...
Thank you very much,
Julius
Change your form to this
echo $this->Form->input('Recommendation.0.mail');
echo $this->Form->input('Recommendation.1.mail');
echo $this->Form->input('Recommendation.2.mail');
echo $this->Form->input('Recommendation.3.mail');
echo $this->Form->input('Recommendation.4.mail');
Then in your controller,use the saveAll method
$this->Recommendation->saveAll($this->request->data);

cakephp multiple select validation

I am using CakePHP and i have something like:
PRODUCT -------> PRODUCT_CATEGORY <---------- CATEGORY
so one product can have 'n' categories and viceversa.
The problem is that i would like to validate the products so that the have at least one category. Since I am using the Form assistant and the validate functions of CakePHP y have arrived to this:
class Product extends AppModel {
var $name = 'Product';
var $validate = array(
'category_id' => array(
'rule' => array('multiple', array('min' => 1)),
'message' => 'You have to choose at least one category'
)
);
}
But it doesn't work, any ideas?
I think you should not validate against category_id, instead use Category (the name of your model).
If this still doesn't work, you should be ablo to find a solution in this question on SO: HABTM form validation in CakePHP
or have a look on this article:
http://nuts-and-bolts-of-cakephp.com/2008/10/16/how-to-validate-habtm-data/
have you tried the NOTEMPTY rule? im assuming the list of categories is in a checkbox format, rite.. by default the category_id if empty. the only logic i can think is, if nothing checked, then it throw the error message.
correct me if im wrong.. :)

Resources