Basically, im trying to learn the basics of cakephp and im stuck at sorting the relationships out. I have tried loads of ways with no success.
I have a lead table which needs to connect to the contact table, there can be many leads to one contact. Im not sure how to do this, could someone please help?
lead model:
<?php
class Lead extends AppModel {
var $name = 'Lead';
var $belongsTo = array(
'Contact' => array(
'className' => 'Contact',
'foreignKey' => 'contact_id'
)
);
}
?>
contact
<?php
class Contact extends AppModel {
var $name = 'Contact';
var $hasMany = array(
'Lead' => array(
'className' => 'Lead',
'foreignKey' => 'contact_id'
)
);
}
?>
Since once contact can have many leads, you'll want to add
var $hasMany = 'Lead';
to your User class.
And since I assume that Lead has a foreign key referencing the 'owning' User, you'll want to add
var $belongsTo = 'User';
to your Lead class.
This will let you access leads and users from both sides of the relationship (from the lead perspective, and from the user perspective).
See the docs for hasMany and belongsTo for more info.
Related
Okay, so I have a form in CakePHP that submits to a database. In this form it submits a field called client_id and it is stored in the database as such as well.
Then I have a view to allow me to view all of the invoices that have ever been created. To view the client responsible for the invoice, I can currently only see the id entered in the form by placing: <?php echo $invoice['Invoice']['client_id']; ?> in the view.
The invoices go to one database called: invoices
The clients name is not stored in the invoices table, just the id
The clients information is stored in one database called: clients
I want to be able to actually display out the clients real name in the invoices view rather than the client id.
I tried adding the following query to my index controller, But i'm not sure what to do after this or if this is even right.
$this->set('clients', $this->Invoice->query("SELECT * FROM clients WHERE id='89545'"));
In order to keep this question short in the first place, Please request specific code by commenting. i.e. Controller code, view code, etc... Thank you in advance.
Additional Thoughts
If I wasn't using CakePHP I could use something like the following, So I guess I just don't know how to put this into cakephp "language".
<?php
query($con, "SELECT name FROM clients WHERE id='$client_id'");
echo $row['name'];
?>
roughly!
Update
Here are my models
First one being the Client.php
<?php
class Client extends AppModel {
public $hasMany = array(
'Invoice' => array(
'className' => 'Invoice',
'foreignKey' => 'client_id'
)
);
}
?>
Second one being the Invoice.php
<?php
class Invoice extends AppModel {
public $belongsTo = array(
'Client' => array(
'className' => 'Client',
'foreignKey' => 'client_id'
)
);
}
?>
And finally, to get my invoices from the database, I am using the following inside: InvoicesController.php
public function index() {
$this->set('invoices', $this->Invoice->find('all'));
}
Have you properly set up your model associations? If so you should be able to do something like $invoice['Client']['client_name'] assuming you didn't use recursive = -1.
/edit: Ok I don't mind throwing some code out, but this is a fundamental concept you'll have to try to wrap your head around. Every model that is connected to another model has to have the association set up or things will be painful.
I am assuming a Client hasMany Invoice. So each invoice is specific to a client, and they can have multiple invoices (ex. October 2013 vs November 2013 invoice). From the CakePHP page we see:
class User extends AppModel {
public $hasMany = array(
'Comment' => array(
'className' => 'Comment',
'foreignKey' => 'user_id',
'conditions' => array('Comment.status' => '1'),
'order' => 'Comment.created DESC',
'limit' => '5',
'dependent' => true
)
);
}
So using that as our template, we end up with:
public $hasMany = array(
'Invoice' => array(
'className' => 'Invoice',
'foreignKey' => 'client_id'
)
);
And that goes in Client.php. As the inverse of hasMany is belongsTo, we have an Invoice belongsTo Client. Again, using the CakePHP page as the template, we end up with:
public $belongsTo = array(
'Client' => array(
'className' => 'Client',
'foreignKey' => 'client_id'
)
);
And that goes in Invoice.php. Once you set up those associations, whenever you do something like $this->Invoice->find('all'); or $this->paginate('Invoice');, with proper $recursive settings, Cake will grab the corresponding Client record. This allows you to do what I said before, something like $invoice['Client']['client_name'].
You can also use the $actsAs = array('Containable'); in the model in order to use the 'contain' directive in your controller's find method (instead of using recursive which most likely will get unwanted data on models with many relations)
I apologize in advance if this question has been answered elsewhere; I searched high and low for an existing answer but came up empty. Perhaps I am looking with the wrong keywords.
I have three models, two (Student and Tutor)of which have a $hasMany relationship with a common model(Appointment) which has a $belongsTo relationship with both of the other models. Exact models are below...
A Student hasMany Appointments...
class Student extends AppModel {
var $hasMany = array (
'Appointment' => array (
'foreignKey' => 'student_id'
)
);
A Tutor hasMany Appointments...
class Tutor extends AppModel {
var $hasMany = array (
'Appointment' => array (
"foreignKey" => 'tutor_id'
)
);
An Appointment belongsTo a Student and a Tutor...
class Appointment extends AppModel {
var $belongsTo = array (
'Student' => array (
'foreignKey' => 'student_id'
),
'Tutor' => array (
'foreignKey' => 'tutor_id'
)
);
When looking at a student's record (e.g. 'app/student/view/4') I need to be able to list the dates of their upcoming appointments and the name of the tutor for that appointment. So I need to access data from the Tutor model (name) while looking at the Student model. Right now I have only been able to accomplish this using $this->Student->query() to pull the related tutor records, but this results in the student's information repeating in the resulting array.
All of the $hasMany and $belongsTo relationships work just fine. Does CakePHP have a built-in function that I am missing to get the related information, or does this need to be done longhand somewhere?
You should consider using Containable. In case you're not familiar with it, it's a Behavior which you can attach to models and use it to define precisely which associated models are to be included in a find, as many models and as deep as you like.
I always use it for all models, by setting it in AppModel:
var $actsAs = array('Containable');
Then in the controller:
$this->Student->find('first', array(
'conditions' => ...,
'contain' => array('Appointment' => 'Tutor'),
...
));
When I was working on my current project, I ran into a rather complex issue. I'll point out my problem much more detailed right now:
There are three Models: User, UsersExtendedField and UsersExtended.
UsersExtendedField contains custom fields that can be managed manually. All custom fields can be shown in the Users view as well, and be filled out of course. The values are then stored in UsersExtended, which has got two foreignKeys: user_id and field_id.
The relations look like this: User hasMany UsersExtendedField, UsersExtendedField hasMany UsersExtended, UsersExtended belongsTo User, UsersExtendedField.
The problem: When accessing the Users view, a form with user information input is shown. Any UsersExtendedFields are available as well, and since these hasMany UsersExtended, they've got plenty of UsersExtended values. But I want to reduce those to only the value(s) that belong to the User, whose view is shown at the moment. Here are my (desired) relations:
Croogo::hookBehavior('User', 'Crooboard.ExtendedUser', array(
'relationship' => array(
'hasMany' => array(
'UsersExtendedField' => array(
'className' => 'Crooboard.UsersExtendedField',
'foreignKey' => '',
'conditions' => array('status' => 1)
),
),
),
));
class UsersExtendedField extends AppModel {
var $name = 'UsersExtendedField';
var $displayField = 'fieldname';
var $hasMany = array(
'UsersExtended' => array(
'className' => 'Crooboard.UsersExtended',
'foreignKey' => 'field_id',
'conditions' => array(
'UsersExtended.user_id = User.id'
)
),
);
}
This is not the full code, these are the important parts. The problem starts right where I wrote 'UsersExtended.user_id = User.id'. Obviously, this won't work. But I do not have any idea how to access the User.id here. I also could not imagine a HABTM structure to solve this task. Do you have any idea how to get the semantics of this 'UsersExtended.user_id = User.id' to work?
Thank your very much for taking the time to read through this and helping me!
It sounds like you need to set up your HABTM relationship properly.
You already have the join table, UsersExtended, which contains your foreign keys.
Remove all previous relationships and set up HABTM in each of your User and UserExtendedField models.
The relationship code in your User model would look like this:
var $hasAndBelongsToMany = array(
'UsersExtended' => array(
'className' => 'UsersExtended',
'joinTable' => 'UsersExtended', //assuming this is the
//name of that model's table
'foreignKey' => 'user_id',
'associationForeignKey' => 'field_id'
)
);
For more information check out the page in the cakephp book
In addition, this blog post helped me grasp the relationship concepts when I was learning cakephp.
say you have 3 models : user, hair_color, and eye_color
user hasOne hair_color
user also hasOne eye_color
however
var $hasOne = 'hair_color';
var $hasOne = 'eye_color';
obviously wont work. So how do you implement many hasOne relationships in a single model?
I assume the answer is in the cookbook, Im going over that area now, I suspect it has something to do with passing an array to $hasOne, but no example of doing this.
var $hasOne = array('HairColor', 'EyeColor');
// hasOne is an array of model names **not file names**
OR
var $hasOne = array(
'HairColor' => array(
'className' => 'HairColor',
...
),
'EyeColor' => array(
'className' => 'EyeColor',
...
)
);
You should read manual http://book.cakephp.org/view/80/hasOne
I have two table
1. Airline -id(primary), name
2. Form - id(primary), operator, other unwanted fields
I want to relate Airline.name to Form.operator. Is it possible since Form.operator is not primary key, if yes give me the query.
Can some one also guide me as how will the cakephp model relation be in this case
I would advise you to not use the name Form as is it used elsewhere in the system, however try this (or something similar) and read http://book.cakephp.org/view/1039/Associations-Linking-Models-Together
In app/models/airline.php:
<?php
class Airline extends AppModel
{
var $name = 'Airline';
var $hasOne = array(
'Form' => array(
'className' => 'Form',
'foreignKey' => 'operator')
);
// other stuff
// ... //
?>
In app/models/form.php:
<?php
class Form extends AppModel
{
var $name = 'Form';
var $belongsTo = array(
'Airline' => array(
'className' => 'Airline',
'foreignKey' => 'operator')
)
;
// other stuff
// ... //
?>
var $hasOne = array(
'airline' => array(
'className' => 'airline',
'foreignKey' => false,
'conditions' => array(
'`form`.`yourfield` = `airline`.`yourfield`'
)
)
}
This should work. just replace your fields
in order to make the relations, as Leo suggested, work, you have to follow the cake conventions. In order to save you some headaches later on, I would therefore suggest the nicely written and short material here and here. You will learn e.g. that a good foreign key for which cakephp can do some lifting for you is named operator_id, instead of simply operator (if operator is not yet a foreign key, it could be that you have a database design issue).
Lifting here refers to automatically recognizing relations once defined in e.g. a $belongsTo.
select * from `airline`, `form` where `airline.id`=`form.operator`