cakephp 3 show latest value with contain - cakephp

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();

Related

register_graphql_field returning null values

I am trying to return values from a query that is only returning null values or is giving me errors based upon everything that I have tried. I have created a WP Plugin to put this code. I have pasted my code below
I have edited this code to what is currently working, but it is only giving me that last entry in the DB table. How would I get them all to display
function register_contact_form_fields() {
register_graphql_field( 'RootQuery', 'contactForm', [
'description' => __( 'Get a user submission', 'codmoncai-contact' ),
'type' => 'ContactForm',
'resolve' => function( $root, $args, $context, $info ) {
global $wpdb;
$combined_data = [];
$results = $wpdb->get_results("SELECT * FROM wpxd_contact_us");
}
return $data;
] );
}
By changing the 'type' in the register_graphql_field function to
'type' => [ 'list_of' => 'ContactForm' ],
Fixed my issue and allowed me to get all rows in the query

Select Distinc on cakephp 3 return wrong fields

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

CakePHP 3.4 group by foreach loop the result

I am struggling with foreaching grouped records.
It is a collection of hours saved with the same date, and I want to group them in my view/output.
Any suggestions? I have tried a ton of different approaches. Here is how I get them from DB. (date = type date in mysql "Y-m-d"). And outputting them normal. All my trials and errors.. I could write all day, and I am sure it is a simple solution for someone that know how cake libs work.
$hours = $this->UserHours->find('all', [
'conditions' => [
'UserHours.user_id' => $this->Auth->user('id'),
'month(UserHours.date)' => $this->request->data('date.month')
],
'order' => ['UserHours.date ASC'],
'group' => ['UserHours.date']
]);
And the foreach loop:
foreach ($projecthours as $hour):
debug($hour);
?>
<tr>
<td> <?php echo $hour->date;?> </td>
<td> <?php echo $hour->start; ?> </td>
<td> <?php echo $hour->end; ?> </td>
</tr>
My problem is that I have no idea how to loop trough the records correctly when grouped from controller. I cant find them when using the "group" condition in controller. I only get the first record of each date when using "group".
:) I guess they are somewhere inside there, but I cant figure this one out. I am quite new to cake 3.4..
After you get the grouped dates, you get all dates matching each grouped date.
// get grouped dates
$dates = $this->UserHours->find('all', [
'conditions' => [
'UserHours.user_id' => $this->Auth->user('id'),
'month(UserHours.date)' => $this->request->data('date.month')
],
'order' => ['UserHours.date ASC'],
'group' => ['UserHours.date']
]);
$hours = [];
// find all dates for each grouped date
foreach ($dates as $date) {
$hours[] = $this->UserHours->find('all', [
'conditions' => [
'UserHours.user_id' => $this->Auth->user('id'),
'month(UserHours.date)' => $this->request->data('date.month')
],
'order' => ['UserHours.date ASC']
])
->where(['UserHours.date' => $date->date]);
}
foreach ($hours as $values) {
foreach ($values as $hour) {
dd($hour->date);
}
}
That's the expected result, as that is how SQL grouping works, you get one value per group, there simply will be no further values in the results.
If you just want to output things in a grouped manner, then that's something different, for that you have to select all data, and then you could simply group the results on PHP level, for example using the collection/resultset method groupBy():
$query = $this->UserHours->find('all', [
'conditions' => [
'UserHours.user_id' => $this->Auth->user('id'),
'month(UserHours.date)' => $this->request->data('date.month')
],
'order' => ['UserHours.date ASC']
]);
// callback usage required as `date` is most likely an object
$groupedByDate = $query->all()->groupBy(function ($row) {
return $row['date']->format('Y-m-d');
});
// if it weren't an object, then passing the fields name would already do it
// $groupedByDate = $query->all()->groupBy('date');
foreach ($groupedByDate as $date => $group)
{
// $date = the value of UserHours.date shared by all entities in the group
// $group = an array of UserHour entities that share the same UserHours.date value
foreach ($group as $hour)
{
// ...
}
}
See also
Cookbook > Database Access & ORM > Query Builder > Queries Are Collection Objects
Cookbook > Collections > Collection::groupBy()

Count in contain Cakephp 3

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.

Is there an alternative to neighbors in Cakephp

I am coverting my app over to cakephp 3.0 and I am having trouble finding an alternative to using neighbors in the find method.
I need to find the next record in the associated table and neighbors was a great way to do it.
//Open courses
$options = [
'conditions' => ['Employees.user_id' => 1, 'CoursesEmployees.completed' => false],
'limit' => 3,
'contain' => 'Employees'
];
$recentOpen = $this->CoursesEmployees->find('all', $options)->toArray();
// get next module for each open course
foreach ($recentOpen as $key => &$value) {
$currentModule = $value['CourseModule']['id'];
$neighbors = $this->CoursesEmployees->CourseModules->find(
'neighbors',
['field' => 'id', 'value' => $currentModule]
);
$value['CourseModule']['next_module'] = $neighbors['next']['CourseModule']['name'];
};
Another issue with the code I discovered is that $this->CoursesEmployees->find('all', $options)->toArray(); seems to return a complex array with everything cakephp uses to query the table and not the actual results like I got with cakephp 2. I added the ->toArray() as recommended with 3.0
Because I loathe "Answers" that simply point to a URL where you may or may not be able to decipher a half answer today, but could be gone tomorrow, here is my replacement custom finder:
// In src/Models/Table/ExampleTable.php
/**
* Find neighbors method
*/
public function findNeighbors(Query $query, array $options) {
$id = $options['id'];
$previous = $this->find()
->select('id')
->order(['id' => 'DESC'])
->where(['id <' => $id])
->first();
$next = $this->find()
->select('id')
->order(['id' => 'ASC'])
->where(['id >' => $id])
->first();
return ['prev' => $previous['id'], 'next' => $next['id']];
}
Called simply in the Controller:
// In src/Controller/ExamplesController.php
public function view($id = null) {
...
$neighbors = $this->Examples->find('neighbors', ['id' => $id]);
....
}
As explained here
there is no neighbors find method in cakephp 3.
But if you follow the flow of the issue you will find a custom finder to accomplish it, maybe it will work for you.

Resources