How to Retrieve fields from linked Models - php

I have the following three database tables:
Products
########
id
title
artist_id
Arists
######
id
profile
person_id
People
######
id
first_name
last_name
In my Product model how do I create a method to return the product title along with the artist's first_name?
I have set up the following model associations:
Product belongs to Artist
Artist belongs to Person

Containable is definitely the way to go for filtering related records. Make sure to add $actsAs = array('Containable') into your model or app_model.
Then you can do things like:
$this->Product->find('all', array(
'contain' => array(
'Artist' => array(
'Person' => array(
'id',
'first_name'
)
)
)
));

Assuming you already set the relationships in these models, you just need to set it recursive:
$this->Product->recursive = 2;
print_r($this->Product->find('all'));

Related

CakePHP Associations - hasMany but need to match column in 3rd table?

I am new to CakePHP (2.x) and am creating a post and comments feature. Everything works except I cannot figure out how to get the user's username out of the registrations (third) table (linked with "registration_id"). My associations currently look like:
class Article extends AppModel {
public $hasMany = array('ArticleComment');
public $belongsTo = array(
'ArticleRegistration' => array(
'className' => 'Registration',
'foreignKey' => 'Article.registration_id' //(doesn't work)
),
'ArticleCommentRegistration' => array(
'className' => 'Registration',
'foreignKey' => 'ArticleComment.registration_id' //(doesn't work)
)
);
class ArticleComment extends AppModel {
public $belongsTo = array('Registration','Article');
I am not sure if the associations from ArticleComment are being applied since it is being called through the Article model. I am retrieving the data by:
$this->set('articles', $this->Article->find('all', array('order' => 'Article.created desc', 'limit' => '3')));
I have tried a join and passing two separate variables for the articles and comments array but then I have to remove my associations which leads me to believe it's not proper coding.
Tables are:
articles
__________
id
registration_id
body
article_comments
__________
id
article_id
registration_id
body
registration
__________
id
username
I am fetching the information with:
$this->set('articles', $this->Article->find('all', array('order' => 'Article.created desc')));
TIA!
The generated SQL query from cakephp when you make a find() call is as follows
SELECT `Article`.`id`,
`Article`.`registration_id`,
`Article`.`body`,
`Registration`.`id`,
`Registration`.`username`
FROM `test`.`articles` AS `Article`
LEFT JOIN `test`.`registration` AS `Registration`
ON (`Article`.`registration_id` = `Registration`.`id`)
WHERE 1 = 1 LIMIT 20
So, in order to access the username you just need to write something like this in your view
$articles['Registration']['username'];
I recommend you to use the cakephp bake commands, I could make this proyect like in 10 minutes with them. And also I recommend using Netbeans as IDE, the cakephp plugin is awesome.
Here is a link to an example project that you can clone with git.

Proper Method For Setting Up One-to-One in CodeIgniter Datamapper

I am reviewing all of my models and corresponding tables for CodeIgniter Datamapper. I'm wondering what the correct way of setting up a one-to-one relationship with a defined parent and child is. The way I have been doing it is similar to this:
class Customer ... {
public $has_one = array('address');
}
class Address ... {
public $has_one = array('customer');
}
with the Customer being the parent (ie, has either one or zero Addresses) and the address being the child (always has one Customer). In the database I have a customer_id on addresses which is not null, indexed and associated with customer.id and set to CASCADE on update and delete , and address_id on customers which is null and associated with address.id and set to NO ACTION on update and delete.
Is this the proper configuration for a CI Datamapper one-to-one-or-zero (parent/child) relationship?
There is a good explanation in the FAQ section of the docs:
When configuring a relationship, even a self-relationship, you must define both "sides" of the relationship. This means for a parent/child relationship, you have to specify the parent on the child, and you have to specify the child on the parent.
Here is an example for a complex self-relationship [User (as Boss) has many Employees, and Employees have one Boss]:
// In User
$has_one = array(
// define the relationship to the boss
'boss' => array(
'class' => 'user',
'other_field' => 'employee'
)
);
$has_many = array(
// define the relationship to the employees
'employee' => array(
'class' => 'user',
'other_field' => 'boss'
)
);

CakePHP: Multiple links to same model

Lets say each book has AuthorA and AuthorB fields.
Both fields are foreign keys for authors table.
table authors with fields: id | name
table books with fields: id | name | a_author_id | b_author_id |
How should controller, model and view be set up to be able to create a book with dropdown list of "author a" and "author b" both coming from author table? How would form-input for author-a (and author-b) look like inside "Add" view for Book model?
You need to setup 2 belongsTo association in your Book model with different aliases for Author model.
public $belongsTo = array(
'AAuthor' => array(
'className' => 'Author',
'foreignKey' => 'a_author_id'
),
'BAuthor' => array(
'className' => 'Author',
'foreignKey' => 'b_author_id'
)
);
Use $this->Book->AAuthor->find('list') to get the authors list and set the array to view and specify same array using 'options' key in Form->input() options for both a_author_id and b_author_id fields.

Cakephp - Multiple users with different profile fields

I have three different type of users with different columns for profiles.
I currently have Users table and Groups table with Users table linking to Groups.
How can I set it so that it picks up different type of profiles for each group users?
you can use $belongsTo relation for linking for both table, such that every user belongs to some group.
For that you need to create model of user. Try something like following code
class Users extends AppModel {
var $name = 'Users';
public $belongsTo = array(
'Groups' => array(
'className' => 'Groups',
'foreignKey' => 'group_id'
)
);
}

Model Associations and Data Modelling

I am developing a web app for an art gallery, and I want to check I have set up the data model correctly.
I have a people table and an artists table. Some of the people are artists and some are not.
I also have a products table and each product belongs to one artist.
Below is a simplified version of the tables:
products
********
id
title
artist_id
artists
*******
id
profile
rating
person_id
people
******
id
first_name
last_name
I need to be able to retrieve the name of the artist when performing the find() method on the Product model.
Have I set up the data model correctly and if so what is the best way to retrieve the artist's name without getting lots of unwanted data?
It's possible to use CakePHP's bindModel & unbindModel to build up relations that don't rely on Cake's automagic goodness.
Since you were interested in doing the find on the Product model, I'll set out an example that can be called from the Products controller:
// unbind Artist
$this->Product->unbindModel(array(
'belongsTo' => array('Artist')
));
// bind Artist & Person using explicit conditions
$this->Product->bindModel(array(
'hasOne' => array(
'Artist' => array(
'foreignKey' => false,
'conditions' => array('Artist.id = Product.artist_id')
),
'Person' => array(
'foreignKey' => false,
'conditions' => array('Person.id = Artist.person_id')
),
)
));
// return the person
$person = $this->Product->find('first', array(
'conditions' => array(
'Product.id' => 1 // or any other condition
),
'fields' => array(
'Person.first_name',
'Person.last_name'
)
));
What's happening here?
Firstly, we unbind the Product model's relationship with the Artist model.
Secondly, we bind the Artist and Person models by explicitly defining the relationships and disabling Cake's automatic forigenKey connections.
Lastly, we do a 'first' find on the Product model and only request the 'first_name' & 'last_name' of the Person.
Each 'Product' belongs to an 'Artist' and each 'Artist' hasAndBelongsToMany 'Product'
You will also need the following table:
artists_products
****************
id
product_id
artist_id
http://book.cakephp.org/#!/view/1044/hasAndBelongsToMany-HABTM

Categories