Я пытаюсь повторить этот SQL результат запроса, который работает:Как изменить ассоциации моделей CakePHP 2 на глубокую связь с bindModel и пользовательским поиском?
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 Модели с
- bindModel изменить Модель ассоциации на лету
- заказ Найти поставить логику в модели
Нет основного поля из нижней таблицы за второй уровень. Сообщение об ошибке: «Модель« Ddbroute »не связана с моделью« Доставка ». Поэтому я попробовал его с и без доставки в массиве «содержать», и ни один из способов не привел в поля «Поставка». Я был бы рад использовать соединения, если это необходимо. Я прочитал самые актуальные сообщения в 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)
Хотя поставки hasOne Ddbrouteslot (и это будет hasMany - пересмотрено - теперь он остается как hasOne), для любого отдельного Ddbroute есть только одна связанная с доставкой, которая имеет каждый Ddbroutelot. Контейнер устанавливается во всех моделях. Я не знал, нужно ли сначала использовать 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;
}
В другом контроллере, чтобы запустить операцию поиска:
$this->LoadModel('Ddbroute');
$ddbstatuses = $this->Ddbroute->find('ddbstatuses');
$this->set(compact('ddbstatuses')); // to make available in a view
Я также была предпринята еще одна попытка с длинным массивом объединения, но запрос не привел к какой-либо информации о доставке, отслеживании или статусе, хотя запрос, похоже, запущен.
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;
}
У меня теперь есть решение, но запрос значительно медленнее с использованием моделей CakePHP, чем SQL-решение (2.) ниже. Поле «Delivery.laststatusid» может ссылаться на «Trackingstatus.id», тогда ограничение «порядок» не понадобится. Я пробовал это с помощью unbindModel и bindModel, пытаясь использовать hasOne и принадлежать ассоциациям. Поскольку Delivery.id, первичный ключ, не использовался, мой синтаксис включал '' foreignKey '=> false,' conditions '=> array (' 'Delivery'.'laststatusid' =' Trackingstatus'.'id' ') '. Я получил сообщение об ошибке, что laststatusid был неизвестным столбцом. ** Любые идеи о том, как быть быстрее? ** – netuser1