Multiple relations to the same model CakePHP - mysql

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.

Related

Database indexes cakePHP

I have two tables, namely 'Customer' and 'Event'. The relations between these two are as follows:
Event
var $belongsTo = array(
...
'Customer'=>array(
'className' => 'Customer',
'foreignKey' => 'customer_id'
)
);
Customer
var $hasMany = array(
'Event' => array(
'className' => 'Event',
'foreignKey' => 'customer_id',
'dependent' => false,
)
);
Each and every customer record holds a company id as well as currently logged in user. What I would like to achieve is to get all of the events for a day, related only to a particular company, but that is of course not working since the event table does not hold company id. Maybe the following find call will help to understand the issue better:
$conditions = array('company_id'=>CakeSession::read("Auth.User.company_id"), 'date'=>date("Y-m-d", $tomorrow));
$tomorrowsEvents = $this->find('all', array(
'conditions'=>$conditions, 'contain'=>array('User', 'Customer')));
Moreover, a customer belongs to a company and a company has many customers, just as follows:
Customer
var $belongsTo = array(
'Company' => array(
'className' => 'Company',
'foreignKey' => 'company_id',
'dependent' => false,
),
);
Company
var $hasMany = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'company_id',
'dependent' => false
),
'Customer'=>array(
'className' => 'Customer',
'foreignKey' => 'company_id',
'dependent' => false
)
);
Any help is much appreciated.
I would actually do this query "backwards" by doing it from Customer, and using the containable behavior to contain the related Events:
$this->Customer->find('all',
array(
'conditions' => array(
'company_id' => CakeSession::read("Auth.User.company_id")
),
'contain' => array(
'Event' => array(
'conditions' => array(
'Event.date' => date("Y-m-d", $tomorrow)
)
)
)
));
In your case it seems that Events have many companies and companies have many events. This is ideal situation for hasAndBelongsToMany relationship. However, you have to focus on the className and joinTable properties to handle the non convenient naming of the join table customers.
http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasandbelongstomany-habtm
you need to rethink the problem, because a user can be (customer or company) then they have a group or they are in a type of user. then a user belongs to a group or user type, this group can be a client or company .
users belongsto a group
group has many user
users hasmany events
events has many users
You can tell if is customer or company is the type of group that owns
table___group
id ____ category ____ subcategory
1 ____ customer ____ example
2 ____ company ____ example

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

Retrieving Data From two tables that are associated with a forign key in CakePhp

I have two tables named login and userDetail
Login
login_id
uname
pswd
userdetail_id
and
userdetails
userdetail_id
name
address
email
the login table contain userdetails_id in the userDetail table. i want to get all data from Login table and userDetail table and save it to a variable
if anyone knows, please answer me......
First of all your table structure must be as below.
logins Table.
Id auto_increment
username
password
userDetails Table.
Id auto_increment
user_id
name
address
etc...
Now model for each table would be.
Login
<?php
class Login extends AppModel
{
var $name = 'User';
var $hasMany = array
(
'UserDetail' => array
(
'className' => 'UserDetail',
'foreignKey' => 'user_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
}
?>
UserDetail
<?php
class UserDetail extends AppModel
{
var $name = 'UserDetail';
var $belongsTo = array
(
'User' => array
(
'className' => 'User',
'foreignKey' => 'user_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => ''
)
}
?>
And finally in controller where you need to fetch login detail.
$login_detail = $this->Login->find('all');
You will see userDetail table records in resulting $login_detail.
use pr($login_detail); in controller to see it in action.
Cheers.
Feel Free to ask.
Make sure ContainableBehavior has been enabled. After that you can use following query:
$login = $this->Login->find('first', array(
'contain' => array(
'Userdetail.userdetail_id'
'Userdetail.name',
'Userdetail.address',
'Userdetail.email'
),
'fields' => array(
'Login.login_id'
'Login.uname',
'Login.pswd'
),
'conditions' => array(
'Login.login_id' => 1
)
));
The query for this task would be:
SELECT Login.*, name,address,email
FROM Login JOIN userdetails
ON Login.userdetail_id=userdetails.userdetail_id
The results of this query could be saved to variables by looping in cakephp.

Model association is off for joining users table on comments table for a submission

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

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