将Date设置为列表Cakephp 3中的keyField

时间:2016-04-28 23:04:01

标签: php cakephp cakephp-3.0

我使用list从模型中获取数据并且效果很好

此示例来自Cakephp docs

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

我有一个表名假期

  

id [int] |日期[日期] | name [varchar(200)] |创建了[日期时间]

所以想要一个以日期为关键字,假日为价值的清单 这样的事情

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

所以我通过蛋糕烘焙创建模型并使用此代码来实现它

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

但是它给了我错误

  

非法偏移类型   InvalidArgumentException

当我使用名称从日期更改keyField时效果很好。

这是日志

  

2016-04-29 04:26:41错误:[InvalidArgumentException]非法偏移   请求URL:/ sfworxerp / api / attendances / getMonthAttendanceData   堆栈跟踪:   F:\的public_html \ sfworxerp \厂商\ cakephp的\ cakephp的\ SRC \收集\迭代\ MapReduce.php(160):   蛋糕\收藏\迭代器\的MapReduce ::发射()   F:\的public_html \ sfworxerp \供应商\ CakePHP的\ CakePHP中的\ src \收藏\ CollectionTrait.php(386):   Cake \ Collection \ Iterator \ MapReduce-> emit('New Year',   对象(蛋糕\的I18n \ FrozenDate))   F:\的public_html \ sfworxerp \供应商\ CakePHP的\ CakePHP中的\ src \收藏\迭代器\ MapReduce.php(177):   蛋糕\ ORM \ ResultSet->蛋糕\收集{闭合}(对象(应用\模型\实体\假日),   0,Object(Cake \ Collection \ Iterator \ MapReduce))   F:\的public_html \ sfworxerp \厂商\ cakephp的\ cakephp的\ SRC \收集\迭代\ MapReduce.php(132):   Cake \ Collection \ Iterator \ MapReduce-> _execute()[内部函数]:   蛋糕\收集\迭代\ MapReduce-> getIterator()方法   F:\的public_html \ sfworxerp \厂商\ cakephp的\ cakephp的\ SRC \收集\ Collection.php(50):   IteratorIterator-> __构建体(对象(蛋糕\收集\迭代\ MapReduce的))   F:\的public_html \ sfworxerp \供应商\ CakePHP的\ CakePHP中的\ src \收藏\ CollectionTrait.php(405):   蛋糕\收集\收藏 - > __构建体(对象(蛋糕\收集\迭代\ MapReduce的))   F:\的public_html \ sfworxerp \厂商\ cakephp的\ cakephp的\ SRC \ ORM \ Table.php(1062):   Cake \ ORM \ ResultSet-> combine('date','name',NULL)   F:\的public_html \ sfworxerp \厂商\ cakephp的\ cakephp的\ SRC \数据源\ QueryTrait.php(490):   蛋糕\ ORM \表-1>蛋糕\ ORM {闭合}(对象(蛋糕\ ORM \结果集))   F:\的public_html \ sfworxerp \厂商\ cakephp的\ cakephp的\ SRC \ ORM \ Query.php(1141):   蛋糕\ ORM \查询 - > _applyDecorators(对象(蛋糕\ ORM \结果集))   F:\的public_html \ sfworxerp \厂商\ cakephp的\ cakephp的\ SRC \数据源\ QueryTrait.php(272):   蛋糕\ ORM \查询 - > _decorateResults(对象(蛋糕\ ORM \结果集))   F:\的public_html \ sfworxerp \厂商\ cakephp的\ cakephp的\ SRC \ ORM \ Query.php(871):   蛋糕\ ORM \查询 - > _all()   F:\的public_html \ sfworxerp \厂商\ cakephp的\ cakephp的\ SRC \数据源\ QueryTrait.php(288):   蛋糕\ ORM \查询 - >所有()   F:\的public_html \ sfworxerp \ SRC \控制器\阿比\ AttendancesController.php(133):   Cake \ ORM \ Query-> toArray()[内部函数]:   应用\控制器\阿比\ AttendancesController-> getMonthAttendanceData()   F:\的public_html \ sfworxerp \厂商\ cakephp的\ cakephp的\ SRC \控制器\ Controller.php这样(429):   call_user_func_array(Array,Array)   F:\的public_html \ sfworxerp \厂商\ cakephp的\ cakephp的\ SRC \路由\ Dispatcher.php(114):   蛋糕\控制器\控制器 - > 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 \根目录\的index.php(37):   蛋糕\路由\ Dispatcher->调度(对象(蛋糕\网络\请求),   对象(Cake \ Network \ Response)){main}

非常感谢任何帮助

2 个答案:

答案 0 :(得分:7)

问题:

问题是,对于'date'字段,CakePHP 3返回一个对象,而不是字符串:

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

尝试将其用作密钥不起作用,并抛出您所看到的错误。

如何处理:

this area in the CakePHP book,为了适应这种情况,你可以:

  

使用闭包来访问列表中的实体mutator方法。

TLDR执行此操作:

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

有关其工作原理的说明:

基本上,它将每个实体的值(在您的情况下为每篇文章)放入变量$e,并允许您使用/修改它的数据,并返回您想要用作键的字符串(或价值)领域。在上面的例子中,它获取date对象,并在将其格式化为字符串之后再将其用作键。

答案 1 :(得分:1)

我尝试了一个类似的例子,我得到了同样的错误。

查看错误堆栈似乎与cake返回Time对象而不是字符串这一事实有关。

我找到了一种解决方法:您可以在实体中创建虚拟字段

瞻礼实体

protected function _getFormattedDate()
{
    if(isset($this->date))
        return $this->date->format('Y-m-d');
    return null;
}

所以你可以做到

$holidays = $holidays->find('list',[
    'keyField' => 'formatted_date',
    'valueField'=>'name',
])->toArray();

您还可以使用Dave的建议来创建自定义查找程序。

<强> HolidaysTable

public function findDate(Query $query, array $options)
{

    $options['keyField'] = function ($e) {
        if(isset($e->date))
            return $e->date->format('Y-m-d');
        return null;
    };
    $options['valueField'] = 'name';

    return  $this->findList($query, $options);
}

我刚刚添加了一个关于是否设置了日期字段的控件,否则你可能会收到错误。

<强>控制器

$holidays->find('date')->toArray();