在 Cakephp4 中加入查询只返回一个 table 数据

Joins Query in Cakephp4 only returning one table data

我正在尝试使用 CakePHP4 使用连接查询来获取评论,但是我得到的结果是简单的评论 table 数据。我怎样才能附加用户 table。

例如

public function getReviews()
{
    $this->request->allowMethod(['get']);
    
    //$authenticator = new JWTController();
    //$data        = $authenticator->requestAuthorization();

    $offset = 1;//$data['offset']; 
    
    $reviews = $this->getTableLocator()->get('Reviews');
    $result = $reviews
        ->find('all')
        ->join([
            'Users'=>  [
                'table'      => 'users',
                'type'       => 'INNER',
                'conditions' => 'Users.id = Reviews.userId',
            ]
        ])
        ->order(['Reviews.created' => 'DESC'])
        ->limit(25)
        ->page($offset)->toArray();
            
    $this->jsonOutput(array(
        'error' => false,
        'limit' => 25,
        'data'  => $result
    ));
}
{
    "id": 1,
    "userId": 1,
    "rating": 4,
    "review": "How are you",
    "created": "2020-10-11T23:14:44+00:00"
}

检查生成的 SQL!加入某些东西首先只会做到这一点,创建一个连接。如果您想要来自该连接的任何数据,那么您必须通过选择相应的字段明确地告诉查询构建器:

$reviews
    ->find()
    // select all fields of the reviews table
    ->select($reviews)
    // select specific fields from the join
    ->select(['Users.username', 'Users.email', /* ... */])
    ->join(/* ... */)
    // ...

结果看起来像这样(您可能想为连接使用不同的别名,因为 Users 很奇怪,它至少应该是单数):

{
    "id": 1,
    "userId": 1,
    "rating": 4,
    "review": "How are you",
    "created": "2020-10-11T23:14:44+00:00",
    "Users": {
        "username": "Foo",
        "email": "foo@example.com",
        // ...
    }
}

然而,您可能应该改为使用关联,然后使用 contain(),这样您就不必一遍又一遍地重复自己。在你的 ReviewsTable class 中设置一个 BelongsTo 关联:

public function initialize(array $config): void
{
    // ....

    $this
        ->belongsTo('Users')
        ->setForeignKey('userId')
        ->setJoinType(\Cake\Database\Query::JOIN_TYPE_INNER);
}

理想情况下,您应该遵循命名约定并将外键字段命名为 user_id,然后 CakePHP 将自动选择它,并且您不必使用非常规的字段名称进行配置(对于 BelongsTo 默认名称是关联名称的单数 lowercased/underscored 变体,附加 _id)。

$reviews
    ->find()
    ->contain('Users')
    ->order(/*...*/)
    // ...

结果看起来像这样:

{
    "id": 1,
    "userId": 1,
    "rating": 4,
    "review": "How are you",
    "created": "2020-10-11T23:14:44+00:00",
    "user": {
        "id": 1,
        "username": "Foo",
        // ...
    }
}

另见