How to use one table multiple times? - cakephp

I have a table called flights in which I set the departure and arrival airport. The airports is just another table and I want just to use the airport id in the flights table. How can I do this?, normally I can only use one id (airport_id) how can I use the second one? something like airport_id_2 ?..
My Flight model looks like this:
class Flight extends AppModel{
public $hasOne = "Airport";
}
Or should I do this manually by using joins?

you can use two fields:
arrival_airport_id
departure_airport_id
and in your Model
public $belongsTo = array(
"DepartureAirport" => array(
'className' => 'Airport',
'foreignKey' => 'departure_airport_id'
),
"ArrivalAirport" => array(
'className' => 'Airport',
'foreignKey' => 'arrival_airport_id'
)
)
PS: I think the right relationships is belongsTo and not HasOne because one airport can be related to many flights

Related

CakePHP Join virtualField as displayField

I'm trying to do one of two things, use a virtual field from a model as the display field in my join model, or use the virtual field as the display in a find('list') on my join model.
Here's the current layout:
MODELS
<?php
class Participant extends AppModel {
public $hasMany = array('Registration');
public $virtualFields = array(
'full_name' => 'CONCAT(last_name, ", ", first_name)'
);
public $displayField = 'full_name';
}
-----
class Contest extends AppModel {
public $hasMany = array('Registration');
}
-----
class Registration extends AppModel {
public $belongsTo = array('Participant', 'Contest');
public $hasMany = array('Assignment');
}
?>
Tables are as follows:
participants contests registrations
------------ --------- --------------
id id id
first_name name contest_id
last_name participant_id
In my contests controller I'm trying to develop a list to be viewed as checkboxes in the view.
Here is the excerpt from my contests controller:
$this->loadModel('Registration');
$this->set('registrations', $this->Registration->find(
'list',
array(
'conditions' => array('contest_id' => $contestId),
'recursive' => 1
)
)
);
//$contestId is defined previously, and I have verified such.
This all actually runs fine as it is, and in the view will display a column of checkboxes with the registration_id as the label next to the checkbox.
I would like to get a full_name as is defined in the Participant model to be the displayField of the Registration model. I've been searching and can't quite seem to find a good way of doing that. I hope I have been descriptive enough, and please let me know if you have any questions and I'll try to explain better. Thank you.
edit: I'm using CakePHP 2.4.
try to add the 'fields' parameter
$this->loadModel('Registration');
$this->set('registrations', $this->Registration->find(
'list',
array(
'fields' => array('Registration.id', 'Participant.full_name'),
'conditions' => array('contest_id' => $contestId),
'recursive' => 1
)
));
edit: apparently cake does not place virtual fields of associated models when using find() with 'fields' options.
So you have to build your array by yourself, hoping your models use the containable behavior
$registrations = $this->Registration->find(
'all',
array(
'contain' => array(
'Participant' => array('full_name')
),
'conditions' => array('contest_id' => $contestId),
)
);
$registrations = Hash::combine($registrations, '{n}.Registration.id', '{n}.Participant.full_name');
$this->set('registrations', $registrations);

CakePHP Access a different table my view

I have two tables Contact and Quote, this is a one to many relationship (i.e. one contact can have many quotes). Foreign keys are all setup correctly.
When I go to create a new quote I want to be able to select from a drop down list of contacts.
My code looks like this:
Contact Model:
class Contact extends AppModel {
public $hasMany = array('Quote' => array('className' => 'Quote', 'foreignKey' => 'contact_id'));
}
Quote Model
class Quote extends AppModel {
public $belongsTo = array('Contact' => array('className' => 'Contact', 'foreignKey' => 'contact_id'));
public $validate = array(
'name' => array(
'rule' => 'notEmpty'
),
'amount' => array(
'rule' => 'notEmpty'
)
);
}
Add method in QuotesController:
public function add() {
// TODO: Update this so the user can select the id from a drop down list.
$this->request->data['Quote']['contact_id'] = '1';
if ($this->request->is('post')) {
$this->Quote->create(); // This line writes the details to the database.
if ($this->Quote->save($this->request->data)) {
$this->Session->setFlash('Your quote has been saved.');
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash('Unable to add your quote.');
}
}
}
As you can see I'm currently just hard coding the user id as part of the add process.
I'm assuming you have read and are using this method in your view.
http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::select
Less easy to find (or easier to overlook) is this:
http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#find-list
So in your controller you want to do
$contacts = $this->Article->find('list', array('fields' => array('Contact.id', 'Contact.name'));
$this->set(compact('contacts'));
Then in the view:
echo $this->Form->select('contact_id', $contacts);
Modify the fields for the find to reflect what is actually in your model. And if you need fields combined, you can possibly do it with virtual fields: http://book.cakephp.org/2.0/en/models/virtual-fields.html. Otherwise you can select the fields that need to be composited and use a foreach loop to combine them into a id=>[displayed value] array to pass on to the view. Only the id is the important thing and has to correspond to an id in the Contacts table.

Translate from two tables with i18n database tables (cakePHP)

I have four tables:
gallery_categories table:
id (int);
title (varchar);
gallery_pictures table:
id (int);
title (varchar);
gallery_categories_gallery_pictures table to joint above tables:
gallery_category_id (int);
gallery_picture_id (int);
and the i18n table:
id (int)
locale (varchar)
model (varchar)
foreign_key (int)
field (varchar)
content (text)
I tried:
$this->GalleryCategory->bindModel(array(
'hasOne' => array(
'GalleryCategoriesGalleryPicture',
'GalleryPicture' => array(
'className' => 'GalleryPicture',
'foreignKey' => false,
'conditions' => array('GalleryPicture.id = GalleryCategoriesGalleryPicture.gallery_picture_id')
))));
$galleryCategories = $this->GalleryCategory->find('all', array(
'fields' => array('GalleryCategory.*','GalleryPicture.*')
));
But all time it returns with the right Category table fields and wrong Pictures table fields...
The Category fields contain the right translated words.
The Pictrures fields contain the wrong translated words.
The Models:
class GalleryCategory extends AppModel
{
public $tablePrefix = 'ef_';
var $name = 'GalleryCategory';
public $actsAs = array('Translate' => array(
'title' => 'titleTranslation'
)
);
}
class GalleryPicture extends AppModel
{
public $tablePrefix = 'ef_';
var $name = 'GalleryPicture';
public $actsAs = array('Translate' => array(
'title' => 'titleTranslation'
)
);
}
How could I get the right translated words from both table?
ps: The translation with "i18n Database Tables" works right with only one table (exp: only GalleryCategory or only GalleryPicture).
Translation doesn't work with associated models, see the last couple of lines here:
Note that only fields of the model you are directly doing find on will be translated. Models attached via associations won’t be translated because triggering callbacks on associated models is currently not supported.
Update
It might be tricky, as you have a HABTM relationship - previously I have worked around this by adding a second data retrieval to the afterFind callback of a model, but this was with a simpler association. Hope this helps.

CakePHP HABTM relationship table joins

I have a 'patient_cases' table with a HABTM relationship with a 'procedures' table. This 'procedures' tables has a many to one relationship with 'consultants' table, which then has a many to one relationship with 'specialties' table.
The relationships are working fine and using cakephp debug tool bar i can see everything is coming through correctly when i look at 'patient_cases' index page, however i'm only getting consultant_id and specialty_id rather than all of the fields with that associated model.
which is what should be happening i believe -
In CakePHP some associations (belongsTo and hasOne) performs automatic
joins to retrieve data, so you can issue queries to retrieve models
based on data in the related one.
But this is not the case with hasMany and hasAndBelongsToMany
associations.
I want to be able to get the consultant name from 'consultants' table using procedures.consultant_id and get the specialty name from 'specialties' using consultant.specialty_id.
I have tried playing about with some table joins but with no success,
class PatientCase extends AppModel {
public $hasAndBelongsToMany = array(
'Procedure' => array(
'className' => 'Procedure',
'joinTable' => 'patient_cases_procedures',
'foreignKey' => 'patient_case_id',
'associationForeignKey' => 'procedure_id',
'unique' => true
)
);
}
class Procedure extends AppModel {
public $belongsTo = array(
'Consultant' => array(
'className' => 'Consultant'
)
);
}
class Consultant extends AppModel {
public $belongsTo = array(
'Specialty' => array(
'className' => 'Specialty',
'conditions' => array('Specialty.active' => 1)
)
);
public $hasMany = array(
'Procedure'
);
}
class Specialty extends AppModel {
public $hasOne = array(
'Consultant'
);
);
}
$this->set('patientCases', $this->PatientCase->find('all'));
Returns everything i need, each model array is returned (other relationships not mentioned here), however the model array 'Consultant' is not returned, which also means i can not get the 'Specialty' data which is linked to the 'Consultant' model
EDIT
I have managed to get the data i need by using this in my PatientCasesController
$this->set('patientCases', $this->PatientCase->find('all'));
$this->set('patientCaseProcedures', $this->PatientCase->Procedure->find('all'));
However, ideally i want to return everything in the one 'patientCases', is this possible?
EDIT
I have solved the problem using the recursive function
$this->PatientCase->recursive = 3;
$this->set('patientCases', $this->PatientCase->find('all'));

Add a friend feature in CakePHP

I need a simple add a friend feature in my application, through some research, I would need a join table linking back to users table ? something like this: (I already have a users table)
Users-Friendships-Users
Can anyone give more details about this?
The friendships table should have following columns:
id Integer
user_from (the user who requested friendship)
user_to (the user who accepted friendship)
created (optional to track when your friendship started)
Then you need to create proper Model relation.
class User extends AppModel {
...
var $hasMany = array(
'UserFrom'=>array(
'className'=>'Friendship',
'foreignKey'=>'user_from'
),
'UserTo'=>array(
'className'=>'Friendship',
'foreignKey'=>'user_to'
)
);
var $hasAndBelongsToMany = array(
'Friendship' => array(
'className' => 'User',
'joinTable' => 'friendships',
'foreignKey' => 'user_from',
'associationForeignKey' => 'user_to'
);
...
}
class Friendship extends AppModel {
...
var $belongsTo = array(
'UserFrom'=>array(
'className'=>'User',
'foreignKey'=>'user_from'
),
'UserTo'=>array(
'className'=>'User',
'foreignKey'=>'user_to'
)
)
...
}
This way you are defining 2 relation in each model. You can add HABTM relation too. Run bake script to build your controllers and views. Then in your code you can use something like this:
$this->User->UserFrom->find('all',
array(
'conditions'=>array('user_from'=>1),
'contain'=>array('UserTo')
)
);
This should return friends of user with ID 1 and all friends details.
Be careful with the recursive queries. :)

Resources