Cakephp - HABTM relationship lost after calling method - cakephp

The Issue
I have two methods I need to call in my getContacts function. These methods are as follows:
Method 1:
$authenticated = $this->authenticateUserInternal($inputData['auth']);
Method 2:
$result = $this->Consumer->find('first', array( 'conditions' => array('Consumer.id' => 81)));
When I invoke these methods one after the other my resultset in $result does not have data from related tables. It seems like Method 1 is killing the relationship or affecting my results somehow, but it's a completely un-related function in the AppController.
The Code
The the Consumer model has a HABTM relationship to my Users model through a join table consumers_users.
Consumer Model
public $hasAndBelongsToMany = array(
'User' => array( 'className' => 'User', 'joinTable' => 'consumers_users', 'foreignKey' => 'consumer_id', 'associationForeignKey' => 'user_id', ));
User Model
public $hasAndBelongsToMany = array(
'Consumer' => array(
'className' => 'Consumer',
'joinTable' => 'consumers_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'consumer_id',
));
ConsumersUsers Model
public $belongsTo = array(
'User' => array( 'className' => 'User', 'foreignKey' => 'user_id', ), 'Consumer' => array( 'className' => 'Consumer', 'foreignKey' => 'consumer_id', ), );
My normal result
"Consumer": {
"id": "81",
"fullname": "consumer2",
"email": "consumer2#cici.mailgun.org",
"password": "111111",
"dateregistered": "2013-08-18",
"audio": "0"
}, "User": [
{
"id": "179",
"fullname": "leesa",
"email": "lda#hotmail.com",
"password": "111111",
"imageurl": "http://bridgefiles.s3.amazonaws.com/2013-07-18-144613_IMG_0773.jpeg",
"thumb_url": "http://bridgefiles.s3.amazonaws.com/2013-07-18-144613_IMG_0773.jpeg",
"messagecount": "2",
"dateregistered": "2013-07-29",
"phone1": null,
"phone2": null,
"videoaddress": null,
"ConsumersUser": {
"id": "17",
"consumer_id": "81",
"status": "accepted",
"user_id": "179"
}
},
The Actual Result
"Consumer": {
"id": "81",
"fullname": "consumer2",
"email": "consumer2#cici.mailgun.org",
"password": "111111",
"dateregistered": "2013-08-18",
"audio": "0"
}

You are selecting only the table consumer, I think that the right way is to load the join table and insert recursive 1 to retrieve both table Consumer and User
try this:
$this->loadModel('ConsumersUsers');
$result = $this->ConsumersUsers->find('first', array( 'conditions' => array('Consumer.id' => 81), 'recursive' => 1));

Related

Belongs to Many: save custom field

I need help with saving/updating belongsToMany data with custom field.
I have a tables acl, managers, groups, sections.
I need to save/update data in acl table from sections/edit or sections/add
acl table
id|target_id|target_type|section_id
I need set target_id data 'user' or 'group' depending entities.
edit.ctp
echo $this->Form->control('managers._ids', ['class' => 'multiple', 'multiple' => true]);
echo $this->Form->control('groups._ids', ['class' => 'multiple', 'multiple' => true]);
SectionsTable.php
$this->belongsToMany('Managers', [
'joinTable' => 'acl',
'through' => 'Acl',
'foreignKey' => 'section_id',
'targetForeignKey' => 'target_id',
'conditions' => [
'target_type' => 'user'
]
]);
$this->belongsToMany('Groups', [
'joinTable' => 'acl',
'through' => 'Acl',
'foreignKey' => 'section_id',
'targetForeignKey' => 'target_id',
'conditions' => [
'target_type' => 'group'
]
]);
AclTable.php
$this->belongsTo('Managers', [
'foreignKey' => 'target_id',
'conditions' => [
'target_type' => 'user'
]
]);
$this->belongsTo('Groups', [
'foreignKey' => 'target_id',
'conditions' => [
'target_type' => 'group'
]
]);
I tried to use _joinData, but nothing work
before and after patchEntity()
foreach ($section->groups as &$group) {
$group->_joinData = ['target_type' => 'group'];
}
whithout save()
foreach ($this->request->data['managers']['_ids'] as $id) {
$manager = $this->Sections->Managers->get($id);
$manager->_joinData = new Entity(['target_type' => 'user'], ['markNew' => true]);
$this->Sections->Managers->link($section, [$manager]);
}
$this->request->data has a follow structure:
[
'controller' => '*',
'action' => '*',
'title' => '*',
'managers' => [
'_ids' => [
'0' => '*',
'1' => '*',
'2' => '*',
]
],
'groups' => [
'_ids' => [
'0' => '*',
'1' => '*',
'2' => '*',
]
]
]
Alltimes error: Cannot insert row, some of the primary key values are missing. Got (3, 114, ), expecting (target_id, section_id, target_type)
Now working with following code
$section = $this->Sections->patchEntity($section, $this->request->data, ['associated' => ['Managers', 'Groups']]);
foreach ($section->managers as &$manager) {
$manager->_joinData = new Entity([
'target_id' => $manager->id,
'target_type' => 'user',
'section_id' => $section->id
], ['markNew' => true]);
}
foreach ($section->groups as &$group) {
$group->_joinData = new Entity([
'target_id' => $group->id,
'target_type' => 'group',
'section_id' => $section->id
], ['markNew' => true]);
}
if ($this->Sections->save($section, ['associated' => ['Managers', 'Groups']])) {
$this->Flash->success(__('The section has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The section could not be saved. Please, try again.'));
But, maybe can do it don't listing all fields?
Also I need to create/add new records to acl table when adding new section
But section_id unavailable until save(). Can I save/add acl records by associations
Updated
AclTAble.php
$this->setPrimaryKey(['target_type', 'target_id', 'section_id']);
.
.
.
$this->belongsTo('Managers', [
'foreignKey' => 'target_id',
'conditions' => [
'target_type' => 'user'
]
]);
$this->belongsTo('Groups', [
'foreignKey' => 'target_id',
'conditions' => [
'target_type' => 'group'
]
]);
With primaryKey id, adding and editing entities working, but editing makes dublicates, it's are not perfect for me. And in documentations use composite primaryKey, so i use ['target_id', 'target_type', 'section_id'], with it cake don't make dublicated, but aggain show me error: Cannot insert row, some of the primary key values are missing. Got (8, 197, ), expecting (target_id, section_id, target_type)

HasOne associations table is not saving

Hi I'm trying to save data across 2 tables (Entries and Conditions) at the same time. Entries has a column called foreign_key which is a relation to the Conditions primary id.
I was testing the saving portion and one of my tables (Conditions) saved but my other table (Entries) did not.
Entry.php
protected $_accessible = [
'metadata' => true,
'type' => true,
'foreign_key' => true,
'created' => true,
'modified' => true,
'condition' => true
];
Condition.php
protected $_accessible = [
'user_id' => true,
'data' => true,
'created' => true,
'modified' => true,
'user' => true,
'entry' => true
];
ConditionsTable.php (where I declared the association)
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('conditions');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);
$this->hasOne('Entries', [
'foreignKey' => 'foreign_key',
'bindingKey' => 'id',
'propertyName' => 'entries',
'joinType' => 'INNER'
]);
}
DataControlellr.php (where I'm testing the saving)
$this->loadModel('Conditions');
$data = [
'user_id' => 'b26ee991-a27c-441b-a78b-dd2a1dbf5164',
'data' => json_encode(['test'=>1,'test2' => 2]),
'entry' =>[
'meta' => json_encode(['test'=>1,'test2' => 2]),
'type' => 'conditions'
]
];
$entity = $this->Conditions->newEntity($data,['associated' => 'Entries']);
//dd($entity);
dd($this->Conditions->save($entity));
exit;
}
So again entries table is not saving a row and conditions is, I believe I'm using the right association (has one) but maybe that not the right logic? Much help is appreciated.
The key in your data and your association name need to match. You probably want to change your association to this:
$this->hasOne('Entries', [
'foreignKey' => 'foreign_key',
'bindingKey' => 'id',
'joinType' => 'INNER'
]);
assuming that the class for the fhir_entries table is called EntriesTable, not FhirEntriesTable.
Alternately, leave the association named as it is but change the propertyName to entry (hasOne properties should be singular). Or, change it to fhir_entry and the key in the data array from entry to fhir_entry to match.

Deep associations in select query in cakephp3.7

I'm new to cakephp3. I'm unable to join associated tables data. I have
Employees Table.
EmployeeLogins Table
EmployeeCategories Table
Relation:
Employees table hasMany EmployeeLogins
And EmployeeLogins belognsTo EmployeeCategories
I'm using contain but not getting EmployeeCategories data.
The result i want is like
In single result set
Output :
array(
'Employees' => array(
'id' => 123,
),
'EmployeeLogin' => array(
[0] => array(
'employee_id' => 123,
'last_login' => '2019-01-01',
'category_id' => 3,
'EmployeeCategory' => array(
'id' => 3,
'category_name' => 'contract'
)
)
)
)
EmployeesTable.php
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('employees');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->hasMany('EmployeeLogins', [
'foreignKey' => 'user_id',
'dependent' => true
]);
}
EmployeeLoginsTable.php
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('employee_logins');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->belongsTo('Categories', [
'foreignKey' => 'category_id',
]);
}
EmployeeCategoriesTable.php
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('employee_catgories');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
}
Code in Controller
$Employees = TableRegistry::get('Employees');
$EmployeeLogins = TableRegistry::get('EmployeeLogins');
$EmployeeCategories = TableRegistry::get('EmployeeCategories');
$Employees->hasMany('EmployeeLogins', [
'className' => 'EmployeeLogins',
'foreignKey' => 'employee_id',
'propertyName' => 'employee_logins'
]);
$Employees->EmployeeLogins->belongsTo('EmployeeCategories', [
'className' => 'EmployeeCategories',
'conditions' => [
'EmployeeLogins.category_id' => 'EmployeeCategories.id'
],
'propertyName' => 'employee_categores',
]);
$result = $Employees
->find()
->where([
'Employees.user_id)' => $user_id,
])
->contain([
'EmployeeLogins' => [
'EmployeeCategories'
]
])
->all();
You need to change your contain section like below
$result = $Employees
->find()
->where([
'Employees.user_id)' => $user_id,
])
->contain([
'EmployeeLogins', 'EmployeeLogins.EmployeeCategories'
])
->all();

record not found on contain model in CakePHP 3

I am using CakePHP 3.4
I am retrieving information of user like
$user = $this->Users->get($id, [
'contain' => [
'UserAddresses.States.Countries' => ['conditions' => [
'UserAddresses.deleted' => false]],
],
]);
Here, UserAddresses have user_id column and state_id column and States table have country_id column.
If there is no associated user_address in table, then I gives
record not found error
while removing States.Countries from contain works fine even when record does not exists in UserAddresses
Edit 2 : Relationships
UsersTable.php
$this->hasOne('UserAddresses', [
'foreignKey' => 'user_id'
]);
UserAddressesTable.php
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);
$this->belongsTo('States', [
'foreignKey' => 'state_id',
'joinType' => 'INNER'
]);
StatesTable.php
$this->belongsTo('Countries', [
'foreignKey' => 'country_id',
'joinType' => 'INNER'
]);
$this->hasMany('UserAddresses', [
'foreignKey' => 'state_id'
]);
CountriesTable.php
$this->hasMany('States', [
'foreignKey' => 'country_id'
]);
As Kilian Schuster said, your condition is being applied to Countries. I changed it, try the code bellow:
$user = $this->Users->get($id, [
'contain' => [
'UserAddresses' => [
'conditions' => [
'UserAddresses.deleted' => false
]
],
'UserAddresses.States.Countries'
]
]);
Edit: The record not found error could be caused by the Inner join type for Countries in States model if there is no address related to the got user. Change the join type to Left if the relationship is optional.
With this syntax, you are actually trying to apply the conditions to the "Countries" model, and not to the "UserAddresses" model.

Dealing with Categories in documents for elasticsearch

Been wrestling with this a while and need some help.
I have a document array in PHP that looks something like this
array("title"=>"some title",
"description" => "Short description",
"categories" => array ( array("id" => "1", "name" => "category 1"),
array("id" => "5", "name" => "category 5"),
array("id" => "55", "name" => "category 55"),
)
);
So basically I have a document that has many categories assigned. My ultimate aim with this is to return all documents that contain a specific category by ID.
I have setup mappings, and the documents are being index OK. I have tried both "nested" type of mapping for category, no mapping at all, and "lists" type but that did not work at all with the error on creation of the mappings.
sample of how I set up "lists"
array(
'_source' => array(
'enabled' => true
),
'properties' => array(
'title' => array(
'type' => 'string',
'analyzer' => 'standard'
),
'description' => array(
'type' => 'string',
'analyzer' => 'standard'
),
'categories' => array(
"type" => "lists",
"properties"=> array(
"id" => array("type"=> "integer" ),
"name" => array( "type"=> "string" ),
),
),
)
);
And for completeness, how I set it up as "nested"
array(
'_source' => array(
'enabled' => true
),
'properties' => array(
'title' => array(
'type' => 'string',
'analyzer' => 'standard'
),
'description' => array(
'type' => 'string',
'analyzer' => 'standard'
),
'categories' => array(
"type" => "nested",
"properties"=> array(
"id" => array("type"=> "integer" ),
"name" => array( "type"=> "string" ),
),
),
)
);
When trying to make a search against nested mappings, it tells me
QueryParsingException: [nested] nested object under path [categories] is not of nested type
When trying to make a nested search against an un mapped set of categories (defaulting to what the system finds) it also returns the same error as above.
My questions are:
what mapping should I setup for these array of categories ?
Given a "match_all" query, what filter (and how) should I use to get a single category?
so much thanks in advance for anyone who even takes the time to read this, let alone answer. I'm really hopeful that you can help.
The answer was pretty simple. I had misread the documentation and has added an extra object type into my mapping requests that did not need to be there.
'categories' => array(
"type" => "lists",
"properties"=> array(
"id" => array("type"=> "integer" ),
"name" => array( "type"=> "string" ),
),
),
should have been
'categories' => array(
"properties"=> array(
"id" => array("type"=> "integer" ),
"name" => array( "type"=> "string" ),
),
),
The array type does not need to be defined as a type, it is assumed to be an array. Once removed, it loads the mapping properly.
Now on to searching....

Resources