我们可以向 CakePHP Table 对象添加自定义值吗?

Can we add custom values to a CakePHP Table Object?

查询 table:

时我有一个 Cake 对象
$invoices = TableRegistry::get('invoices')->find('all', ['conditions' => ['order_number =' => $orderNumber]]);

这很好用。然后我想将其他数组 key/values 添加到此对象,例如:

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

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

我试过这个:

compact($invoices, $invoicesTmp);

但这没有用。

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

当 CakePHP 从数据库中获取结果时,记录被存储为数组,然后 CakePHP 将它们转换为 Entity 对象。称为实体“水合”的过程。如果禁用水合作用,记录将仅作为数组返回。

$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'));

更新:

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

字段别名

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

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

以上根据使用的 table 选择不同的列 name。这允许您始终在视图中使用 $record->name,无论哪个 table.

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

字段映射

从 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 变量是由控制器注入的。您现在知道去哪里更改它了。