Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set Date as keyField in list Cakephp 3

I have used list to get data from the model and it works well

This example is from Cakephp docs

$query = $articles->find('list', [
    'keyField' => 'slug',
    'valueField' => 'title'
]);
$data = $query->toArray();

I have a table name holidays

id[int] | date[date] | name[varchar(200)] | created[datetime]

So want a list which has date as the key and holiday as value Somthing like this

[
    '2016-01-01'=>'New Year',
    '2016-01-26'=>'Republic Day',
]

So i created model by cake bake and used this code to achive it

$holidays = TableRegistry::get('Holidays');
$holidays = $holidays->find('list',[
    'keyField' => 'date',
    'valueField'=>'name',
])->toArray();

But its giving me error

Illegal offset type InvalidArgumentException

When i change the keyField from date with name it works great.

Here is the logs

2016-04-29 04:26:41 Error: [InvalidArgumentException] Illegal offset type Request URL: /sfworxerp/api/attendances/getMonthAttendanceData Stack Trace: F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\Collection\Iterator\MapReduce.php(160): Cake\Collection\Iterator\MapReduce::emit() F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\Collection\CollectionTrait.php(386): Cake\Collection\Iterator\MapReduce->emit('New Year', Object(Cake\I18n\FrozenDate)) F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\Collection\Iterator\MapReduce.php(177): Cake\ORM\ResultSet->Cake\Collection{closure}(Object(App\Model\Entity\Holiday), 0, Object(Cake\Collection\Iterator\MapReduce)) F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\Collection\Iterator\MapReduce.php(132): Cake\Collection\Iterator\MapReduce->_execute() [internal function]: Cake\Collection\Iterator\MapReduce->getIterator() F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\Collection\Collection.php(50): IteratorIterator->__construct(Object(Cake\Collection\Iterator\MapReduce)) F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\Collection\CollectionTrait.php(405): Cake\Collection\Collection->__construct(Object(Cake\Collection\Iterator\MapReduce)) F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\ORM\Table.php(1062): Cake\ORM\ResultSet->combine('date', 'name', NULL) F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\Datasource\QueryTrait.php(490): Cake\ORM\Table->Cake\ORM{closure}(Object(Cake\ORM\ResultSet)) F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\ORM\Query.php(1141): Cake\ORM\Query->_applyDecorators(Object(Cake\ORM\ResultSet)) F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\Datasource\QueryTrait.php(272): Cake\ORM\Query->_decorateResults(Object(Cake\ORM\ResultSet)) F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\ORM\Query.php(871): Cake\ORM\Query->_all() F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\Datasource\QueryTrait.php(288): Cake\ORM\Query->all() F:\public_html\sfworxerp\src\Controller\Api\AttendancesController.php(133): Cake\ORM\Query->toArray() [internal function]: App\Controller\Api\AttendancesController->getMonthAttendanceData() F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\Controller\Controller.php(429): call_user_func_array(Array, Array) F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\Routing\Dispatcher.php(114): Cake\Controller\Controller->invokeAction() F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\Routing\Dispatcher.php(87): Cake\Routing\Dispatcher->_invoke(Object(App\Controller\Api\AttendancesController)) F:\public_html\sfworxerp\webroot\index.php(37): Cake\Routing\Dispatcher->dispatch(Object(Cake\Network\Request), Object(Cake\Network\Response)) {main}

Any help is highly appreciated

like image 242
Aman Rawat Avatar asked Sep 08 '25 10:09

Aman Rawat


1 Answers

The Problem:

The problem is, for 'date' fields, CakePHP 3 returns an object, not a string:

'date' => object(Cake\I18n\FrozenDate) {
    'time' => '1997-01-03T00:00:00+00:00',
    'timezone' => 'UTC',
    'fixedNowTime' => false
},

Trying to use that as the key doesn't work, and throws the error you're seeing.

How to handle:

Per this area in the CakePHP book, to accommodate this, you can:

use closures to access entity mutator methods in your list finds.

TLDR Do this:

$query = $articles->find('list', [
    'keyField' => function ($e) {
         return $e->date->format('Y-m-d');
     },
    'valueField' => 'title'
]);

Explanation for how it works:

Basically, it puts the value of each entity (in your case each article) into the variable $e, and allows you to use/modify it's data, and return the string you want to use as the key (or value) field. In the case above, it's getting the date object, and formatting it into a string before returning it to be used as the key.

like image 200
Dave Avatar answered Sep 10 '25 00:09

Dave