Cakephp Select foreign key and order by name! - cakephp

I can get drop downs from foreign keys but how to sort them by name instead of id.
Adding 'order' => 'Country.name asc' in belongsTo model doesn't work, or I'm missing something!!!
e.g. Choose country, state, city, and those to be sorted by name, instead of id.

Are you scaffolding? If not should have a call similar to
$this->set('groups', $this->User->Group->find('list'));
in your controller simply add the sort condition to the find call e.g.
$this->set('groups', $this->User->Group->find('list',array('order'=>'Group.name desc')));

Related

Soql object has multiple lookups to user

Afternoon,
I am gathering data from the LiveChatTranscript and there are multiple references to user as lookup fields. How do I pick which property I want to use as my reference to user?
LiveChatTranscript properties
LastModifiedById Lookup(User)
CreatedById Lookup(User)
OwnerId Lookup(User,Group)
query
-webroot-/query/?q=select chatkey, caseid, status,requesttime, starttime, endtime,endedby,name,ReferrerUri,platform,location, waittime,body,supervisortranscriptbody, case.description, ownerid,ownerid.user.alias?? from livechattranscript where chatkey = '12345'
In this case, owner is the field name. It looks up to the user object. No need to include the object name there. Just drop the id potion for ownerid.
Use owner.alias.

Best rules to get data with Contain

In CakePHP 3 ORM has changed and I can't find the proper way to select needed data from the database.
In CakePHP 2, I use contain('User.name','User.id'), but In CakePHP 3 this code doesn't work.
So how can I select only id and name from User?
The code:
$query = $data->find()->contain(['Users'])->execute()->fetchAll('assoc');
// I want only user.id and user.name.
$articles = $this->Model->find()
->select(['fields_you_want_from_this_Model'])
->contain(['Assoc_Model' => function($q) {
return $q
->select(['fields_you_want_from_the_associated_model']);
}]);
U must take a look about this page: http://book.cakephp.org/3.0/en/orm/query-builder.html#passing-conditions-to-contain
In certain case you must use autoFields method.
Be carefull with contain when u select few fields in the callable, u always have to select the foreign key also:
When you limit the fields that are fetched from an association, you must ensure that the foreign key columns are selected. Failing to select foreign key fields will cause associated data to not be present in the final result.

Fetching category name with a INNER JOIN

I have a query that returns details of an item. It item belongs to a certain category; hence I have linked the ITEMS table to CATEGORIES table with a foreign key being saved to the ITEMS table.
Now, I want the details of any selected item to also display the category name instead of the foreign key. I have tried the INNER JOIN as follows, but surprisingly still the query displays a foreign key.
Here is my query:
/* Create the prepared statement */
if ($stmt = $mysqli->prepare("SELECT categories.category AS category,
items.id,
items.name,
items.description
FROM items
INNER JOIN categories
ON categories.cat_id = items.cat_id
WHERE items.id='$id'")) {
/* Execute the prepared Statement */
$stmt->execute();
/* Bind results to variables */
$stmt->bind_result($id,$category,$name,$description);
/* fetch values */
while ($rows = $stmt->fetch()) {
...
}
...
}
Out put for category name:
<?php
echo $category;
?>
What could be missing here?
Your binding order is wrong, it should be:
$stmt->bind_result($category, $id, $name, $description);
Your order in the SELECT clause matters, so bind_result can figure out wich column binds to wich variable.
This is way out of my element, but nobody answered it yet so I figured I'd take a shot.
Is it because you are selecting 3 items in your query... category, id, description
Then when you are binding variables you're binding 4... $id, $category, $name, $description
So perhaps what is happening is variable $id is actually the category, and $category is actually the id (which is what you're seeing)
You seem to be fetching 3 items (from your select) to 4 variables, I don't think this is good.

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

CakePHP save two models, second based on first

I have the following association:
Group hasAndBelongsToMany User, with the groups_users join table.
When I create a new group, I want to add to the join table the founder of the group.
My $this->data array looks like:
Array
(
[Group] => Array
(
[name] => seyufgsduifsj
[access] => 2
[founder_id] => 3
[random_key] => I6XC7uMTelpTSdq8DbtLPjqubiF7s6Pn
)
[GroupsUser] => Array
(
[user_id] => 3
[group_role_id] => 1
[random_key] => PZsDZXcoCTHw1IuvqsfURVpPX6AcZ3r2
)
)
I tried with save() and saveAll(), but it would add only the group in the groups table and not the user-group association.
So, basically, I have an add form where the user fills in the group name and access. Then, if the data validates, I add a couple of more field values to the group array (like random_key) and to the join table array (like user_id and group_role_id). I want Cake to save the group first, take its id, update the join table array with the proper group_id, and then save this second array too.
Is this possible in a straight-forward way, or do I have to write two consequent save() methods, for the second one providing the last inserted id in the first one?
Thanks!
You can use saveAll() function, but you need to change the format of the GroupsUser array. According to documentation of saveAll() your data should look like this:
Array
(
[Group] => Array
(
[name] => seyufgsduifsj
[access] => 2
[founder_id] => 3
[random_key] => I6XC7uMTelpTSdq8DbtLPjqubiF7s6Pn
)
[GroupsUser] => Array
(
[0] => Array
(
[user_id] => 3
[group_role_id] => 1
[random_key] => PZsDZXcoCTHw1IuvqsfURVpPX6AcZ3r2
)
)
)
Your example would work if the relation is Group belongsTo GroupsUser, but I believe this is not your case
Perhaps the related models are not passing validation. Use the following piece of code to save only if all models validate:
$this->Group->saveAll($this->data, array('validate' => 'only'));
If you don't find your Group being saved this time around, then it's most probably validation rules in your Join Model that are failing. My guess is that you have a notEmpty validation for the group_id, which you would have to remove in order for saveAll() to work.
Hope this points you in the direction of solving your problem.
EDIT: Your associations are a little off. Here's what it should be:
Group hasMany GroupsUser
User hasMany GroupsUser
GroupRole hasMany GroupsUser
GroupsUser belongsTo Group
GroupsUser belongsTo User
GroupsUser belongsTo GroupRole
Remove the hasAndBelongsToMany association between Groups and User. It doesn't exist any more.

Resources