CakePHP 关联:处理空 ID

CakePHP associations: handle null id

我有这个型号:

Proforma
  ->hasMany('ItemProformas', ['foreignKey' => 'proforma_id']);
  ->belongsTo('Customers', ['foreignKey' => 'customer_id']);
  ->belongsTo('ProformaStates', ['foreignKey' => 'proforma_state_id']);
  ->hasMany('Invoices', ['foreignKey' => 'proforma_id']);

ItemProformas
  ->belongsTo('Proformas', ['foreignKey' => 'proforma_id', 'joinType' => 'INNER']);
  ->belongsTo('ItemDeliveryNotes', ['foreignKey' => 'item_delivery_note_id']);

ItemDeliveryNotes
    ->belongsTo('DeliveryNotes', ['foreignKey' => 'delivery_note_id', 'joinType' => 'INNER']);
    ->belongsTo('ItemOrders', ['foreignKey' => 'item_order_id']);
    ->belongsTo('ItemOrdersTypes', ['foreignKey' => 'item_orders_type_id']);
    ->belongsTo('Products', ['foreignKey' => 'product_id']);

每个ItemProforma可以有一个ItemDeliveryNotes,否则外键就是null。这是我的 paginate 电话:

$this->paginate = [
    'contain' => [
        'Customers',
        'ProformaStates',
        'ItemProformas' => ['ItemDeliveryNotes' => ['DeliveryNotes']]
    ]
];

有了这个模型,我得到了 item_delivery_note_id 设置的所有 itemProforma。相反,即使 item_delivery_note_idnull.

,我也很想得到它们

我不确定这里的 belongsTo 是否正确(我的意思是在 ItemProformas 定义中)。但是 hasOne 意味着它 一个关联行,而不是 可能 有一个。

检索 all itemProformas 的正确语法是什么,即使它们没有任何关联的 ItemDeliveryNote?但如果他们有,我还需要检索 ItemDeliveryNote 对象。

关联类型取决于您的架构。如果外键在源table,那么就是belongsTo,如果外键在目标table,那么就是hasOne.

相关记录是否必须存在也主要取决于架构,而不是关联类型。如果外键可以为空,则相关记录是可选的。如果以及如何在应用程序级别实施该约束,则另当别论。

话虽这么说,ItemDeliveryNotesDeliveryNotes 都是 belongsTo,默认情况下会使用联接,因此两个关联都将联接到同一个查询中,并且由于您已经将 DeliveryNotes 关联配置为使用 INNER 连接,它将排除不存在 DeliveryNotes 的行,当然当不存在 ItemDeliveryNotes 时也是如此。

假设您的架构是建模的 correctly/properly,例如,您可以更改关联配置以在适用的情况下默认使用 LEFT 连接,或者您可以更改包含在每个查询基础(手动或使用自定义查找器):

$this->paginate = [
    'contain' => [
        'Customers',
        'ProformaStates',
        'ItemProformas' => [
            'ItemDeliveryNotes' => [
                'DeliveryNotes' => [
                    'joinType' => \Cake\Database\Query::JOIN_TYPE_LEFT,
                ],
            ],
        ],
    ],
];

更改 ItemDeliveryNotes 的获取策略也可以工作(尽管根据记录的数量可能会很费力),即使用 select 策略而不是 join策略,则关联的 ItemDeliveryNotes 记录将在单独的查询中检索,因此不会影响 ItemProformas:

的检索
$this->paginate = [
    'contain' => [
        'Customers',
        'ProformaStates',
        'ItemProformas' => [
            'ItemDeliveryNotes' => [
                'strategy' => \Cake\ORM\Association::STRATEGY_SELECT,
                'DeliveryNotes',
            ],
        ],
    ],
];