I have a table Post and this has a has-many association with a table Stars.
I can get all the associated data using:
$this->Posts->find()->contain(['Stars']);
That works well.
But I want to count the Stars. I have tried this but its not working:
$this->Posts->find->contain([
'Stars' => function($q) {
return $q->select(['total' => $q->func()->count('Stars.post_id')]);
}
]);
//I've also tried this
...
...$q->select(['total' => "COUNT(Stars.post_id)"]);
...
//Also fail
This does not return the number of associated Stars.
Is there something wrong or should do it some other way?
Thanks
you have to select also the foreign key otherwise cake is not able to join the tables. And you have also to group the result
'Stars' => function($q) {
$q->select([
'Stars.post_id',
'total' => $q->func()->count('Stars.post_id')
])
->group(['Stars.post_id']);
return $q;
}
As here we have used total as virtual field, can be create more like this in same model as:
public function index()
{
$checklist = TableRegistry::get('Checklists');
$query = $checklist->find()
->where('Checklists.is_deleted = 0')
->contain([
'ChecklistTitles' => function($q) {
return $q -> select([
'ChecklistTitles.title',
'ChecklistTitles.checklist_id'
]);
},
'ChecklistTypes' => function($w){
return $w->select(['ChecklistTypes.type']);
},
'AssignedChecklists' => function($e){
$e->select([
'AssignedChecklists.checklist_id',
'completed' => $e->func()
->count('AssignedChecklists.checklist_id'),
])
->group(['AssignedChecklists.checklist_id'])
->where(['AssignedChecklists.is_deleted = 0 AND AssignedChecklists.checklist_status = 2']);
return $e;
}
]);
// ->toArray();
// pr($query);die;
$this->paginate = [
'limit' => 20,
'sortWhitelist' => [
'id', 'checklist_title', 'checklist_type'
]
];
$this->set('query', $this->paginate($query));
$this->set(compact('checklists','query'));
$this->set('_serialize', ['checklists','query']);
}
As here I have calculated completed, I want to calculate cancelled with different where condition, what will be the syntax for it in cakephp3?
Try this:
$total = $this->Posts->find()->contain(['Stars'])->count();
As refereed in the cookbook.
Related
I have the following code in a Table definition.
$paginationQuery = $this->find()
->select([
'Members__id','Members__member_type','Members__first_name',
'Members__middle_name','Members__last_name','Members__suffix'
])
->contain([
'SocialMembers' => [
'foreignKey' => false,
'queryBuilder' => function (Query $q) {
return $q->where([
'Members.Members__id' => 'SocialMembers.full_member_id'
]);
}
]
])
->from([
$this->getAlias() => $query
])
->order([
'Members__last_name' => 'ASC',
'Members__first_name' => 'ASC'
]);
return $paginationQuery;
This is to paginate the results of a union of two sets of extracted data.
The problem comes from the queryBuilder function. The left join that is generated looks like this:
LEFT JOIN members SocialMembers ON (
SocialMembers.member_type = 2
AND Members.Members__id = 'SocialMembers.full_member_id'
)
There is an unneeded pair of single quotes around SocialMembers.full_member_id. queryBuilder appears to correctly handle the Members.Members__id, but not the value field of the array. Is there any way to get this to generate correctly?
Was able to resolve this by moving the contains clause to the preceding finder methods.
this function should return the field of the table I want, but this doesn't happen, return all field of the table, with simply sql work fine "SELECT DISTINCT especie FROM packages"
public function listSpicies()
{
$packages = $this->Packages->find('all')
->select('especie')
->distinct('especie');
$this->set([
'success' => true,
'data' => $packages,
'_serialize' => ['success', 'data']
]);
}
I think You can use something like this:
$packages = $this->Packages->find('all' , [
'fields' => [
'anyAlias' => 'DISTINCT(espiece)'
]
])
->toArray();
Notice. If this collection is serialized and outputted as a JSON, check \App\Model\Entity\Package - if espiece is inside $_hidden array - remove this from array
I'm trying to update the status on my tickets table to the value : 2.
Once I can create the comment... (is working.. :) ), I wanted to change the status to 2.
This is my ticket model and the following function:
public function addComment($id,$body,$solved)
{
$this->find($id)->status = 2;
$this->save();
$this->comments()->create([
'ticket_id' => $id,
'body' => $body,
'user_id' => auth()->id()
]);
}
You need to get your object first then you can Update it:
public function addComment($id,$body,$solved)
{
$ticket = $this->find($id);
$ticket->status = 2;
$ticket->save();
$ticket->comments()->create([
'ticket_id' => $id,
'body' => $body,
'user_id' => auth()->id()
]);
}
Try changing your code like this. Maybe this will fix the problem you're having:
public function addComment($id,$body,$solved)
{
$ticket = Ticket::find($id);
$ticket->status = 2;
$ticket->save();
$ticket->comments()->create([
'ticket_id' => $id,
'body' => $body,
'user_id' => auth()->id()
]);
}
I'm trying to perform a search on two joined columns, fname and lname.
This does not appear to be working:
Object of class Cake\Database\Expression\FunctionExpression could not be converted to string
$users = $this->Users->find();
$users->select(['id', 'fname', 'lname'])
->where([$users->func()->concat(['fname', 'lname']).' LIKE' => $terms]);
Any ideas?
Thanks.
If you're concatenating first and last names, they should be concatenated with spaces in between.
$users->select(['id', 'fname', 'lname'])
->where(function ($exp, $query) use ($terms) {
$conc = $query->func()->concat([
'fname' => 'identifier', ' ',
'lname' => 'identifier'
]);
return $exp->like($conc, $terms);
});
Yu have to use query expression but this can't be done in a pagination array.
So Following ndn suggestion here's how I would do
create a custom finder. In your UsersTable file
public function findByKeyword(Query $query, array $options)
{
$keyword = $options['keyword'];
$query->where(
function ($exp, $q) use($keyword){
$conc = $q->func()->concat([
'Users.fname' => 'literal', รน
'Users.lname' => 'literal']);
return $exp
->or_([
'Users.fname LIKE' => "%$keyword%",
'Users.lname LIKE' => "%$keyword%",
])
->like($conc, "%$keyword%");
}
);
return $query;
}
Controller
$this->paginate = [
'finder' => [
'byKeyword' => [
'keyword' => $this->request->data['Users']['keyword']
]],
'conditions' => $limo, // this will merge your $limo conditions
// with the ones you set in the custom finder
'order'= > ['Users.fname desc'],
];
$this->set('userlist', $this->paginate($this->Users));
I think you have to use SQL expressions. Try something like this:
->where(function ($exp, $q) use($terms) {
$concat = $q->func()->concat([
'fname' => 'identifier',
'lname' => 'identifier'
]);
return $exp->like($concat, $terms);
});
i have a little problem with cakephp
i have DB
measurers => id, title, color...
usages => id, measurer_id, value...
and i want to do something like
$this->paginate = [
'contain' => [
'MeasurerTypes',
'Usages' => function($q) {
return $q->find('latest');
}
],
'finder' => ['my' => $this->user['id']]
];
$this->set('title',__('My measurers'));
$this->set('measurers', $this->paginate($this->Measurers));
$this->set('_serialize', ['measurers']);
this is only example code, is there to find only one latest variable and no all list for that?
Check this:
http://book.cakephp.org/2.0/en/models/additional-methods-and-properties.html#model-getinsertid
Example:
$lastItem = $this->YOURMODEL->getInsertID();
Edit:
In CakePHP 3
http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html
$result = $articles->find('all')->all();
// Get the first and/or last result.
$row = $result->first();
$row = $result->last();