Acces data from non-direct related model - cakephp

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

Related

HABTM CakePHP no results for related model

I have problem with HABTM models. When I try to fetch any related model f.e. like this:
$this->Tagi->find('first');
I dont get any results for associated model. Result looks like this:
array(
'Tagi' => array(
'id' => '1',
'nazwa' => 'sth'
),
'Instytucje' => array()
)
I am sure that there should be result, I've double checked it, even
$this->Tagi->getDataSource()->getLog(false, false)
shows correct query, that fetches right results.
If you have any idea whats wrong plz give me a hint.
Tagi model:
public $hasAndBelongsToMany = array(
'Instytucje' =>
array(
'className' => 'Instytucje.Instytucje',
'joinTable' => 'instytucje-tagi',
'foreignKey' => 'tag_id',
'associationForeignKey' => 'instytucja_id',
'unique'=> true
)
);
Instytucje model:
public $hasAndBelongsToMany = array(
'Tagi' =>
array(
'className' => 'Instytucje.Tagi',
'joinTable' => 'instytucje-tagi',
'foreignKey' => 'instytucja_id',
'associationForeignKey' => 'tag_id',
'unique'=> true
)
);
EDIT:
Main problem is that HABTM refers to AppModel causing error:
Error: Table app_models for model AppModel was not found in datasource prod.
Which can be bypassed by adding $useTable in AppModel, which results in prior problem.
SOLVED
When using naming convention far beyond this Cake use, you have use third model with $useTable pointed on reference table.
Moreover its important to correctly point Cake to classes inside plugins.
I think you're problem relates to the fact that you are not using CakePHP's naming conventions. From the look of the query being generated Cake doesn't know how to correctly alias the join table, hence getting an AppModel alias in your query. I suspect that this is causing issues when Cake tries to build the results array from the query.
This might not work, but try creating a model for the joins table called InstytucjeTagi; then update your associations to use this using the with key:-
Tagi model:
public $hasAndBelongsToMany = array(
'Instytucje' =>
array(
'className' => 'Instytucje.Instytucje',
'joinTable' => 'instytucje-tagi',
'with' => 'InstytucjeTagi',
'foreignKey' => 'tag_id',
'associationForeignKey' => 'instytucja_id',
'unique'=> true
)
);
Instytucje model:
public $hasAndBelongsToMany = array(
'Tagi' =>
array(
'className' => 'Instytucje.Tagi',
'joinTable' => 'instytucje-tagi',
'with' => 'InstytucjeTagi',
'foreignKey' => 'instytucja_id',
'associationForeignKey' => 'tag_id',
'unique'=> true
)
);
If this doesn't fix it try using the afterFind() callback in the Tagi model to check what Cake is returning:-
afterFind($results, $primary = false) {
parent::afterFind($results, $primary);
// Print out the $results to check what Cake is returning.
debug($results);
return $results;
}

cakephp saveAssociated with different aliases in models

I want to use aliases in cakephp(2.5.3) models which names are different from the name of the related model. The problem occures when I want o save data with saveAssociated method. My models have hasMany and belongsTo relations. When I want to save data it says there is na error. I dig the problem and think that this could be a problem with validateAssociated method which can change $data value or my knowledge of CakePHP is still on newbe level... Can anyone explain me what may I do wrong ?.
My Model A:
public $hasMany = array(
'alias1' => array(
'className' => 'AB',
'foreignKey' => 'a_id'
),
);
My Model AB:
public $belongsTo = array(
'alias2' => array(
'className' => 'A',
'foreignKey' => 'a_id'
),
'alias3' => array(
'className' => 'B',
'foreignKey' => 'b_id'
),
);
I try to save data with:
$this->alias2->alias1->saveAssocated($this->request->data)
Any idea ?

CakePHP 2.0: display associated records

I know the solutions is simple and might have something to do with the Containable behavior but I can't get it working. Without all the tries
This is the case. I'd like to display the Event details of an Event (eg. a conference). Each event takes place in a EventVenue and each EventVenue is located in a Country.
So in the Country Model the following is present:
public $hasMany = array(
'EventVenue' => array(
'className' => 'EventVenue',
'foreignKey' => 'country_id'
))
In the EventVenue model a BelongsTo association is made
public $belongsTo = array(
'Country' => array(
'className' => 'Country',
'foreignKey' => 'country_id'
))
And in the Event model a hasOne association is made
public $hasOne = array(
'EventVenue' => array(
'className' => 'EventVenue',
'foreignKey' => 'event_id',
))
What I want is to display the country name on the page that is renderd in the EventsController. I do get all the Event and EventVenue data but the associated Country for the venue is not retrieved.
The data is retrieved in the following way
$item = $this->Event->findBySlug($slug);
How can I also get the country name (eg. Netherlands) retrieved from the database? I tried something like this but that did not work:
$item = $this->Event->findBySlug($slug,array(
'contain' => array(
'Event' => array(
'EventVenue' => array(
'Country'
)
)
)
)
Try this:
$item = $this->Event->findBySlug($slug,array(
'contain' => array(
'EventVenue' => array(
'Country'
)
)
);
Update
Turns out findBy does not support Containable. You could use this to get the desired result:
$item = $this->Event->find('first',array(
'conditions' => array(
'Event.slug' => $slug
),
'contain' => array(
'EventVenue' => array(
'Country'
)
)
);
Oh and make sure you have this in the model: public $actsAs = array('Containable');
try this method:
$this->Event->recusive = 2;
$item = $this->Event->findBySlug($slug);
You need to set the recursive to 2 before you make the find, something like this
$this->Event->recursive = 2;
with this, you'll get the Event, the EventVenue and the Country on one shot
Hope it helps

what is CakePHP model alias used for?

In user model:
var $hasMany = array(
'Photo' => array(
'className' => 'Photo',
'foreignKey' => 'owner_id',
...
),
);
In photo model:
var $belongsTo = array(
'Owner' => array(
'className' => 'User',
'foreignKey' => 'owner_id',
...
),
);
Here one user has many photos.
So what my question is that here the alias name is 'Owner', which make me clear to understand the exact meaning of 'User', but is this the only reason to use alias? does it affect 'Photo' in user model? or how to use 'Owner' in/by cakephp?
I don't quite understand the meaning of alias in model.
Appreciate your help!
Two useful scenarios for aliases:
1. Multiple foreign keys to the same model
For example, your photos table has two fields: created_user_id & modified_user_id
var $belongsTo = array(
'CreatedUser' => array(
'className' => 'User',
'foreignKey' => 'created_user_id',
...
),
'ModifiedUser' => array(
'className' => 'User',
'foreignKey' => 'modified_user_id',
...
),
);
2. Creating logical words specific to your application's domain
Using the conditions field in the array, you could specify different kinds of models:
var $hasMany = array(
'ApprovedUser' => array(
'className' => 'User',
'foreignKey' => 'group_id',
'conditions' => array(
'User.approved' => 1,
'User.deleted' => 0
),
...
),
'UnapprovedUser' => array(
'className' => 'User',
'foreignKey' => 'group_id',
'conditions' => array(
'User.approved' => 0,
'User.deleted' => 0
),
...
),
'DeletedUser' => array(
'className' => 'User',
'foreignKey' => 'group_id',
'conditions' => array('User.deleted' => 1),
...
),
);
In the above example, a Group model has different kinds of users (approved, unapproved and deleted). Using aliases helps make your code very elegant.
It allows you to do things like $this->Owner->read(null,$userId); You can have an OwnersController and views/owners.
It is ... an alias. In a sense, User is an alias for the db table users.
A better example: I have a CMS where I use the table articles for Article, BlogItem and News. Those three names are aliases for the same table that allow me to set up different models, relationships and behaviour. So I have a BlogItemsController and a NewsController as well as an ArticlesController.

CakePhp: On the fly associations using a re-named Model field?

I'm trying to use on the fly associations to trim down the data I retrieve, but the model I'm using is associated to other models with a re-named field because I have 2 of the same models associated with it.
So, here's the model, say 'test', that has two 'user' fields, both related to the User model.
In the model:
var $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id'
),
'User_Watched' => array(
'className' => 'User',
'foreignKey' => 'user_id_watched'
)
);
When I retrieve data related to 'test', I want to only retrieve particular data linked to the 'User' and 'User_Watched' fields without any other nested information.
But when I do:
$this->User->unbindModel(array('hasMany' => array('something1', 'something2')), false);
then something1 and something2 data does not show up for the 'User' field of model 'test', but is still retrieved for the 'User_watched' field.
Can I not retrieve unwanted data for the 'User_watched' field?
Hope this makes sense... :)
KcYxA,
Containable behavior might help a lot in this case, as benjamin mentioned, your "find" queries would look like:
$this->User->find('first', array(
'conditions' => array('User.id' => $id),
'contain' => array('UserWatched')
));
In this case, you won't have to use unbindModel method. In this example, you'll get User and UserWatched data.
If you need only User data from "find", then tell Cake to "$this->User->contain();" so it won't go further then User model.
to use on the fly associations to trim
down the data I retrieve
Good idea.
'foreignKey' => 'user_id_watched'
should possibly be:
'foreignKey' => 'user_watched_id'.
Edit 1: At least this would make sense according to my current understanding. If user_id is a correct foreign key(FK), which cakephp uses to unbind the relations, but user_id_watched isn't, than your described behavior is explained.
Edit 2: The Containable behavior gives you another tool for controlling associated models.
Change $primaryKey in fly, run controller
Sample:
// Models
//....
class PreProductoDescripcion extends AppModel {
/**
* Primary key field
*
* #var string
*/
public $primaryKey = 'id_producto_descripcion';
//....
//....
}
class SenasaPedidosDetalles extends AppModel {
/**
* Display field
*
* #var string
*/
public $displayField = 'cod_tango';
public $belongsTo = array(
'SenasaPedidos' => array(
'className' => 'SenasaPedidos',
'foreignKey' => 'senasa_pedidos_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'PreProductoDescripcion' => array(
'className' => 'PreProductoDescripcion',
'foreignKey' => 'cod_tango',
//'conditions' => array('SenasaPedidosDetalles.cod_tango' => 'PreProductoDescripcion.codigo'),
'fields' => '',
'order' => ''
)
);
//....
#
// Controller Fly
//...
$this->SenasaPedidos->Behaviors->load('Containable');
$this->SenasaPedidos->SenasaPedidosDetalles->PreProductoDescripcion->primaryKey = 'codigo';
$datos = $this->SenasaPedidos->find(
'first', array(
'fields' => array( 'SenasaPedidos.*' ),
'conditions' => array( 'SenasaPedidos.id' => $id ),
'contain' => array(
'Usuarios' => array(
'fields' => array( 'Usuarios.apellido_nombre' )
),
'Clientes' => array(
'fields' => array( 'Clientes.razon_social' )
),
'Provincias' => array(
'fields' => array( 'Provincias.nombre' )
),
'Transportes' => array(
'fields' => array( 'Transportes.razon_social' )
),
'SenasaPedidosDetalles' => array(
'fields' => array( 'SenasaPedidosDetalles.*' ),
'PreProductoDescripcion' => array(
'fields' => array(
'PreProductoDescripcion.id_producto_descripcion',
'PreProductoDescripcion.descripcion'
)
)
),
)
));
//...

Resources