如何 select 将特定字段附加到表默认字段?

How to select a specific field additionally to a tables default fields?

我希望使用 JOIN 连接 select 来自 table 的数据和 CakePHP 中的视图,如下所示:

$this->Annonces->find('all')
        ->where($arrFiltres)
        ->order($arrOrder)
        ->join([
            'table' => 'annonces_suivis',
            'alias' => 'AnnoncesSuivis',
            'conditions' => [...],      
        ]);

并且希望能够 select 第一个 table 的所有字段和联合 table 的一些字段,如下所示:

->select(['Annonces.*', 'AnnoncesSuivis.id']);

但这会创建一个错误的 SQL 查询。

ORM 查询不支持

.*,它会将其转换为

Annonces.* AS Annonces__*

这是无效的 SQL。它可以与较低级别的数据库查询 (Connection::newQuery()) 一起使用,它不会添加别名,但是它不会 return 实体,所以这可能不是您想要的。

Cookbook > Database Access & ORM > Database Basics > \Cake\Database\Connection::newQuery()

传递一个 table 对象

从 CakePHP 3.1 开始,您可以将 table 对象传递给 Query::select(),这将导致选择 table 的所有字段。

$this->Annonces
    ->find('all')
    ->select(['AnnoncesSuivis.id'])
    ->select($this->Annonces)
    ->join([
        'table' => 'annonces_suivis',
        'alias' => 'AnnoncesSuivis',
        'conditions' => [ /* ... */ ],     
    ])
    ->where($arrFiltres)
    ->order($arrOrder);

这样 AnnoncesSuivis.id 字段和 Annonces 的所有字段都将被选中。

Cookbook > Database Access & ORM > Query Builder > Selecting All Fields From a Table

从模式构建字段

这也是在内部传递 table 对象的原因,CakePHP < 3.1 也支持它。

$query = $this->Annonces->find('all');

$fields = $query->aliasFields(
    $this->Annonces->schema()->columns(),
    $this->Annonces->alias()
);

$query
    ->select(array_merge(['AnnoncesSuivis.id'], $fields))
    ->join([
        'table' => 'annonces_suivis',
        'alias' => 'AnnoncesSuivis',
        'conditions' => [ /* ... */ ],     
    ])
    ->where($arrFiltres)
    ->order($arrOrder);

这也适用于可以传递给 Table::find()fields 选项,尽管在这种情况下您必须使用单独的查询对象,例如

$fields = $this->Annonces->query()->aliasFields(
    $this->Annonces->schema()->columns(),
    $this->Annonces->alias()
);

$this->Annonces->find('all', [
    'fields' => array_merge(['AnnoncesSuivis.id'], $fields)
    // ...
]);

使用Query::autoFields()

在较早的 CakePHP 版本中,您还可以使用 Query::autoFields(),当设置为 true 时,将自动包含主要 table 和可能包含的字段。

Cookbook > Database Access & ORM > Retrieving Data & Results Sets > Passing Conditions to Contain

自动选择所有字段是默认行为,除非您通过 Query::select() 设置字段,在这种情况下,您必须明确启用 Query::autoFields().

$this->Annonces
    ->find('all')
    ->select(['AnnoncesSuivis.id'])
    ->autoFields(true)
    ->join([
        'table' => 'annonces_suivis',
        'alias' => 'AnnoncesSuivis',
        'conditions' => [ /* ... */ ],     
    ])
    ->where($arrFiltres)
    ->order($arrOrder);

这应该会为您提供所需的查询,但是如前所述,如果您想要包含手动加入的 table 的所有字段,这将仅适用于主要 table 和包含项,那你就得一一指定了。

您还可以在实体中创建虚拟字段:

namespace App\Model\Entity;
use Cake\ORM\Entity;

class User extends Entity { 
    protected function _getFullName() {
       return $this->_properties['first_name'] . ' ' . $this->_properties['last_name']; 
    } 
}

echo $entity->full_name;