I'm trying to model the following:
A journey has an id, a fromCity and a toCity.
My DB looks like this:
Table journey:
id | fromCity | toCity
1 2 4
2 4 2
Table fromCity:
id | name
2 paris
4 london
I have models defined for the city and for the journey.
In my model file for the journey I want to declare a $hasOne filed in order resolve the fromCity id to the city's name.
I tried to follow the CakePHP tutorial on hasOne (http://book.cakephp.org/view/80/hasOne) but I can't wrap my head around how to resolve two foreign keys.
Can someone please explain to me how a var $hasone = ... has to look for this case?
Edit: The models:
<?php class City extends AppModel { var $name='City';} ?>
<?php class Journey extends AppModel { var $name='Journey'; /*var $hasOne=array(...)*/} ?>
Edit 2:
var $hasOne = array(
'CityFrom' => array(
'className' => 'City',
'conditions' => 'Journey.fromAirport = CityFrom.id',
'dependent' => true,
'foreignKey' => 'id = Journey.fromCity' ),
'CityTo' => array (
'className' => 'City',
'conditions' => 'Journey.toCity = CityTo.id',
'dependent' => true,
'foreignKey' => 'id = Journey.toCity'
)
);
Seems to work for the first entry of the journey table. All other's values are null. I think the problem occours from having two columns with the same name in this query.
As Rin mentioned,you need to use beLongsTo instead of hasOne.Here's a example about Multiple relations to the same model from Cookbook.Hope it helps.
First of all your link leads to 1.2 docs, you probably downloaded 1.3.
In 1.3, you should probably also use belongsTo on FromCity and ToCity Models (but I could be wrong, long time ago I used it :)
Related
I'm trying to do one of two things, use a virtual field from a model as the display field in my join model, or use the virtual field as the display in a find('list') on my join model.
Here's the current layout:
MODELS
<?php
class Participant extends AppModel {
public $hasMany = array('Registration');
public $virtualFields = array(
'full_name' => 'CONCAT(last_name, ", ", first_name)'
);
public $displayField = 'full_name';
}
-----
class Contest extends AppModel {
public $hasMany = array('Registration');
}
-----
class Registration extends AppModel {
public $belongsTo = array('Participant', 'Contest');
public $hasMany = array('Assignment');
}
?>
Tables are as follows:
participants contests registrations
------------ --------- --------------
id id id
first_name name contest_id
last_name participant_id
In my contests controller I'm trying to develop a list to be viewed as checkboxes in the view.
Here is the excerpt from my contests controller:
$this->loadModel('Registration');
$this->set('registrations', $this->Registration->find(
'list',
array(
'conditions' => array('contest_id' => $contestId),
'recursive' => 1
)
)
);
//$contestId is defined previously, and I have verified such.
This all actually runs fine as it is, and in the view will display a column of checkboxes with the registration_id as the label next to the checkbox.
I would like to get a full_name as is defined in the Participant model to be the displayField of the Registration model. I've been searching and can't quite seem to find a good way of doing that. I hope I have been descriptive enough, and please let me know if you have any questions and I'll try to explain better. Thank you.
edit: I'm using CakePHP 2.4.
try to add the 'fields' parameter
$this->loadModel('Registration');
$this->set('registrations', $this->Registration->find(
'list',
array(
'fields' => array('Registration.id', 'Participant.full_name'),
'conditions' => array('contest_id' => $contestId),
'recursive' => 1
)
));
edit: apparently cake does not place virtual fields of associated models when using find() with 'fields' options.
So you have to build your array by yourself, hoping your models use the containable behavior
$registrations = $this->Registration->find(
'all',
array(
'contain' => array(
'Participant' => array('full_name')
),
'conditions' => array('contest_id' => $contestId),
)
);
$registrations = Hash::combine($registrations, '{n}.Registration.id', '{n}.Participant.full_name');
$this->set('registrations', $registrations);
Someone can help me on this issue please?
How to join table on specific field?
I have 2 tables and I want to join them like this: Actus.user_id=>Follows.follower_id
table 1 =>
Follows
id
user_id
follower_id
table 2 =>
Actus
id
user_id
content
created
Forcing a join is done like this (on top of my head):
<?php
$results = $this->Actu->find('all',
array('joins'=> array(
'table'=>'followers',
'type'=>'inner',
'alias'=>'Follower',
'conditions'=>array(
'Follower.follow_id = Actu.user_id',
)
)
)
?>
But you would normally don't need forcing joins. CakePhp can build this for you, if your Models (Actu and Follower) are declared properly. What about setting a "Actu" hasMany "Follower" relationship ? See here
EDIT :
I would do it like this (I am not sure about the exact model name, double check it) :
<?php
class Actu extends AppModel {
public $hasMany = array(
'Follow'=> array(
'className' => 'Follow',
'foreignKey' => 'follower_id'
)
);
}
?>
I have had this working plenty of times so I am wondering if I have missed something GLARINGLY obvious or subtly hidden.
I have the following code in a model called Wedding:
public $hasMany = array(
'Photo' => array(
'className' => 'Photo',
'foreignKey' => 'wedding_id'
)
);
and I have the corresponding code in a Model called Photo:
public $belongsTo = array(
'Wedding' => array(
'className' => 'Wedding',
'foreignKey' => 'wedding_id'
)
);
but when I view the url /Weddings/ I do not get the linked photographs in the $weddings variable. Here is the db entry in photos:
id name file wedding_id
1 Couple Shot xxx.jpg 1
and in weddings:
id name groom bride weddingdate location_id photo_id
1 Ike & Tina Turner Ike Turner Tina Turner 2010-01-01 1 1
What have I missed? Thanks
You may need to set the recursive when you call the model or before you call the find method:
$this->Wedding->recursive = 1;
This will pull the associated data.
I am new to cakePHP and I am trying to figure out how to create the following relationship:
The employees.manager_id will point to the employees.id of their manager. So, in other words, employee Jason will have a manager of Jill. Jason is employees.id 1 with employees.manager_id 2. Jill is employees.id 2 and employees.manager_id null.
How do I setup the model controller in such a way that when indexing, adding, editing, etc. that the manager_id should be looked up from the same table. For example, when indexing, I would like to see that 'Jill' is the manager of jason rather than the number 2...
you can define following association:
class Employee extrnds AppModel {
var $belongsTo = array(
'Parent' => array('className' => 'Employee',
'foreignKey' => 'manager_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
Then you can access it by:
$this->Employee->Parent->find('list');
I am working on a plugin for our CakePHP CMS that will handle blogs. When getting to the tags I needed to set the HABTM relationship to unique = false to be able add tags to a post without having to reset them all.
The BlogPost model looks like this
class BlogPost extends AppModel {
var $name = 'BlogPost';
var $actsAs = array('Core.WhoDidIt', 'Containable');
var $hasMany = array('Blog.BlogPostComment');
var $hasAndBelongsToMany = array('Blog.BlogTag' => array('unique' => false), 'Blog.BlogCategory');
}
The BlogTag model looks like this
class BlogTag extends AppModel {
var $name = 'BlogTag';
var $actsAs = array('Containable');
var $hasAndBelongsToMany = array('Blog.BlogPost');
}
The SQL error I am getting when I have the unique => true setting in the HABTM relationship between the BlogPost and BlogTag is
Query: SELECT `Blog`.`BlogTag`.`id`, `Blog`.`BlogTag`.`name`, `Blog`.`BlogTag`.`slug`, `Blog`.`BlogTag`.`created_by`, `Blog`.`BlogTag`.`modified_by`, `Blog`.`BlogTag`.`created`, `Blog`.`BlogTag`.`modified`, `BlogPostsBlogTag`.`blog_post_id`, `BlogPostsBlogTag`.`blog_tag_id` FROM `blog_tags` AS `Blog`.`BlogTag` JOIN `blog_posts_blog_tags` AS `BlogPostsBlogTag` ON (`BlogPostsBlogTag`.`blog_post_id` = 4 AND `BlogPostsBlogTag`.`blog_tag_id` = `Blog`.`BlogTag`.`id`)
As you can see it is trying to set the blog_tags table to 'Blog'.'BlogTag. which isn't a valid MySQL name.
When I remove the unique => true from the relationship it all works find and I can save one tag but when adding another it just erases the first one and puts the new one in its place.
Does anyone have any ideas? is it a bug or am I just missing something?
Cheers,
Dean
Dean
So do you have the tables blog_posts_blog_tags?
To quote the CakePHP literature on HABTM relationships
We'll need to set up an extra table in the database to handle HABTM associations. This new join table's name needs to include the names of both models involved, in alphabetical order, and separated with an underscore ( _ ).
So ( dropping the Blog bit for readability !) you need your posts tables, your tags table and your posts_tags table and then the HABTM definition is
class Post extends AppModel {
var $name = 'Post';
var $hasAndBelongsToMany = array(
'Tag' =>
array(
'className' => 'Tag',
'joinTable' => 'posts_tags',
'foreignKey' => 'post_id',
'associationForeignKey' => 'tag_id',
'unique' => true,
)
);
}