Рекурсивно найти вложенные активные записи отношений в Yii
Предположим, у вас есть отношение, подобное следующему, и вы хотите найти все учетные записи, которые принадлежат данному клиенту:
- Customer 1
- accounts
- Account 1
- customers
- Customer 2
- accounts
- Account 2
- Account 3
- Customer 3
- customers
- Customer 4
- accounts
- Account 4
- Account 5
(Для Клиента 1 это счета 1, 2, 3, 4 и 5; для Клиента 3 это счета 4 и 5; и т. Д.)
Как бы Вы это сделали?
Это встречалось несколько раз в моих проектах, и мне любопытно, как другие решили это.
Вот суть моего решения (комментарии кода в ссылке):
<?php
public function getNestedRelated($nested, $from, $nestedCriteria = array(), $fromCriteria = array(), $maxLevels = false, $includeFirst = true, $_currentLevel = 0, &$_recursedSoFar = array())
{
// Always return an array (for array_merge)
$related = array();
// Prevent infinite recursion
if (in_array($this->primaryKey, $_recursedSoFar)) {
return $related;
}
$_recursedSoFar[] = $this->primaryKey;
// Nested records at this level
if ($_currentLevel > 0 || $includeFirst) {
// Whether to refresh nested records at this level. If criteria are
// provided, the db is queried anyway.
$refreshNested = false;
$related = $this->getRelated($nested, $refreshNested, $nestedCriteria);
}
// Handle singular ("HAS_ONE", "BELONGS_TO") relations
if (!is_array($related)) {
$related = array($related);
}
// Don't recurse past the max # of levels
if ($maxLevels !== false && $_currentLevel > $maxLevels) {
return $related;
}
// Whether to refresh children of this record. If criteria are provided,
// the db is queried anyway.
$refreshFrom = false;
// Go down one more level
$_currentLevel++;
foreach ($this->getRelated($from, $refreshFrom, $fromCriteria) as $child) {
// Recursive step
$nestedRelated = $child->getNestedRelated($nested, $from, $nestedCriteria, $fromCriteria, $maxLevels, $includeFirst, $_currentLevel, $_recursedSoFar);
$related = array_merge($related, $nestedRelated);
}
return $related;
}
1 ответ
Задумывались ли вы об использовании предварительного заказа, чтобы получить все детали за один раз? Если это возможно, держите как учетные записи, так и клиентов в 1 таблице, тогда 1 запрос с предварительным заказом фактически получит все, что вам нужно.
Если вы храните клиентов и учетные записи в двух разных таблицах, я полагаю, что вы все равно можете использовать предварительный заказ, чтобы минимизировать количество запросов, которые вы делаете.
Я использую в Yii это расширение, тоже держу вещи в предзаказе, это довольно приятно http://www.yiiframework.com/extension/nestedsetbehavior/