can a table have hasMany relation with multiple table - cakephp

Will the given below code can work where Mark and Subject are two model with which Student model associate through hasMany association
class Student extends AppModel
{
public $name = 'Student';
var $hasMany = array(
'Mark' => array(
'className' => 'Mark',
'foreignKey' => 'student_id'
),
'Subject' => array(
'className' => 'Subject',
'foreignKey' => 'student_id'
)
);
}

yes you can relationship with many tables
http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html
Find conditions with hasMany model

Related

Acces data from non-direct related model

I have a big question, i have 3 days now trying to find the solution. I explain
I have 3 models: Comprobantes, Receptores and Puestos.
Comprobantes have a field called receptor_id which gives you the receptor and
Receptor have a field call puesto_id which gives you the puesto, something like
Comprobantes access to Receptores and Receptores access to Puestos, the thing now is that I had made a relation to show the field puesto from Puestos of my Receptor in the Comprobantes Model the only problem i had is that only the id is shown and i want to show the field "puesto" from Puesto not the "id" from Puesto.
edit: This is the code but Comprobantes dont have a direct relation with Puestos
class Puesto
{
var $hasMany = array(
'Receptor' => array(
'className' => 'Receptor',
'foreignKey' => 'puesto_id'
)
);
}
class Receptor
{
var $belongsTo = array(
'Emisor' => array(
'className' => 'Emisor',
'foreignKey' => 'emisor_id'
),
'Puesto' => array(
'className' => 'Puesto',
'foreignKey' => 'puesto_id'
)
);
}

Model linking in CakePHP

In this example, how do you create the "assignments-to-teachers" relationship in the models?
assignments subjects teachers
--------- --------- ------
id id id
student_id subject_name teacher_name
subject_id teacher_id
I want an SQL query that shows: assignment_id, student_id, subject_name, teacher_name. I used a "belongsTo" to create the "assignments-to-subjects" relationship, but I'm not sure how to create the "assignments-to-teachers".
AssignmentsController.php
public function index() {
$this->set('assignments', $this->Assignment->find('all'));
}
--------------------------
Assignment.php
public $belongsTo = array(
'Subject'
);
I did get this to work by adding joins to the "find('all')" in the controller, but I'm wondering how to do this in the models.
AssignmentsController.php
//(working, but looking to solve this in models, not controller)
$this->set('assignments', $this->Assignment->find('all', array(
'joins' => array(
array(
'table' => 'subjects',
'alias' => 'Subject',
'type' => 'LEFT',
'conditions' => 'Assignment.subject_id = Subject.id'
),
array(
'table' => 'teachers',
'alias' => 'Teacher',
'type' => 'LEFT',
'conditions' => 'Subject.teacher_id = Teacher.id'
)
),
'fields' => array('*','Subject.subject_name', 'Teacher.teacher_name')
)));
As far as I can tell, assignments are related to teachers through subjects, right? Then, on Subject model:
public $belongsTo = array('Teacher');
Also, on AppModel, use Containable behavior:
public $actsAs = array('Containable');
Now, you can do a find on assignment this way:
$this->Assignment->find('all', array(
'fields' => array('id', 'student_id')
'contain' => array(
'Subject' => array(
'fields' => array('id', 'subject_name')
'Teacher' => array(
'fields' => array('id', 'teacher_name')
)
)
)
));
Containable behavior will let you do a deep search through related models

CakePHP Many To Many With Conditions

I'm newbie on CakePHP, and now I'm stuck on many to many situation
ok, i have 3 Table :
questions
with fields (id, question)
question_product
with fields (id, question_id, product_id, question_number, is_enabled)
products
with fields (id, name, code, is_enabled)
so when i want to select questions with specific field, i don't know how to fix it
for now, my code is like this :
Question.php (Model)
class Question extends AppModel {
public $hasAndBelongsToMany = array (
'Product' => array (
'joinTable' => 'question_product',
'foreignKey' => 'question_id',
'associationForeignKey' => 'product_id',
'unique' => 'keepExisting',
'order' => 'question_number',
'fields' => array (
'QuestionProduct.question_number',
'Product.id',
'Product.name'
),
'conditions' => array (
'QuestionProduct.is_enabled' => 1,
)
)
);
}
QuestionsController.php (Controller)
public function loadQuestions($productId) {
$this->view = 'load_questions';
$questions = $this->Question->find('all', array (
'fields' => array (
'Question.id',
'Question.question',
'Question.is_optional',
'Question.reason_optional',
'Question.text_size'
),
'conditions' => array (
'QuestionProduct.product_id' => $productId
)
));
$this->set($questions);
}
method loadQuestions have one parameter to select with specified product
if i using sql query, it will be like this
select all from Question with condition Product.product_id=4, sorted by QuestionProduct.question_number ascending
select questions.*
from questions
join question_product on questions.id=question_product.question_id
join products on products.id=question_product.product_id
where products.id=4
order by question_product.question_number;
any answer will be appreciated :)
Thanks !
Any time you use a many-many (HABTM) relation with any other field that requires conditions, it is no longer many-many as far as Cake is concerned. You want the HasManyThrough relationship
Instead of using hasAndBelongsToMany relation, use two belongsTO relation from question_product to questions and another time from question_product to products.
question_product belognsTo questions
question_product belongsTo products
NOTE:you should change the table name from question_product to question_products as cakePHP convention
in your model QuestionProduct model :
<?php
// declares a package for a class
App::uses('AppModel', 'Model');
class QuestionProduct extends AppModel {
/**
* #see Model::$actsAs
*/
public $actsAs = array(
'Containable',
);
/**
* #see Model::$belongsTo
*/
public $belongsTo = array(
'Product' => array(
'className' => 'Product',
'foreignKey' => 'product_id',
),
'Question' => array(
'className' => 'Question',
'foreignKey' => 'question_id',
),
);
then in your Controller :
public function loadQuestions($productId) {
$this->view = 'load_questions';
$questions = $this->QuestionProduct->find('all', array (
'fields' => array (
'Question.id',
'Question.question',
'Question.is_optional',
'Question.reason_optional',
'Question.text_size'
),
'conditions' => array (
'QuestionProduct.product_id' => $productId
),
'contain' => array('Product','Question')
));
$this->set($questions);
}
It should make exactly the query you want, and I don't think it has any other way to produce that query.

Models with two hasOne relations to same table

I'm building an MMA (mixed martial arts) website with CakePHP. I've got a fights table in my database that has three columns at its simplest: id, fighter_a, and fighter_b.
I'm having trouble getting my head around what type of relation my Fight model would have with my Fighter module. Am I right in thinking fighter_a and fighter_b would be two hasOne relations?
I tried this with the following in my Fight model:
<?php
class Fight extends AppModel {
public $name = 'Fight';
public $hasOne = array(
'FighterA' => array(
'className' => 'Fighter',
'foreignKey' => 'fighter_a'
),
'FighterB' => array(
'className' => 'Fighter',
'foreignKey' => 'fighter_b'
)
);
}
And then this in my Fighter model:
<?php
class Fighter extends AppModel {
public $name = 'Fighter';
public $hasMany = array(
'Fight'
);
}
But this threw an error in my CakePHP application when calling $this->Fight->findById($id) (where $id was the ID of a fighter):
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Fight.fighter_id' in 'field list'
How can I link my models so that I can call all fights a fighter has been in?
Distilled from conversation under the question, the solution would be this:
Rewrite the $hasMany in your FighterModel to look like:
public $hasMany = array(
'Fight' => array(
'className' => 'Fight',
'finderQuery' => 'SELECT * FROM fights AS Fight WHERE Fight.fighter_a_id = {$__cakeID__$} OR Fight.fighter_b_id = {$__cakeID__$};'
)
);

Associations in CakePHP with non-conventional database

We are converting an application for use with CakePHP 2.0.3.
For some reason, I cannot seem to set proper relations between my models.
Here's an example:
User (id, petid, country, picid, ...)
Pet (id, userid, picid, ...)
Picture (id, albumid, ....)
Album (id, userid, petid, ...)
The meanings of these are the following:
- A user can have multiple pets, but can only have selected one pet at the same time (therefore, petid in User)
- Pets belong to one user
- Pets and Users can have multiple pictures, but only one profile picture, therefore Pet.picid and User.picid
- Pets and users can have multiple Albums
I set up my models in CakePHP, but I cannot figure out which relations to use between them since the Database is not following the conventions.
I've tried the following:
User
-> hasMany(Pets)
-> hasOne(Picture)
-> hasMany(Album)
Pet
-> belongsTo(User) (works fine, with foreignkey userid)
-> hasMany(Album)
-> hasOne(Picture)
Album
-> hasMany(Picture)
---- Logic to achieve this? It either belongs to a user or pet-----
-> belongsTo(User)
-> belongsTo(Pet)
Picture
-> belongsTo(Album)
I'm new to CakePHP and cannot figure out the way to go here.
Do you have any suggestions?
I would suggest using Aliases in your relationships which will help get your head around the data being returned.
For example, your User model could use SelectedPet and ProfilePicture in it's associations:
User.php model
/**
* belongsTo associations
*
* #var array
*/
public $belongsTo = array(
'SelectedPet' => array(
'className' => 'Pet',
'foreignKey' => 'petid'
),
'ProfilePicture' => array(
'className' => 'Picture',
'foreignKey' => 'picid',
)
);
/**
* hasMany associations
*
* #var array
*/
public $hasMany = array(
'Album' => array(
'className' => 'Album',
'foreignKey' => 'userid',
'dependent' => false
),
'Pet' => array(
'className' => 'Pet',
'foreignKey' => 'userid',
'dependent' => false
)
);
Your Pet model could use ProfilePicture as well:
/**
* belongsTo associations
*
* #var array
*/
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'userid'
),
'ProfilePicture' => array(
'className' => 'Picture',
'foreignKey' => 'picid'
)
);
/**
* hasMany associations
*
* #var array
*/
public $hasMany = array(
'Album' => array(
'className' => 'Album',
'foreignKey' => 'petid',
'dependent' => false
)
);
Picture model:
/**
* belongsTo associations
*
* #var array
*/
public $belongsTo = array(
'Album' => array(
'className' => 'Album',
'foreignKey' => 'albumid'
)
);
..and finally your Album model:
/**
* belongsTo associations
*
* #var array
*/
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'userid'
),
'Pet' => array(
'className' => 'Pet',
'foreignKey' => 'petid'
)
);
/**
* hasMany associations
*
* #var array
*/
public $hasMany = array(
'Picture' => array(
'className' => 'Picture',
'foreignKey' => 'albumid',
'dependent' => false
)
);
With regards to the logic of an Album belonging to a User or a Pet, you could just handle this in your controller when saving data or returning it. I.e User is given preference over Pet.
I hope this helps.

Resources