在CakePHP 3中检索相关数据(hasMany)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在CakePHP 3中检索相关数据(hasMany)相关的知识,希望对你有一定的参考价值。
Events hasMany TicketTypes
TicketTypes belogsTo Events
我正在尝试检索具有相关故障单类型的所有事件:
$query= $this->Events
->find()
->select(['id', 'name'])
->autoFields(false)
->contain(['TicketTypes' => function($q) {
return $q->select(['TicketTypes.id', 'TicketTypes.name']); }])
;
生成的SQL查询:
SELECT Events.id AS `Events__id`, Events.name AS `Events__name` FROM events Events
但我的期望是:
SELECT Events.id AS `Events__id`, Events.name AS `Events__name`, TicketTypes.id AS `TicketTypes__id`, TicketTypes.name AS `TicketTypes__name` FROM events Events LEFT JOIN ticket_types TicketTypes ON Events.id = (TicketTypes.event_id)
这就是我的模型的配置方式:
class EventsTable extends Table
{
public function initialize(array $config)
{
$this->displayField('name');
$this->addAssociations([
'hasMany'=> ['TicketTypes']
]);
}
}
class TicketTypesTable extends Table
{
public function initialize(array $config)
{
$this->displayField('name');
$this->addAssociations([
'belongsTo' => ['Events']
]);
}
}
以下是调试查询查询的结果:
object(CakeORMQuery) {
'(help)' => 'This is a Query object, to get the results execute or iterate it.',
'sql' => 'SELECT Events.id AS `Events__id`, Events.name AS `Events__name` FROM events Events',
'params' => [],
'defaultTypes' => [
'Events.id' => 'integer',
'id' => 'integer',
'Events.name' => 'string',
'name' => 'string',
'Events.datetime_start' => 'datetime',
'datetime_start' => 'datetime',
'Events.datetime_end' => 'datetime',
'datetime_end' => 'datetime',
'Events.created' => 'datetime',
'created' => 'datetime',
'Events.modified' => 'datetime',
'modified' => 'datetime',
'Events.slug' => 'string',
'slug' => 'string',
'TicketTypes.id' => 'integer',
'TicketTypes.event_id' => 'integer',
'event_id' => 'integer',
'TicketTypes.name' => 'string',
'TicketTypes.description' => 'text'
],
'decorators' => (int) 0,
'executed' => false,
'hydrate' => true,
'buffered' => true,
'formatters' => (int) 0,
'mapReducers' => (int) 0,
'contain' => [
'TicketTypes' => [
'queryBuilder' => object(Closure) {
}
]
],
'matching' => [],
'extraOptions' => [],
'repository' => object(AppModelTableEventsTable) {
'registryAlias' => 'Events',
'table' => 'events',
'alias' => 'Events',
'entityClass' => 'AppModelEntityEvent',
'associations' => [
(int) 0 => 'tickettypes'
],
'behaviors' => [],
'defaultConnection' => 'default',
'connectionName' => 'default'
}
}
这是调试$query->all()
的结果:
object(CakeORMResultSet) {
'items' => [
(int) 0 => object(AppModelEntityEvent) {
'id' => (int) 101,
'name' => 'qwertyuiop',
'ticket_types' => [],
'[new]' => false,
'[accessible]' => [
'*' => true
],
'[dirty]' => [],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[repository]' => 'Events'
},
...
正如您在此行中所看到的那样,查询不会返回'ticket_types' => []
票证类型。
我该怎么做才能检索TicketTypes
数据?
谢谢。
hasMany
关联正在单独的查询中检索
关于Cakephp ORM如何检索关联数据的假设是不正确的。
与在主查询中使用连接的hasOne
和belongsTo
关联不同,hasMany
和belongsToMany
关联数据在单独的查询中被检索,该查询使用从主查询收集的外键值进行过滤,在您的情况下将是Events.id
列值。
查看SQL日志的其余部分,您应该找到类似的查询
SELECT
TicketTypes.id AS `TicketTypes__id`, ...
FROM
ticket_types TicketTypes
WHERE
TicketTypes.event_id IN (1,2,3, ...)
该查询的结果与主结果一起拼接,并在单个结果集中返回。
需要选择外键
第二个问题是你的包含select()
调用缺少外键列(TicketTypes.event_id
),这是必需的,因为没有它,ORM不能将结果拼接在一起,因此票证类型将不会出现在结果中。
从文档引用:
限制从关联中提取的字段时,必须确保选择了外键列。未能选择外键字段将导致相关数据不存在于最终结果中。
也可以看看
- Cookbook > Database Access & ORM > Retrieving Associated Data
- Cookbook > Database Access & ORM > Query Builder > Passing Conditions to Contain
以上是关于在CakePHP 3中检索相关数据(hasMany)的主要内容,如果未能解决你的问题,请参考以下文章
CakePHP - 在模型中查找没有 hasMany 关系的 hasMany 关联?
在 CakePHP 中使用 saveAll() 保存多个 hasMany 数据,而无需在视图中写入 id
在 CakePHP 中获取多个插入的 hasMany 项的 id