CakePHP bindModel working, preset Model associations not - cakephp

I am in development of a personal project.
I have two models 'Show' and 'Episode'. I have one controller 'Ops'.
Show model:
class Show extends AppModel
{
var $name = 'Show';
var $hasMany = array(
'Episode' => array(
'className' => 'Episode',
'foreignKey' => 'show_id'
)
);
}
Episode model:
class Episode extends AppModel
{
var $name = 'Episode';
var $belongsTo = array(
'Show' => array(
'className' => 'Show',
'foreignKey' => 'show_id'
)
);
}
Ops controller:
class OpsController extends AppController
{
var $name = 'Ops';
var $uses = array('Show','Episode');
function index()
{
$episodes = $this->Episode->find('all',array(
'limit' => 10,
'order' => array('Episode.first_aired' => 'DESC'),
)
);
debug($this->Episode);
debug($episodes);
}
}
When running the Ops controller I get the 'Episode' records like I want but don't get the associated 'Show' record based on the 'show_id' in the 'belongsTo' configuration. It appears that it is not referencing the model at all as I can purposefully break the model class an the request still goes on.
After doing a lot of checking, researching, and testing, I was able to get it to work by adding the following into the Ops controller before the find() request:
$this->Episode = ClassRegistry::init('Episode');
$this->Episode->bindModel(
array('belongsTo' => array(
'Show' => array(
'className' => 'Show'
)
)
)
);
Now while this works I would still like to know why my models are not being called properly. Any help would be most appreciated. Thanks!

What happens if you query Show in the same way?
Are you certain the id fields are defined correctly?
On both tables you should have id(INTsize) and on episodes there should also be show_id(INTsize).
If it's set up according to Cake convention, you should be able to remove the 'foreignKey' => 'show_id' line and Cake will sort it out itself.`

It sounds like Cake isn't using your model files and instead automagically generating some based on the tables.
It sounds dumb, but check the folders and file names for spelling errors and that they are lowercase.

In your Show model, you have the Episode foreign key set to show_id, which should be episode_id. However, I don't think that is causing the problem.
You aren't changing any CakePHP naming conventions, from what I can tell, so just remove the arrays that define the association and leave as string, e.g.
class Show extends AppModel
{
var $name = 'Show';
var $hasMany = array(
'Episode'
);
}
class Episode extends AppModel
{
var $name = 'Episode';
var $belongsTo = array(
'Show'
);
}
This may not work, but I have bumped into similar issues before and this resolved it. Good luck.

Related

CakePHP Join virtualField as displayField

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);

How can I use counterCache() for tracking view counts with CakePHP?

Every time a user views a submission, I track the count and tie it to a session:
SubmissionsController:
// Count view
if ($this->Session->check('viewed_submission_' . $submissionId) !== true) {
$clientIp = ip2long($this->request->clientIp());
$this->SubmissionsViews->countView($submissionId, $clientIp);
$this->Session->write('viewed_submission_' . $submissionId, true);
}
I'm keeping track of them in a SubmissionsViews table.
SubmissionsViews Model:
class SubmissionsViews extends AppModel {
var $name = 'SubmissionsViews';
var $belongsTo = array(
'Submission' => array(
'className' => 'Submission'
)
);
public function countView($submissionId, $clientIp) {
$this->set('submission_id', $submissionId);
$this->set('user_ip', $clientIp);
$this->save($this->data);
}
}
My SubmissionsView table submissions_views has the following fields:
id
submission_id
user_ip
created
I'm trying to set up counterCache to keep track of additions to that table, but not sure how to set it up. I'm currently adding the counterCache in my $belongsTo within my Submission model:
class Submission extends AppModel {
var $belongsTo = array(
'User' => array(
'className' => 'User'
),
'SubmissionsViews' => array(
'counterCache' => true
)
);
But it's telling me it can't find Submission.submissions_views_id. In the documentation, all it said was that I needed to add a field to my submissions table called submissions_views_count, so I'm confused how to get this working?
Model names should be singlular, so SubmissionViews should be SubmissionView.
Your association is incorrect. Submission hasMany SubmissionView, not belongsTo.
counterCache needs to be specified in the SubmissionView model inside the belongsTo config for Submission, not in the Submission model file. Please read the manual more carefully.

Add a friend feature in CakePHP

I need a simple add a friend feature in my application, through some research, I would need a join table linking back to users table ? something like this: (I already have a users table)
Users-Friendships-Users
Can anyone give more details about this?
The friendships table should have following columns:
id Integer
user_from (the user who requested friendship)
user_to (the user who accepted friendship)
created (optional to track when your friendship started)
Then you need to create proper Model relation.
class User extends AppModel {
...
var $hasMany = array(
'UserFrom'=>array(
'className'=>'Friendship',
'foreignKey'=>'user_from'
),
'UserTo'=>array(
'className'=>'Friendship',
'foreignKey'=>'user_to'
)
);
var $hasAndBelongsToMany = array(
'Friendship' => array(
'className' => 'User',
'joinTable' => 'friendships',
'foreignKey' => 'user_from',
'associationForeignKey' => 'user_to'
);
...
}
class Friendship extends AppModel {
...
var $belongsTo = array(
'UserFrom'=>array(
'className'=>'User',
'foreignKey'=>'user_from'
),
'UserTo'=>array(
'className'=>'User',
'foreignKey'=>'user_to'
)
)
...
}
This way you are defining 2 relation in each model. You can add HABTM relation too. Run bake script to build your controllers and views. Then in your code you can use something like this:
$this->User->UserFrom->find('all',
array(
'conditions'=>array('user_from'=>1),
'contain'=>array('UserTo')
)
);
This should return friends of user with ID 1 and all friends details.
Be careful with the recursive queries. :)

Paginating and retriving data with CakePHP

Hi
I'm trying to to do pagination from the KindsController but with data from the LinkModel
Tables :
Kinds links
id id
name title
order url
kind_id
order
model:
class Kind extends AppModel{
var $name = 'Kind';
var $hasMany = 'Link';
}
controller:
class KindsController extends AppController{
var $name = 'Kinds';
var $paginate = array(
'Kind'=> array(
'limit' => 12,
'order'=> array('Kind.order'=>'ASC')
)
);
}
desired result (view) ;
Kind.name ( numbers of links )
links.name
........
..........
Kind.name ( numbers of links )
links.name
........
..........
i'm using the kinds.order and links.order to control how the data is displayed in the view
from an admin area.
i need to retrive data from the kinds table ordered by kinds.order ASC and the number of links, and the links data ordered by links.order
thanks
You can define order in the relation like this:
class Kind extends AppModel{
var $hasMany = array(
'Link' => array(
'className' => 'Link',
'order' => 'Link.name'
),
);
}

Using HABTM relationships in cakephp plugins with unique set to false

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,
)
);
}

Resources