cant display rows from belongsToMany - cakephp

I cant display any rows from a belongsToMany relationship (tutors have subjects). I use the exact same code on another table but for some reason this code gives an error which says the colum doesnt exist when it does.
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Subjects.subject_id' in 'on clause'
$tid = 12;
$sub = $this->Subjects->find('list')->hydrate(true);
$sub->matching('Tutors', function ($q) use ($tid) {
return $q->where(['Tutors.id' =>$tid]);
});
Model in tutors
$this->belongsToMany('Subjects', [
'foreignKey' => 'tutor_id',
'targetForeignKey' => 'subject_id',
'joinTable' => 'tutors_subjects'
]);

Try rename your table tutors_subjects as subjects_tutors
Join tables, used in BelongsToMany relationships between models,
should be named after the model tables they will join, arranged in
alphabetical order (articles_tags rather than tags_articles)
More Info Model and Database Conventions

Related

Tables not joining using options to find()

I am trying to join the following two tables in a controller:
artifacts_publications
----------------------
id
artifact_id
publication_id
and
authors_publications
--------------------
id
author_id
publication_id
Other tables which have associations like belongsTo and HasMany set up easily join using contain(). For these tables, suppose no association is already defined. In the end, I want to join another table to the join of these tables but for now I cannot get these two joined.
The Controller uses
namespace App\Controller;
use App\Controller\AppController;
use Cake\ORM\TableRegistry;
use Cake\Datasource\ConnectionManager;
In the index() action of the controller, I have
$options['joins'] = [
[
'table' => 'authors_publications',
'alias' => 'j',
'type' => 'LEFT OUTER',
'conditions' => [
'authors_publications.publication_id = artifacts_publications.publication_id',
],
],
];
$query = TableRegistry::getTableLocator()->get('artifacts_publications')->find('all', $options);
$query->limit(2);
debug($query);
debug($query->toArray());
The resulting SQL query is somewhat like this, but I have shortened long identifiers:
SELECT id, artifact_id, publication_id
FROM artifacts_publications
LIMIT 2;
Executing that query also shows no join. I tried to follow cakePHP table joining two tables issue but I still cannot join. Hand-written SQL worked but it is not elegant. What am I missing here?
#Utsav
Try to use the Containable behaviour of CakePHP by switching the 'join' with 'contain'.
$options = [
'fields' => [
'ArtifactsPublication.fieldsYouWant'
],
'conditions' => [
'ArtifactsPublication.id' => $artifactId
],
'contain' => [
'AuthorsPublication'
]
];
You can also set the recursive to define if you want to get the contained model's linked models. Alternativly you can specify in the fields option what fields you want from the artifacts_publications Model and then just contain the authors_publications Model.
Hope this helps as I have had bad experiences with manual joins in CakePHP, also the CakePHP standard is to use contain. Just note a contain cannot retrieve distant joined data.
Cheers mate :)

CakePHP 2.x fields list shows list of id's instead of values

In my PartsController I have the following code:
$serialNrs = $this->Part->find('list',
array(
'conditions'=>array(
'Part.status_id' => 3
),
'fields'=> array('serial_nr_id' )
//'fields'=> array('serialNr.name')
));
The according select field shows a list of id's instead of values.
When I use 'fields'=> array('serialNr.name') I get an error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'SerialNr.name' in 'field list'
SELECT Part.serial_nr_id, SerialNr.name FROM part145.parts AS Part WHERE Part.status_id = 3
What do I need to do to show a list of values?
You should use the Model name instead of the actual table name in database, thus
$serialNrs = $this->Part->find('list',
array(
'conditions'=>array(
'Part.status_id' => 3
),
'fields'=> array('Part.name' )
));
According to the above code, you have a model named "Part" where it points to a database table where there are at least a "status_id" column and a "name" column.

cakephp - issue for joining multiple tables

I am joining multiple tables like the following.
$recommend_logs = $this->RecommendingProductLog->find('all', array(
'recursive' => 2,
'fields' => array('Product.ProductName', 'Product.Gender', 'Product.Price', 'RecommendingProductLog.preference', 'Brand.BrandName'),
'conditions' => array('RecommendingProductLog.user_id' => $user_id),
'contain' => array('Product', 'Product.Brand')
));
I am getting this query from log.
SQL Query: SELECT `Product`.`ProductName`, `Product`.`Gender`, `Product`.`Price`, `RecommendingProductLog`.`preference`, `Brand`.`BrandName`, `Product`.`id` FROM `database`.`recommending_Product_log` AS `RecommendingProductLog` LEFT JOIN `database`.`Products` AS `Product` ON (`RecommendingProductLog`.`Product_id` = `Product`.`id`) WHERE `RecommendingProductLog`.`user_id` = 32
Even though 'Product' table is a child table of 'Brand' table, somehow I don't see 'Brand' table in the query. That's why I am getting an error 'Unknown column 'Brand.BrandName' in 'field list'.
I specified 'Brand' in the Perfume model as 'belongsTo' and 'Perfume' in RecommendingPerfumeLog model and 'Perfume' as hasMany in Brand model.
can somebody point where the problem is?
thanks.
Have you correctly put the foreign keys on the respective tables of the relation? In this case Product have to have a a key with the name brand_id and it must be a foreign key to the brand id field.
Also check this and try to put your joins.
I don't remenber this 'contain' field from the docs. Are you using the latest version?

SUM field from contained records

On cake 2.1, I need to SUM a field from the contained records.
Currently I get the sum of All records on the child table, but need to group by the id of my main table (employee).
Attend belongs to Employee
$agents = $this->Employee->find('all', array(
'fields' => array('Employee.FullNameNoId'),
'conditions' => $conditions,
'contain' => array(
'Attend' => array(
'conditions' => array(
'Attend.as_date BETWEEN ? AND ?' => array(
date('Y-m-d', strtotime($this->passedArgs['date1'])),
date('Y-m-d', strtotime($this->passedArgs['date2']))
)
),
'fields' => array('sum(Attend.as_labormin) AS total'),
//'group' => array('Attend.employee_id') // This gets sql errors below
)
)
));
Tried several combinations with SQL errors:
'group' => array('Attend.employee.id') // Model "Attend" is not associated with model "Attend"
//Column not found: 1054 Unknown column
'group' => array('employee_id') // Model "Attend" is not associated with model "employee_id"
// Column not found: 1054 Unknown column 'Attend.group' in 'field list'
'group' => array('Employee.id') //Column not found: 1054 Unknown column Attend.group' in 'field list'
Relation betweent tables is fine, I can get related records, problem is to get a sum by employee id.
Checked Cakephp SUM of related field, but it seems cumbersome to use SELECT SUM, and they left out the grouping needed.
Can you help?
Try disabling 'autoFields'. It is known to cause SQL errors with aggregate functions and 'group by' statements. Find out more here

CakePHP find on a join table

Sorry if this is obvious - I'm trying to do a find() on a join table and failing, whats the correct syntax to do this?
Basically I have expenseCode table with a HABTM releationship with the expense table.
In my expenseCode model I have:
public function beforeDelete($cascade = false) {
$count = $this->Expense->find("count", array(
'conditions' => array('expense_code_id' => $this->id)
));
if ($count == 0) {
return true;
} else {
//$this->Session->setFlash('Record cannot be deleted as it has ' . $count . 'number of expenses attached to it');
return false;
}
}
If I uncomment the setFlash() I get the error.
Where am I going wrong? Thanks in advance.
Unfortunately it's not possible to perform such a query on the HABTM join table from one of the parent models without some extra work. I'm assuming that Expense is the parent model and ExpensesCode the join model?
A common way is to modelise the HABTM join table. Say you have an expenses and codes table which are joined by expenses_codes:
$this->Expense->bindModel(array('hasOne' => array('ExpensesCode')));
$this->Expense->find('all', array(
'fields' => array('Expense.*'),
'conditions' => array('ExpensesCode.expense_code_id' => $this->id)
));
However, Cake also auto-iniatlises a model for the join table when a HABTM association is defined (see the manual, and the "with" key in the list of possible keys).
So this syntax would let you directly query the join table:
$this->Expense->ExpensesCode->find('all', array(
'conditions' => array('ExpensesCode.expense_code_id' => $this->id)
));
The query above will net you with an array containing only the results from the join table, as it doesn't perform a join like the first procedure. So you would have to perform a second find() on the Expense model to find the expenses related to the expense_code_id from ExpensesCode.
EDIT:
It's a framework convention that HABTM join tables should be underscored and alphabetically ordered. So if the HABTM join table is called codes_expenses, it's auto-modelised as CodesExpense.
You can also work in a simpler way if you create another model with two hasMany relations instead of one with HABTM.
HasAndBelongsToMany between two models is in reality shorthand for three models associated through both a hasMany and a belongsTo association.
I found it is one of the simplest ways to save and retrieve data.
For more information:
http://book.cakephp.org/2.0/en/models/saving-your-data.html#what-to-do-when-habtm-becomes-complicated

Resources