CakePHP 3 - 保存时在关联中找不到插件 table
CakePHP 3 - Plugin table not found in associations when saving
我有一个插件,其中包含它使用的所有 tables。
plugins
/MyPlugin
/src
/Model
/Table
EventsTable.php
EventValuesTable.php
...
我正在尝试保存一个 Event
实体及其相关的 hasMany EventValues
关联。
$data = [
'event_type_id' => 5,
'event_values' => $values // An array of EventValue entities
];
$event = $eventsTable->newEntity($data, [
'associated' => ['MyPlugin.EventValues']
]);
但是,它找不到关联的 table 并给出以下错误:
无法为 "MyPlugin" 关联整理数据。它与 "Events"
无关
现在我已经花了几个小时调试它,这是我目前的状态:
3.3 版本引入 Cake 核心的一段新代码抛出异常
\Cake\ORM\Marshaller.php (Line 94) 在尝试分解 associated
数组时抛出异常。
问题:
Marshaller
class 似乎将 MyPlugin.EventValues
关联视为嵌套模型关联 - 即它认为 MyPlugin
是与正在保存的主要实体 (Event
)。它不是在我的插件的 src/Table
目录中寻找模型。
我需要找到一种方法让 Cake 意识到 MyPlugin.EventValues
意味着:
plugins/MyPlugin/src/Model/Table/EventValuesTable.php
相反,它将其分析为:
src/Model/Table/MyPluginsTable.php
所以我的问题是:
- 这是引入的 Cake 错误吗?
- 如果不是,我如何告诉它从我的插件 tables 建立关联?
我知道你们首先要问的是查看我的模型关联和所有内容,但在从 Cake 3.1 更新到 3.3 之前这是有效的,我 100% 确定关联是正确的。请记住所有 table 都在插件 table 目录中,主应用程序 table 目录中没有任何内容。
关联别名无需插件
您似乎混淆了 class 名称和关联别名,后者可以独立于使用的 class 定义,并且可能的插件前缀正在从中丢弃。
例如创建关联时
$this->hasMany('MyPlugin.EventValues');
关联class会将整个别名(即MyPlugin.EventValues
)设置为className
选项,然后拆分class名称(EventValues
)来自插件名称(MyPlugin
),并将前者设置为关联名称(即EventValues
)。
这与像
这样定义关联实际上是一样的
$this->hasMany('EventValues', [
'className' => 'MyPlugin.EventValues'
]);
所以从逻辑上讲,您现在必须通过无插件名称来引用关联,即
'associated' => ['EventValues']
然后 ORM 将从关联的 className
选项值前缀的插件中计算出正确的 class名称。
不存在的关联现在会严重失败
你在那里做的事情在 3.1 中只是运气好,在 3.3 之前,不存在的关联是 discarded in the marshalling process,导致事情可能会悄无声息地失败,即 ['MyPlugin.EventValues']
实际上与通过相同一个空数组。
从 3.3 开始,不存在的关联将 cause an exception to be raised,这就是您所看到的。引自文档:
Table::newEntity()
and Table::patchEntity()
will now raise an exception when an unknown association is in the associated
key.
Cookbook > 3.X Migration Guide > 3.3 Migration Guide > ORM Improvements.
您不能编组实体
不支持编组实体。如果你想传递现成的实体,你不能将相应的关联标记为已编组,那样会出错,准确地说,你会留下一个空的 event_values
属性,如 non-array values are being discarded.
所以,正如已经提到的,它只是靠运气。在 3.1 中,你不存在的关联将被丢弃,导致 event_values
属性 被排除在关联编组过程之外,导致传递的数据按原样设置在 $event
实体上.
如果您已经为关联创建了现成的实体,请不要将其标记为已编组
$event = $eventsTable->newEntity($data);
或在编组过程后将它们设置在生成的实体上
$event = $eventsTable->newEntity($data);
$event->event_values = $arrayOfEventValueEntities;
当然,如果事先没有特定的原因需要创建实体,那么只需将数据以数组格式传递,然后让编组器将其相应地转换为实体
$data = [
'event_type_id' => 5,
'event_values' => [
['event_value_property' => 'value'],
['event_value_property' => 'value'],
// ...
]
];
$event = $eventsTable->newEntity($data, [
'associated' => ['EventValues']
]);
我有一个插件,其中包含它使用的所有 tables。
plugins
/MyPlugin
/src
/Model
/Table
EventsTable.php
EventValuesTable.php
...
我正在尝试保存一个 Event
实体及其相关的 hasMany EventValues
关联。
$data = [
'event_type_id' => 5,
'event_values' => $values // An array of EventValue entities
];
$event = $eventsTable->newEntity($data, [
'associated' => ['MyPlugin.EventValues']
]);
但是,它找不到关联的 table 并给出以下错误:
无法为 "MyPlugin" 关联整理数据。它与 "Events"
无关现在我已经花了几个小时调试它,这是我目前的状态:
3.3 版本引入 Cake 核心的一段新代码抛出异常
\Cake\ORM\Marshaller.php (Line 94) 在尝试分解
associated
数组时抛出异常。
问题:
Marshaller
class 似乎将 MyPlugin.EventValues
关联视为嵌套模型关联 - 即它认为 MyPlugin
是与正在保存的主要实体 (Event
)。它不是在我的插件的 src/Table
目录中寻找模型。
我需要找到一种方法让 Cake 意识到 MyPlugin.EventValues
意味着:
plugins/MyPlugin/src/Model/Table/EventValuesTable.php
相反,它将其分析为:
src/Model/Table/MyPluginsTable.php
所以我的问题是:
- 这是引入的 Cake 错误吗?
- 如果不是,我如何告诉它从我的插件 tables 建立关联?
我知道你们首先要问的是查看我的模型关联和所有内容,但在从 Cake 3.1 更新到 3.3 之前这是有效的,我 100% 确定关联是正确的。请记住所有 table 都在插件 table 目录中,主应用程序 table 目录中没有任何内容。
关联别名无需插件
您似乎混淆了 class 名称和关联别名,后者可以独立于使用的 class 定义,并且可能的插件前缀正在从中丢弃。
例如创建关联时
$this->hasMany('MyPlugin.EventValues');
关联class会将整个别名(即MyPlugin.EventValues
)设置为className
选项,然后拆分class名称(EventValues
)来自插件名称(MyPlugin
),并将前者设置为关联名称(即EventValues
)。
这与像
这样定义关联实际上是一样的$this->hasMany('EventValues', [
'className' => 'MyPlugin.EventValues'
]);
所以从逻辑上讲,您现在必须通过无插件名称来引用关联,即
'associated' => ['EventValues']
然后 ORM 将从关联的 className
选项值前缀的插件中计算出正确的 class名称。
不存在的关联现在会严重失败
你在那里做的事情在 3.1 中只是运气好,在 3.3 之前,不存在的关联是 discarded in the marshalling process,导致事情可能会悄无声息地失败,即 ['MyPlugin.EventValues']
实际上与通过相同一个空数组。
从 3.3 开始,不存在的关联将 cause an exception to be raised,这就是您所看到的。引自文档:
Table::newEntity()
andTable::patchEntity()
will now raise an exception when an unknown association is in theassociated
key.
Cookbook > 3.X Migration Guide > 3.3 Migration Guide > ORM Improvements.
您不能编组实体
不支持编组实体。如果你想传递现成的实体,你不能将相应的关联标记为已编组,那样会出错,准确地说,你会留下一个空的 event_values
属性,如 non-array values are being discarded.
所以,正如已经提到的,它只是靠运气。在 3.1 中,你不存在的关联将被丢弃,导致 event_values
属性 被排除在关联编组过程之外,导致传递的数据按原样设置在 $event
实体上.
如果您已经为关联创建了现成的实体,请不要将其标记为已编组
$event = $eventsTable->newEntity($data);
或在编组过程后将它们设置在生成的实体上
$event = $eventsTable->newEntity($data);
$event->event_values = $arrayOfEventValueEntities;
当然,如果事先没有特定的原因需要创建实体,那么只需将数据以数组格式传递,然后让编组器将其相应地转换为实体
$data = [
'event_type_id' => 5,
'event_values' => [
['event_value_property' => 'value'],
['event_value_property' => 'value'],
// ...
]
];
$event = $eventsTable->newEntity($data, [
'associated' => ['EventValues']
]);