Оказывается, ты не можешь. По крайней мере, не с синтаксисом, представленным выше, и не с CakePHP 1.2.6. Я просмотрел исходный код (ууу! Открыть исходные фреймворки!) И нашел файл cake/libs/model/datasources/dbo_source.php
, содержащий код для соединений.
Все начинается с DboSource::renderStatement()
, который делает поверхностный обход массива $query['joins']
, заменяя эти определения объединений фрагментами SQL через DboSource::buildJoinStatement($join)
, что приводит в порядок аргументы (заполнение пробелов и т. Д.) затем вызывает DboSource::renderJoinStatement
, чтобы создать фрагмент SQL одного предложения объединения.
me: Это должно быть легко исправить!
Мне сказали не редактировать материал в cake/libs
, поэтому вместо этого я скопировал файл dbo_source.php
в app/models/datasources/
для редактирования. Затем я взял свой топор и реорганизовал мелкую прогулку массива $query['joins']
в DboSource::renderStatement()
в новый метод DboSource::buildJoinStatementArray()
, в результате чего появились два метода:
function buildStatement($query, $model) {
$query = array_merge(array('offset' => null, 'joins' => array()), $query);
# refactored (extract method) to make recursion easier
$query['joins'] = $this->buildJoinStatementArray($query['joins']);
return $this->renderStatement('select', array(
'conditions' => $this->conditions($query['conditions'], true, true, $model),
'fields' => implode(', ', $query['fields']),
'table' => $query['table'],
'alias' => $this->alias . $this->name($query['alias']),
'order' => $this->order($query['order']),
'limit' => $this->limit($query['limit'], $query['offset']),
'joins' => implode(' ', $query['joins']),
'group' => $this->group($query['group'])
));
}
/**
* Replaces the join statement array syntax with SQL join clauses.
*/
function buildJoinStatementArray($joins) {
if (!empty($joins)) {
$count = count($joins);
for ($i = 0; $i < $count; $i++) {
if (is_array($joins[$i])) {
$joins[$i] = $this->buildJoinStatement($joins[$i]); # $joins[$i] now contains something like "LEFT JOIN users As User on User.group_id = Group.id"
}
}
}
return $joins;
}
Как только у меня было DboSource::buildJoinStatementArray()
, пришло время изменить DboSource::buildJoinStatement()
- все, что я сделал, это добавил проверку на $data['joins']
и альтернативный метод рендеринга для этого случая:
function buildJoinStatement($join) {
$data = array_merge(array(
'type' => null,
'alias' => null,
'table' => 'join_table',
'conditions' => array()
), $join);
if (!empty($data['alias'])) {
$data['alias'] = $this->alias . $this->name($data['alias']);
}
if (!empty($data['conditions'])) {
$data['conditions'] = trim($this->conditions($data['conditions'], true, false));
}
# allow for nested joins
if (!empty($data['joins']) and is_array($data['joins'])) {
$data['joins'] = $this->buildJoinStatementArray($data['joins']);
return $this->renderNestedJoinStatement($data);
}
else
{
return $this->renderJoinStatement($data);
}
}
Новый метод renderNestedJoinStatement()
очень похож на DboSource::renderJoinStatement()
:
/**
* Renders a final SQL JOIN that contains nested join statements
*
* @param array $data
* @return string
*/
function renderNestedJoinStatement($data) {
extract($data);
$nestedJoins = implode(' ', $joins);
return trim("{$type} JOIN ({$table} {$alias} {$nestedJoins})ON ({$conditions})");
}