Can we add custom values to a CakePHP Table Object?

风格不统一 提交于 2020-01-24 19:10:08

问题


I have a Cake Object when querying a table:

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

This works fine. I then want to add other array key/values to this Object, like this one:

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

But $invoicesTmp is incompatible with $invoices. (one is an array, other is an CakePHP Object)

I have tried this:

compact($invoices, $invoicesTmp);

but that didn't worked.


回答1:


The find() method of a Table object returns a Cake\ORM\Query object. This object is used to build SQL queries and to execute them. It has some features to define how the results from the query should be returned.

When CakePHP fetches results from the database the records are stored as an array, and CakePHP then converts them to Entity objects. A process called "hydration" of entities. If you disable hydration the records are returned as just an array.

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

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

The above creates a query object, and you can iterate over the query records because the object itself supports iteration.

The query object implements the Cake\Collection\CollectionInterface interface, which means we can perform a bunch of collection methods on it. The most common method is the toArray().

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

The $invoices variable is now a valid array object holding the all the records with each record as an array object.

You can now easily use array_merge to assign extra metadata to each record.

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

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

Updated:

Based upon the comments it appears you wish to use two different tables with different column names, but those columns represent the same data.

Field Aliases

You can rename fields in the SQL query to share a common alias.

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

The above selects a different column for name depending upon which table is being used. This allows you to always use $record->name in your view no matter which table.

I don't like this approach, because it makes the source code of the view file appear to reference a property of the entity that doesn't really exist. You might get confused when returning to the code later.

Field Mapping

From a MVC perspective. Only the controller knows what a view needs. So it's easier if you express this knowledge as a mapping.

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

Later in your view to output the columns you do it like this:

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

It becomes verbose as to what is happening, and why. You can see in the view that the controller provided a mapping between something called name and the actual field. You also know that the $map variable was injected by the controller. You now know where to go to change it.



来源:https://stackoverflow.com/questions/47865478/can-we-add-custom-values-to-a-cakephp-table-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!