我们可以将自定义值添加到CakePHP表对象吗?

时间:2017-12-18 09:33:06

标签: php cakephp cakephp-3.0

查询表时我有一个Cake对象:

$invoices = TableRegistry::get('invoices')->find('all', ['conditions' => ['order_number =' => $orderNumber]]);

这很好用。然后我想将其他数组键/值添加到此Object,如下所示:

$invoicesTmp = array();
$invoicesTmp['customer'] = "name of customer";

$invoicesTmp与$发票不兼容。 (一个是数组,另一个是CakePHP对象)

我试过这个:

compact($invoices, $invoicesTmp);

但这没效果。

1 个答案:

答案 0 :(得分:4)

Table对象的find()方法返回Cake\ORM\Query个对象。此对象用于构建SQL查询并执行它们。它有一些功能来定义如何返回查询结果。

当CakePHP从数据库中获取结果时,记录将存储为数组,然后CakePHP将它们转换为Entity个对象。一个名为" hydration"实体如果禁用水合作用,记录将仅作为数组返回。

$query = TableRegistry::get('invoices')
                 ->find()
                 ->where(['order_number'=>$orderNumber])
                 ->enableHydration(false);

foreach($query as $record) {
    pr($record);
}

以上创建了一个查询对象,您可以迭代查询记录,因为该对象本身支持迭代。

查询对象实现了Cake\Collection\CollectionInterface接口,这意味着我们可以在其上执行一堆收集方法。最常见的方法是toArray()

$invoices = TableRegistry::get('invoices')
                 ->find()
                 ->where(['order_number'=>$orderNumber])
                 ->enableHydration(false)
                 ->toArray();

$invoices变量现在是一个有效的数组对象,它将每条记录的所有记录保存为数组对象。

您现在可以轻松使用array_merge为每条记录分配额外的元数据。

$invoices = array_map(function($invoice) {
     return array_merge(['customer'=>'name of customer'], $invoice);
}, $invoices);

$this-set(compact('invoices'));

<强>更新

根据评论显示,您希望使用具有不同列名的两个不同表,但这些列表示相同的数据。

字段别名

您可以重命名SQL查询中的字段以共享公共别名。

  $table = TableRegistry::get($whichTable ? 'table_a' : 'table_b');
  $records = $table->find()
               ->select([
                   'id',
                   'invoice_id',
                   'name' => ? $whichTable ? 'customer_name' : 'invoice_name'
               ])->all();

以上为name选择了不同的列,具体取决于正在使用的表。这使您可以始终在视图中使用$record->name,无论哪个表格。

我不喜欢这种方法,因为它使视图文件的源代码看起来引用了实际上不存在的实体的属性。稍后返回代码时可能会感到困惑。

字段映射

从MVC的角度来看。只有控制器知道视图需要什么。因此,如果您将此知识表达为映射,则会更容易。

  $map = [
      'id'=>'id',
      'invoice_id'=>'invoice_id',
      'name' => ? $whichTable ? 'customer_name' : 'invoice_name'
  ];

  $table = TableRegistry::get($whichTable ? 'table_a' : 'table_b');
  $records = $table->find()
               ->select(array_values($map))
               ->all();
  $this->set(compact('records','map'));

稍后在您的视图中输出列,您可以这样做:

  foreach($records as $record) {
        echo $record->get($map['name']);
  }

关于发生了什么以及为什么会变成详细。您可以在视图中看到控制器提供了名为name的内容与实际字段之间的映射。您还知道控制器注入了$map变量。你现在知道去哪里改变它。