I am making a message system in CakePHP and I have table messages
id
from_id
to_id
subject
message
to_id is set as FK for user so user can haveMany messages but how can I echo the name of sender if I get only id?
User Model:
class User extends AppModel {
public $name = 'User';
public $hasOne = array (
'UserProfile'=>array(
'className'=>'UserProfile',
'foreignKey'=>'id'
)
);
public $hasMany = array(
'Message'=>array(
'className'=>'Message',
'foreignKey'=>'to_id'
)
);
}
Message Model:
class Message extends AppModel {
public $name = 'Message';
public $belongsTo = array (
'User'=>array(
'className'=>'User',
'foreignKey'=>'to_id'
),
);
}
Message Controller:
public function messages(){
$user = $this->User->find( 'first', array('conditions' => array(
'User.id' => $this->Session->read('Auth.User.id'))));
$this->set('user', $user);
if($this->request->is('post')) {
$this->requert->data['Message']['from_id'] = $this->Auth->user('id');
debug($this->request->data);
}
}
This needs to store all information about user in array including array Message but in this case I get the arrat Message with:
id => 1
from_id => 10
to_id => 7
subject => 'subject'
message => 'body'
So how can I extract the name of sender from this id?
Please help?
In this case you will need to use aliases for the classNames.
class Message extends AppModel {
public $belongsTo = array(
'Sender' => array(
'className' => 'User',
'foreignKey' => 'from_id'
),
'Receiver' => array(
'className' => 'User',
'foreignKey' => 'to_id'
)
);
}
class User extends AppModel {
public $hasMany = array(
'SentMessages' => array(
'className' => 'Message',
'foreignKey' => 'from_id'
),
'Messages' => array(
'className' => 'Message',
'foreignKey' => 'to_id'
)
);
}
Related
I've read about convections and I have my application/database straight.
I've read too about $hasOne, $hasMany, $belongsTo, etc
But, I'm facing a problem/issue that I can't solve for my self.
My models: Car, Event, Refuel, Repair
My controller: CarsController
My relations:
class Car extends AppModel {
public $BelongsTo = array('User');
public $hasMany = array('Event');
}
.
class Event extends AppModel {
public $BelongsTo = array('Car');
public $hasOne = array('Refuel');
}
.
class Refuel extends AppModel {
public $BelongsTo = array('Event');
}
Output of find() excecuted from CarsController
array(
'Car' => array(
'id' => '1',
'user_id' => '1',
'make' => 'Make',
'model' => 'Model',
),
'Event' => array(
(int) 0 => array(
'id' => '1',
'car_id' => '1',
'dateEvent' => '20-10-2014',
'description' => '1'
),
(int) 1 => array(
'id' => '2',
'car_id' => '1',
'dateEvent' => '20-10-2014',
'description' => '2'
),
(int) 2 => array(
'id' => '3',
'car_id' => '1',
'dateEvent' => '20-10-2014',
'description' => '3'
)
)
)
You need to know this:
Car belongs to a User. User may have many cars
Car has many events. An event just have one car.
To each Event should be associated one refuel or one repair. A refuel or repair cant have more than one event associated.
Tables:
users: id
cars: id, user_id
events: id, car_id
refuels: id, event_id (unique)
repairs: id, event_id (unique)
Have I defined well the relations ?
How to express it in cakePHP, special events-refuels and events-repairs?
You missed
class User extends AppModel {
public $hasMany = array('Car');
}
I've found that array('recursive' => 2) solve the problem!
But what is this and why ?
I have 3 models:
User
Like
Post
Like has 2 foreign key set using CakePHP convention on user_id and post_id (that are the id column of the other 2 models).
I want to run a find that mime the LEFT JOIN in sql on Post with a condition on the foreign key.
In detail i want:
1: all the posts.
1a: if the post have a like from the user XXX I want it included in the result
1b: else the post doesn't have a ->Like attribute.
So, if i do this:
$posts = $this->Post->find('all');
in $posts i have all the posts, and for each posts all the likes.
Reading the book, I feel like i should write something like:
$options['joins'] = array(
array('table' => 'likes',
'alias' => 'Likes',
'type' => 'LEFT',
'conditions' => array(
'Post.id = Likes.post_id',
'Likes.user_id = 536f6a29-babc-4724-a74d-2ce100000000'
)
)
);
$posts = $this->Post->find('all', $options);
But this doesn't work.
Hope this is clear.
well you need put in your models
class User extends AppModel
{
public $useTable = 'users';
public $primaryKey = 'id';
public $hasMany = array(
'Post',
'Like'
);
}
class Post extends AppModel
{
public $useTable = 'posts';
public $primaryKey = 'id';
public $belongsTo = array('User');
public $hasMany = array(
'Like'
);
}
class Like extends AppModel
{
public $useTable = 'likes';
public $primaryKey = 'id';
public $belongsTo = array('Post','User');
}
and in you controller
$this->loadModel("User");
$query = $this->User->find('all', array(
'joins' => array(
array(
'table' => 'posts',
'alias' => 'Post',
'type' => 'LEFT',
'conditions' => array(
'User.id = Post.user_id'
)
),
array(
'table' => 'likes',
'alias' => 'Like',
'type' => 'LEFT',
'conditions' => array(
'User.id = Like.user_id'
)
)
),
'conditions' => array(
'Post.id = Likes.post_id',
'Likes.user_id = 536f6a29-babc-4724-a74d-2ce100000000'
),
'order' => array(
'Post.id' => 'ASC'
),
'fields' => array('Post.*','User.id'),
'recursive' => -1
));
I am new to Cakephp and I don't found any solution for my problem.
I have three tables-
medicines:
id|Name|company_id
companies:
id|Name|city_id
cities:
id|Name
I have to select medicines.name, companies.name and cities.name where ids are matched so
how I cand do this by Cakephp method.
I know the simple sql query for this:
SELECT medicines.name, companies.name and cities.name FROM medicines, companies, cities WHERE medicines.company_id=companies.id AND companies.city_id=cities.id
Thanks in Advance
Have you tried reading the book? It is well explained there: Associations: Linking Models Together
Defining relations between different objects in your application
should be a natural process. For example: in a recipe database, a
recipe may have many reviews, reviews have a single author, and
authors may have many recipes. Defining the way these relations work
allows you to access your data in an intuitive and powerful way.
Examples from the book:
class User extends AppModel {
public $hasOne = 'Profile';
public $hasMany = array(
'Recipe' => array(
'className' => 'Recipe',
'conditions' => array('Recipe.approved' => '1'),
'order' => 'Recipe.created DESC'
)
);
}
class User extends AppModel {
public $hasMany = array(
'MyRecipe' => array(
'className' => 'Recipe',
)
);
public $hasAndBelongsToMany = array(
'MemberOf' => array(
'className' => 'Group',
)
);
}
class Group extends AppModel {
public $hasMany = array(
'MyRecipe' => array(
'className' => 'Recipe',
)
);
public $hasAndBelongsToMany = array(
'Member' => array(
'className' => 'User',
)
);
}
My associations in CakePHP are a bit off. Here is the problem. I have a users table
and a comments table. When retrieving a submission I want to join the users table
on the comments table with Comment.user_id == User.id.
Comment Model:
class Comment extends AppModel {
var $name = 'Comment';
var $belongsTo = array('User');
var $hasMany = array(
'CommentsLike' => array(
'className' => 'CommentsLike'
),
'Comment' => array(
'className' => 'Comment'
)
);
var $hasAndBelongsToMany = array(
'User' => array(
'className' => 'User',
'joinTable' => 'comments',
'foreignKey' => 'Comment.user_id',
'associationForeignKey' => 'user_id'
),
'Submission' => array(
'className' => 'Submission'
)
);
User Model:
class User extends AppModel {
var $name = 'User';
var $hasMany = array('Comment');
var $hasAndBelongsToMany = array(
'Comment' => array(
'className' => 'Comment',
'joinTable' => 'comments',
'foreignKey' => 'Comment.user_id',
'associationForeignKey' => 'user_id',
),
'Submission' => array(
'className' => 'Submission',
'order' => 'Submission.created DESC'
)
);
When I grab a submission, it grabs all comments for it, but it doesn't join on
the users table which is what I want
Submission Model:
class Submission extends AppModel {
var $name = 'Submission';
var $belongsTo = array(
'User' => array(
'className' => 'User'
)
);
var $hasMany = array(
'Comment' => array(
'className' => 'Comment',
'order' => 'Comment.created DESC',
'conditions' => array(
'Comment.deleted' => 0
)
),
'SubmissionsVote' => array(
'className' => 'SubmissionsVote'
),
'SubmissionThumbnails' => array(
'className' => 'SubmissionThumbnails'
)
);
A find on a submission will return this:
[Submission] => Array
(
// removed for sake of stackoverflow length
)
[User] => Array
(
[id] => 2
[username] => bob_cobb
)
[Comment] => Array
(
[0] => Array
(
[id] => 1
[submission_id] => 112
[comment] => this is a test comment
[user_id] => 2
[created] => 5 minutes ago
[deleted] =>
[parent_id] =>
)
)
As you can see [Comment][0] should also have [Comment][0][User] or something similar.
Why would I want this? Simple: I want to grab the username of the person who
commented by the foreign key of user_id from the comments table. I've read the docs and tutorials and pretty sure I'm close on this but not sure what's holding me back.
Here is a screenshot of the comments table:
Here is a screenshot of the users table structure:
You can a couple of options:
Either set the recursive property in the Submission model to the level you need to fetch back your associated data ( see http://book.cakephp.org/2.0/en/models/model-attributes.html#recursive )
or (more preferable) use the Containable behaviour ( see http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html ) to specify what related data to return:
class Submission extends AppModel
public $actsAs = array('Containable');
}
Use it like this in your find:
$data = $this->Submission->find('all', array(
'conditions'=>array(your conditions here),
'contain'=>array(
'User,
'Comment'=>array(
'User'
)
)
));
Most people use containable in every model so add it to AppModel and set AppModel::recursive to -1
Hey we have three tables in our database which are connected through two relationships which are Account and Invoices.
Accounts (id....)
Invoices (id, sender_id, receiver_id)
Relationships (id, sender_id, receiver_id)
Sender and receiver are both foreign keys which reference the account table so in cakePHP an account_id. The relationship table specifies relationships where invoices can be sent or received and the invoice table displays the invoices that have been sent.
How do we link both these foreign keys with Accounts in CakePHP?
Cake is finding there is a relationship and listing the receivers available to send an invoice to. At the moment its sending the right sender_id to the database but the sending the relationship_id to the database as the receiver_id in the invoice table.
Already gone through this but doesnt work: http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasandbelongstomany-habtm
Here is what we have for our two models:
Account model:
class Account extends AppModel{
var $name='Account';
public $useTable = 'accounts';
public $primaryKey = 'id';
var $hasAndBelongsToMany = array(
'User' =>
array(
'className'=>'User',
)
);
var $hasMany = array(
'Template' =>
array(
'className'=>'Template',
'foreignKey'=>'account_id',
),
'InvoiceRecieved' => array(
'className'=>'Invoice',
'foreignKey'=>'receiver_id',
),
'InvoiceSent' => array(
'className'=>'Invoice',
'foreignKey'=>'sender_id',
)
);
}
Invoice model:
class Invoice extends AppModel{
var $name='Invoice';
var $hasAndBelongsToMany = array(
'Field' =>
array(
'className'=>'Field',
'joinTable'=>'fields_invoices'
)
);
var $belongsTo = array(
'Sender' => array(
'className' => 'Account',
'foreignKey' =>'account_id',
),
'Receiver' => array(
'className' => 'Account',
'foreignKey' =>'receiver_id',
)
);
public $useTable='invoices';
public $primaryKey='id';
Invoice Controller:
$accounts2=$this->User->AccountsUser->find('list', array(
'fields'=>array('account_id'),'conditions' => array(
'user_id' => $this->Auth->user('id'))));
$accounts=$this->User->Relationship->find('list', array('fields'=>array('receiver_id'),'conditions' => array('sender_id' => $accounts2)));
if($this->request->is('post')){
($this->Invoice->set($this->request->data));
//if($this->Invoice->validates(array('fieldList'=>array('receiver_id','Invoice.relationshipExists')))){
$this->Invoice->save($this->request->data);
$this->Session->setFlash('The invoice has been saved');
}else {
$this->Session->setFlash('The invoice could not be saved. Please, try again.');
}
//}
$this->set('accounts', $accounts);
$this->set('accounts2', $accounts2);
Add view:
<?php
echo $this->Form->create('Invoice', array('action'=>'addinvoice'));
echo $this->Form->input('sender_id',array('label'=>'Sender: ', 'type' => 'select', 'options' => $accounts3));
echo $this->Form->input('receiver_id',array('label'=>'Receiver: ', 'type' => 'select', 'options' => $accounts));
echo $this->Form->end('Click here to submit Invoice');
?>
I don't think you need a join table for invoices, and senders and receivers. You can store these foreign keys in your invoices table. Your relationships would then be:
<?php
class Invoice extends AppModel {
public $belongsTo = array(
'Sender' => array(
'className' => 'Account',
'foreignKey' => 'sender_id'
),
'Receiver' => array(
'className' => 'Account',
'foreignKey' => 'receiver_id'
)
);
}
If you then need to distinguish invoices that have been sent or not, you could also add a column called status_id or similar, and store another foreign key to a new statuses table, with an ID column and name column, and the following sample data:
id name
== ====
1 Draft
2 Sent
And any other statuses you may need.