在我的cakephp 2.0项目中我有这个模型场景(遵循伪代码):
model Product {
int id;
Video video;
}
model Video {
....
}
我想使用cakephp $ this-> Product-> find('all')获取我的所有产品和相关视频。 Cakephp以这种方式在多维数组中给出结果:
{
Product: {
id: "3",
video_id: "1",
},
Video: {
id: "1",
url: "c",
},
{
Product: {
id: "3",
video_id: "1",
},
Video: {
id: "1",
url: "c",
}
如何在父Product中获取视频(子对象),这样:
{
Product: {
id: "3",
video_id: "1",
Video: {
id: "1",
url: "c",
}
}
我知道,对于这个特殊情况,它很容易创建一个新数组,因为只有两个对象,但无论如何都要使这个自动更大的关系,cakephp可以处理这个吗?
答案 0 :(得分:2)
这将有助于在findall
中获取每个产品中的每个Video子项$products = $this->Product->find('all')
foreach($products as $product) {
echo $product["Video"]["url"];
}
答案 1 :(得分:2)
Cake返回对象的方式是正确的,因为它正在访问连接并返回主find对象内的数据。
如果您有更深层次的递归或者使用可包含来访问更深层次的关系,则您正在讨论的对象内的对象会发生。
例如
$this->Product->find('all');
会返回像
这样的对象array(
'Product' => array(
'id' => '3',
'video_id' => '1',
),
'Video' => array(
'id' => '1',
'url' => c,
),
)
只有在该模型上有hasMany或HABTM连接或您更改级别或使用可包含然后查看已连接模型的关系时,才会发生对象布局。
我希望这是有道理的。
答案 2 :(得分:2)
尝试这种方法。覆盖默认find('all')
,以便它接受自定义参数,这将允许重新格式化结果。将其放在AppModel
中,以便所有模型都可以访问
根据评论的要求编辑,从重新格式化的结果中删除HABTM关联的空关联和联合数据:
class AppModel extends Model
{
protected function _findAll($state, $query, $results = array())
{
if ($state === 'before') {
return $query;
}
if (isset($query['reformat']) && $query['reformat'] === true) {
foreach ($results as &$_result) {
reset($_result);
$modelName = key($_result);
$modelPart = array_shift($_result);
if (!empty($query['filter']) && is_array($query['filter'])) {
$this->recursive_unset($_result, $query['filter']);
}
$_result = array(
$modelName => array_merge($modelPart, $_result)
);
}
}
return $results;
}
public function getHabtmKeys() {
$habtmKeys = array();
// 1. level inspection
foreach ($this->hasAndBelongsToMany as $name) {
$habtmKeys[] = $name['with'];
}
// 2. level inspection
$allAsssoc = array_merge(
$this->belongsTo,
$this->hasMany,
$this->hasOne
);
foreach ($allAsssoc as $assocName => $assocVal) {
foreach ($this->$assocName->hasAndBelongsToMany as $name) {
$habtmKeys[] = $name['with'];
}
}
return $habtmKeys;
}
private function recursive_unset(&$array, $keys_to_remove) {
foreach ($keys_to_remove as $_key) {
unset($array[$_key]);
}
foreach ($array as $key => &$val) {
if (is_array($val)) {
if (empty($val) || (!isset($val[0]) && empty($val['id']))) {
unset($array[$key]);
} else {
$this->recursive_unset($val, $keys_to_remove);
}
}
}
}
}
要删除空关联和HABTM联合数据,我使用 recursive unset procedure 结合检查关联来获取相关模型。我无法通过配置find,contains或任何其他方式实现此目的。
下一个array_shift($_result)
将$_result
数组分为两部分 - 运行find
的主模型(它始终是结果中的第一个键) 其余(所有关联),然后它将这些数组合并到主模型的键下。当然,这仅在第一级重新格式化结果,但在更深层次上是默认嵌套的关联,因此您不需要关心它。
现在一如既往地使用find('all')
,但提供自定义reformat
和filter
参数。如果您不提供它们,结果将以默认格式提取。
filter
是要从结果中删除的键数组
getHabtmKeys()
动态获取模型的HABTM关联键数组(只有1和2级关联,可以进一步修改以更深入地检查)。
<强>用法:强>
// To nest child associations in parent
$this->Product->find('all', array(
'reformat' => true
));
// To remove also joint data for HABTM and empty associations
$this->Product->find('all', array(
'reformat' => true,
'filter' => $this->Product->getHabtmKeys(),
));
// Keys to remove can be also manually added
$this->Product->find('all', array(
'reformat' => true,
'filter' => array_merge($this->Product->getHabtmKeys(), 'SomeExtraKey'),
));