如何只检索那些至少有一个关联记录的记录?

时间:2016-04-02 13:00:04

标签: cakephp associations query-builder cakephp-3.2

数据应仅显示包含数据的租约。在正常查询中,通常我这样做是正确的加入。

我知道contain()在默认情况下是左连接,但可以包含正确的连接吗?

我的查询:

$properties = $this->find()
                ->select([
                    'Property.id', 'Property.company_id', 'Property.address1', 'Property.postcode',  
                ])
                ->contain([                    
                    'Tenancies' => function($q) {
                        return $q
                            ->select([
                                'Tenancies.id','Tenancies.property_id','Tenancies.created',
                                'Tenancies.stage', 'Tenancies.landlord_offer_sent', 'Tenancies.offer_letter_contract_id',
                            ])
                            ->contain([
                                'Tenants' => function($q) {
                                    return $q
                                        ->select([
                                            'Tenants.id', 'Tenants.stage', 'Tenants.tenancy_id', 'Tenants.holding_fee',
                                        ])
                                        ->where([
                                            'active = 1',
                                        ]);
                                    }
                            ])
                            ->where([
                                'Tenancies.active = 1',
                            ]);
                    }
                ])
                ->where(['Property.active = 1', $conditions])
                ->toArray();

e.g。我需要读取节点为空'tenancies' => [],的节点,它应该只显示节点1.

打印=>

(int) 0 => object(App\Model\Entity\Property) {

        'id' => (int) 95,
        'company_id' => (int) 3,
        'address1' => '40 Arthur Street',
        'postcode' => 'LE11 3AY',
        'tenancies' => [],
        '[new]' => false,
        '[accessible]' => [
            '*' => true
        ],
        '[dirty]' => [],
        '[original]' => [],
        '[virtual]' => [],
        '[errors]' => [],
        '[invalid]' => [],
        '[repository]' => 'Property'

    },
    (int) 1 => object(App\Model\Entity\Property) {

        'id' => (int) 102,
        'company_id' => (int) 3,
        'address1' => 'Grace Dieu Court',
        'postcode' => 'LE11 4QH',
        'tenancies' => [
            (int) 0 => object(App\Model\Entity\Tenancy) {

                'id' => (int) 16,
                'property_id' => (int) 102,
                'created' => object(Cake\I18n\FrozenTime) {

                    'time' => '2015-05-08T09:30:41+00:00',
                    'timezone' => 'UTC',
                    'fixedNowTime' => false

                },
                'stage' => (int) 6,
                'landlord_offer_sent' => false,
                'offer_letter_contract_id' => (int) 37,
                'tenants' => [
                    (int) 0 => object(Cake\ORM\Entity) {

                        'id' => (int) 16,
                        'stage' => (int) 7,
                        'tenancy_id' => (int) 16,
                        'holding_fee' => (float) 50,
                        '[new]' => false,
                        '[accessible]' => [
                            '*' => true
                        ],
                        '[dirty]' => [],
                        '[original]' => [],
                        '[virtual]' => [],
                        '[errors]' => [],
                        '[invalid]' => [],
                        '[repository]' => 'Tenants'

                    },
                    (int) 1 => object(Cake\ORM\Entity) {
                    ...
                    ...
                    ...

我尝试了内连接'joinType' => 'INNER',但没有运气:

class TenancyTable extends Table
{

    /**
     * Initialize method
     *
     * @param array $config The configuration for the Table.
     * @return void
     */
    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->table('tenancy');
        $this->displayField('id');
        $this->primaryKey('id');

        $this->addBehavior('Timestamp');

        $this->belongsTo('Properties', [
            'foreignKey' => 'property_id',
            'className' => 'property',
            'joinType' => 'INNER'
        ]);

2 个答案:

答案 0 :(得分:0)

不能通过hasMany关联的包含

使用包含无法完成此操作,因为hasMany是通过单独的查询检索的。相反,您必须自己添加正确的联接,INNER联接(比RIGHT联接更便携)可以执行此操作,如果您想将结果限制为仅具有关联的联接{ {1}}。

没有条件的简单Tenancies,以及一些避免重复的分组

Query::innerJoinWith()

...而且你已经完成了,这将添加一个像

这样的连接
$properties = $this
    ->find()
    // ...
    ->innerJoinWith('Tenancies')
    ->group('Property.id');

INNER JOIN tenancies Tenancies ON Property.id = Tenancies.property_id 也适用于所有其他类型的关联

对于innerJoinWith()belongsTo关联,可以通过包含来完成,因为对于这些类型的关联,所有数据都在同一查询中检索。要按具有关联记录的那些进行过滤,只需将连接类型更改为hasOne,例如

INNER

另见

答案 1 :(得分:0)

当我简单地将contains更改为matching时,此方法有效。

似乎有可能,请参见Filtering By Associated Data