Linking two tables with two (composite) foreign key relation - cakephp

Version: 3.2.1
Relations
Two columns from table B are associated with two columns from table A.
Table A -> hasMany -> table B
Table B -> belongsTo -> table A
B.a_id = A.a_id
B.a_name = A.a_name
Cookbook
No example found in the cookbook.
http://book.cakephp.org/3.0/en/orm/associations.html
How can I specify these relations? Already tried this:
$this->hasMany('B', [
'conditions' => ['A.a_id' => 'B.a_id', 'A.a_name' => 'B.a_name']
]);
And this:
$this->hasMany('B1', [
'foreignKey' => 'a_id',
'joinType' => 'INNER',
'className' => 'B'
]);
$this->hasMany('B2', [
'foreignKey' => 'a_name',
'joinType' => 'INNER',
'className' => 'B'
]);

Composite keys can be specified using arrays, this is supported for foreign keys as well as primary keys nearly everywhere.
$this->hasMany('B', [
'foreignKey' => [
'a_id',
'a_name'
],
'bindingKey' => [
'a_id',
'a_name'
]
]);
An example in the docs wouldn't hurt, you may want to open a ticket over at GitHub.
ps. hasMany associations do not support a joinType option.

Related

Unable to save associated (hasOne) data

I am creating a simple API with CakePHP 4, and I am having some issues saving some POST data. This is a new project, so the models are newly baked, based on my 3 tables: elaborations, details, jobs
The ElaborationTable table has these relations:
$this->hasOne('Details', [ // this (and the next) is the only thing that I've manually changed here: hasOne instead of hasMany
'foreignKey' => 'elaboration_id',
]);
$this->hasOne('Jobs', [
'foreignKey' => 'elaboration_id',
]);
While both DetailsTable and JobsTable have this:
$this->belongsTo('Elaborations', [
'foreignKey' => 'elaboration_id',
'joinType' => 'INNER',
]);
In my controller, this is what I'm using to retrieve the POST data and save it to each database table:
$data = $this->request->getData();
$data['user_id'] = $this->Auth->user('id');
$elaboration = $this->Elaborations->newEntity($data, [
'associated' => [
'Details',
'Jobs'
]
]);
Finally, my POST data is something like this:
APP/Controller/ElaborationsController.php (line 85)
[
'detail' => [
'regione' => 'Lazio',
'provincia' => 'RM',
'comune' => 'Roma',
],
'job' => [
'serramenti' => '1',
],
'user_id' => (int) 2,
]
Now, the user_id field gets saved in my elaborations table, no errors are issued, but still the details and jobs tables remains empty, no data is saved.
What am I doing wrong?

Error: SQLSTATE[42P01]: Undefined table: "Missing FROM-claouse entry for table

Hy I create a join query using cakephp find as shown below :
$test = $this->DiagnosisBind->find(
'all',
[
'table' => 'diagnosis_binds',
'alias' => 'dbinds',
'order' => 'dbinds.set_num ASC',
//'recursive' => 0,
'conditions' => [
'dbinds.deleted IS NULL',
'dbinds.diagnosis_id ='.$diagnosisData[0][0]['id']
],
'joins' => [
[
'type' => 'INNER',
'table' => 'diagnosis_treats',
'alias' => 'dtreats',
'conditions' => [
'dtreats.diagnosis_bind_id = dbinds.id'
]
],
[
'type' => 'INNER',
'table' => 'medical_masters',
'alias' => 'medmas',
'conditions' => [
'medmas.deleted IS NULL'
]
]
],
'fields' => [
'dtreats.id',
'dtreats.medical_name',
'dtreats.amount',
'dbinds.days'
]
]
);
When executing the query, I got this error :
I have read this post missing FROM-clause entry for table "Grupo" cakephp And solution is create a recursive (I have tried but failed) and use containable (I'm not suppose to create containable). So what's wrong in my find above. Thank you
Note:
I'm using cakephp 2.0
Postgresql
There are no table and alias options for query builder finders, they are only available for joins, so your main table will use the default alias as you can see in the query in the error message, and that alias is DiagnosisBind, hence using dbinds will cause an error.
Long story short, use DiagnosisBind instead of dbinds.
Side note, never ever inject data into single value conditions (or in the key of a key => value condition for that matter):
'dbinds.diagnosis_id ='.$diagnosisData[0][0]['id']
That's a possible SQL injection vulnerability!, always use the key => value syntax, or bindings:
'DiagnosisBind.diagnosis_id' => $diagnosisData[0][0]['id']

cakephp belongsToMany with 4 tables

We have 4 tables
Users
-id
Profiles
-id
-user_id
Questions
-id
Options
-id
ProfileQuestions
-id
-profile_id
-question_id
-option_id
Now i require to get all profiles and each profile have multiple questions and each question has many options.
User Model
$this->hasMany('Profiles', [
'foreignKey' => 'user_id'
]);
Profiles Model
$this->belongsToMany('Questions', [
'foreignKey' => 'profile_id',
'targetForeignKey' => 'question_id',
'joinTable' => 'profile_questions',
'through' => 'ProfileQuestions' ,
'joinType' => 'LEFT']);
Questions Model
$this->belongsToMany('Options', [
'foreignKey' => ['question_id'],
'targetForeignKey' => 'option_id',
'joinTable' => 'profile_questions',
'through' => 'ProfileQuestions'
]);
ProfileQuestions Model
$this->belongsTo('Profile', [
'foreignKey' => 'profile_id',
]);
$this->belongsTo('Questions', [
'foreignKey' => 'question_id'
]);
$this->belongsTo('Options', [
'foreignKey' => 'option_id'
]);
Controller code to get the result
$query = $this->Users->find('first')
$query->contain(['Profiles.Questions.Options']);
Error
Fatal error: Out of memory (allocated 408944640) (tried to allocate 665912212 bytes) in vendor\cakephp\cakephp\src\Database\Statement\MysqlStatement.php on line 39
Issue is related to Associations. If we set the profile_id where condition with the options contain then it works for that profile id.

Cakephp 3 : How to fetch joing table associated data?

I have a table name countries , countries has relation with users, users has relation with MoneyTransferTransactions
In MoneyTransferTransactions view I need fetch country name.
I already join Users table in MoneyTransferTransactionsTable by below code
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);
In user table I also used inner join like below code
$this->belongsTo('Countries', [
'foreignKey' => 'country_id',
'joinType' => 'INNER'
]);
In MoneyTransferTransactions controller I have used below code to fetch all data with associated data.
$this->paginate = [
'contain' => ['Users','TransferOptions'],
'conditions'=> ['MoneyTransferTransactions.status'=>1],
'order' =>['MoneyTransferTransactions.id'=>'DESC']
];
I have used var_dump in index.ctp , I gotted country id from users table but not got country name from countries table. How can I get country name from MoneyTransferTransactions>index.ctp ?
Add association between Users and Countries in 'contain'
$this->paginate = [
'contain' => ['TransferOptions', 'Users' => ['Countries']],
'conditions' => ['MoneyTransferTransactions.status' => 1],
'order' => ['MoneyTransferTransactions.id' => 'DESC']
];

Joining 3 tables with a junction table (HABTM)

We have 3 tables - items, locations and taxes. items_locations and locations_taxes are already associated. But, there is a need to connect all of them - items_locations_taxes
Database schema is already in place. When I baked locations model, it did something like this :
$this->belongsToMany('LocationsTaxes', [
'foreignKey' => 'location_id',
'targetForeignKey' => 'locations_tax_id',
'joinTable' => 'items_locations_taxes'
]);
$this->belongsToMany('Items', [
'foreignKey' => 'location_id',
'targetForeignKey' => 'item_id',
'joinTable' => 'items_locations'
]);
$this->belongsToMany('Taxes', [
'foreignKey' => 'location_id',
'targetForeignKey' => 'tax_id',
'joinTable' => 'locations_taxes'
]);
First belongsToMany seems to be wrong. Its auto generated through Bake.
Now, how can these 3 be connected through join?
And, take a note that junction tables are using composite primary keys and do not contain id column.

Resources