How to define relations with cakePHP? - mysql

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 ?

Related

Find to mime the LeftJoin in CakePhp

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

Cakephp: How to link models if each model connected to other by some foreign key

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

How to retrive From which user is message in Cake?

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

CakePHP: Table Joins

I am new to CAKEPHP and using joins for the first time. I read the documentation as well.
Now i have two models, One is for Users and other is for Status.
In Status table i have a foreign Key which is User Id in users table.
I want to use $hasMany with conditions such that if a logged in user Share a status it should update the status table having UID in the foreign key and UID is Users table primary key
I dont know what and how to do that.
What i believe is that it should be something like this
class User extends AppModel
{
var $name = 'User';
var $hasMany = array(
'Status' => array(
'conditions' => array('Status.FK' => 'User.id')
)
);
}
Hope i did it right?
for hasMany put this code in your User Model:
/**
* #see Model::$hasMany
*/
public $hasMany = array(
'Status' => array(
'className' => 'Status',
'foreignKey' => 'Status.FK',
'dependent' => true,
),
);
but The Best way is that using belongsTo in your Status Model,Because belongsTo has fewer queries than hasMany method. and in your controller you can use the Status model to retrieving users with their status. for example:
In Status Model:
/**
* #see Model::$belongsTo
*/
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'Status.FK',
),
);
then In your Controller for find specific rows from database you can use :
$this->recursive = 1;
$this->Status->find('all',array('conditions' => array('User.id' => $id)));

Multiple relations to the same model CakePHP

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.