gpt4 book ai didi

php - 如何使用 bindModel 和自定义查找器将 CakePHP 2 模型关联更改为深度链接?

转载 作者:行者123 更新时间:2023-11-29 19:40:00 25 4
gpt4 key购买 nike

我正在尝试复制此有效的 SQL 查询结果:

SELECT r.id, r.day, s.ddbroute_id, s.delivery_id, d.id, d.laststatusid, t.id, t.delivery_id, t.statusstage_id, st.id, st.stage
FROM ddbroutes r
LEFT JOIN ddbrouteslots s on r.id = s.ddbroute_id
LEFT JOIN deliveries d on s.delivery_id = d.id
LEFT JOIN trackingstatuses t on d.laststatusid = t.id
LEFT JOIN statusstages st on t.statusstage_id = st.id

我正在使用 CakePHP 2 模型

  1. bindModel 用于动态更改模型关联
  2. 自定义查找将逻辑放入模型中

第二层以外的底部表格没有公共(public)字段。错误消息是:“模型“Ddbroute”与模型“Delivery”不关联。”因此,我在“包含”数组中尝试了带或不带 Delivery 的情况,两种方式都没有引入 Delivery 字段。如果合适的话,我很乐意使用联接。我已阅读了 StackOverflow 上我能找到的最相关的帖子。

我的代码和更多信息如下。非常感谢任何帮助。

<小时/>

我有五个表(包括以下字段):

ddbroutes (id, day)
ddbrouteslots (id, ddbroute_id, delivery_id)
deliveries (id, laststatusid)
trackingstatuses (id, statusstage_id)
statusstages (id, stage)

模型中设置了以下关系:

Ddbroute hasMany Ddbrouteslot (Ddbrouteslot belongsTo Ddbroute)
Delivery hasOne Ddbrouteslot (Ddbrouteslot belongsTo Delivery)
Delivery hasMany Trackingstatus (Trackingstatus belongsTo Delivery)
Statusstage hasMany Trackingstatus (Trackingstatus belongsTo Statusstage)

尽管 Delivery hasOne Ddbrouteslot(这将是 hasMany - 修订版 - 现在仍保留为 hasOne),但对于任何单个 Ddbroute,只有一个与每个 Ddbrouteslot 关联的 Delivery。所有模型均设置了 Containable。我不知道是否需要先使用 unbindModel(它没有更改错误消息)。

我在 Ddbroute.php 模型文件中的代码(仅限交付表)

public $findMethods = array('ddbstatuses' => true);

protected function _findDdbstatuses($state, $query, $results = array()) {
if ($state === 'before') {
$ddbrouteslotmodel = ClassRegistry::init('Ddbrouteslot');
$ddbrouteslotmodel->unbindModel(
array('belongsTo' => array('Delivery'))
);
$ddbrouteslotmodel->bindModel(
array('hasOne' => array(
'Delivery' => array(
'className' => 'Delivery',
'foreignKey' => 'id',
'dependent' => false,
'fields' => array(
'id', 'laststatusid'
)
)
))
);

$deliverymodel = ClassRegistry::init('Delivery');
$deliverymodel->unbindModel(
array('hasOne' => array('Ddbrouteslot'))
);
$deliverymodel->bindModel(
array('belongsTo' => array(
'Delivery' => array(
'className' => 'Delivery',
'foreignKey' => 'delivery_id'
)
)
)
);

$query['contain'] = array(
'Ddbrouteslot', 'Delivery'
);
return $query;
}
return $results;
}

在另一个 Controller 中,运行查找操作:

$this->LoadModel('Ddbroute');
$ddbstatuses = $this->Ddbroute->find('ddbstatuses');
$this->set(compact('ddbstatuses')); // to make available in a view

我还进一步尝试使用长连接数组,但查询没有引入任何 Delivery、Trackingstatus 或 Statusstage 信息,尽管查询似乎已运行。

  public $findMethods = array('ddbstatuses' => true);

protected function _findDdbstatuses($state, $query, $results = array()) {
if ($state === 'before') {

ClassRegistry::init('Delivery'); // not sure these three lines were needed so I tried with and without them
ClassRegistry::init('Trackingstatus');
ClassRegistry::init('Statusstage');



$query['joins'] = array(
array(
'table' => 'ddbrouteslots',
'alias' => 'Ddbrouteslot',
'type' => 'LEFT',
'conditions' => array(
'Ddbroute.id = Ddbrouteslot.ddbroute_id'
)),
array(
'table' => 'deliveries',
'alias' => 'Delivery',
'type' => 'LEFT',
'conditions' => array(
'Ddbrouteslot.id = Delivery.id'
)),
array(
'table' => 'trackingstatuses',
'alias' => 'Trackingstatus',
'type' => 'LEFT',
'conditions' => array(
'Delivery.laststatusid = Trackingstatus.id'
)),
array(
'table' => 'statusstages',
'alias' => 'Statusstage',
'type' => 'LEFT',
'conditions' => array(
'Trackingstatus.statusstage_id = Statusstage.id'
))
);


$query['contain'] = array(
'Ddbrouteslot',
'Delivery', // Not sure I should be adding these other models, so I tried with and without them
'Trackingstatus',
'Statusstage'
);
return $query;
}
return $results;
}

最佳答案

经过一些帮助,我现在有四种解决方案来获取我的数据,尽管实际上其中三个是第一个解决方案的变体。我相对缺乏经验,有些基本的东西我不太欣赏。

<强>1。在 Controller 中

$this->LoadModel("Ddbrouteslot");
$res = $this->Ddbrouteslot->find("all", array(
"conditions" => array(
"Ddbrouteslot.delivery_id > 0",
"Ddbrouteslot.ddbroute_id" => 45
),
"contain" => array(
"Ddbroute",
"Delivery" => array(
"Trackingstatus" => array(
"order" => array(
"Trackingstatus.id" => "desc"
),
"limit" => 1,
"Statusstage"
)
)
)
);

来自 DebugKit 的计时:主查询为 20 毫秒; Trackingstatus 和 Statusstage 是针对四个相关交付的额外查询,每次 18 毫秒 x 4;总时间为 164 毫秒。这非常慢,并不理想。

这要从第二个模型 Ddbrouteslot 开始,因为它与 Ddbroute 和 Delivery 都有直接关系。任何协会均未发生任何变化。从 Ddbrouteslot 到 Delivery 的 ownTo 关系工作正常。Delivery_id 上的 Delivery 和 Trackingstatus 之间已经存在 hasMany 关系。

<小时/>

<强>2。使用 SQL

$this->LoadModel("Ddbroute");
$qres = $this->Ddbroute->query(
"SELECT *
FROM
ddbroutes AS r
LEFT JOIN ddbrouteslots s on r.id = s.ddbroute_id
LEFT JOIN deliveries d on s.delivery_id = d.id
LEFT JOIN trackingstatuses t on d.laststatusid = t.id
LEFT JOIN statusstages st on t.statusstage_id = st.id
WHERE s.delivery_id > 0 AND s.ddbroute_id = 45
;"
debug($qres);

时间:这花了 19 毫秒。这意味着速度要快得多。 Cake 文档中不建议这样做,并且显然它不像纯 Cake find 那样在数据库之间可移植。

<小时/>

<强>3。更改基本模型

$rres = $this->Ddbroute->find("all", array(
"conditions" => array(
"Ddbroute.id" => 45
),
"recursive" => -1,
"contain" => array(

"Ddbrouteslot" => array(
"conditions" => array(
"Ddbrouteslot.delivery_id > 0"
),
"Delivery" => array(
"Trackingstatus" => array(
"order" => array(
"Trackingstatus.id" => "desc"
),
"limit" => 1,
"Statusstage"
)
)
)
)
));
debug($rres);

计时:主查询为 18 毫秒;对于四个相关的交付,Delivery、Trackingstatus 和 Statusstage 均为 18ms x 4;总时间为 234 毫秒。它速度较慢,因为每次发货都需要运行 Delivery,因为它不在 Ddbroute 的模型内。改变递归并没有什么区别。

<小时/>

<强>4。使用自定义查找这与上面的 1.) 是相同的查询,但只是使用了自定义查找方法。

public $findMethods = array('ddbstatuses' => true);   
protected function _findDdbstatuses($state, $query, $results = array()) {
if ($state === 'before') {
$query['conditions'] = array(
"Ddbrouteslot.delivery_id > 0",
"Ddbrouteslot.ddbroute_id" => 45
);
$query['contain'] = array(
"Ddbroute",
"Delivery"=> array(
"Trackingstatus" => array(
"order" => array(
"Trackingstatus.id" => "desc"
),
"limit" => 1,
"Statusstage"
)
)
);
return $query;
}
return $results;
}

关于php - 如何使用 bindModel 和自定义查找器将 CakePHP 2 模型关联更改为深度链接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41412754/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com