public static function load($parent, $childs, $keyField, array $ids, $foreignKey = null) { self::parseItemStatement($parent, $parentItemName, $parentFields); Lms_Item::initStructure(Lms_Item::getClassName($parentItemName)); $struct = Lms_Item::getStruct($parentItemName); if (count($parentFields)) { if ($foreignKey && !in_array($foreignKey, $parentFields)) { array_unshift($parentFields, $foreignKey); } foreach ($struct->getPk() as $fieldName) { if (!in_array($fieldName, $parentFields)) { array_unshift($parentFields, $fieldName); } } } if (!$foreignKey && $struct->hasIndex($keyField)) { $foreignKey = $keyField; } $newScalarPKs = self::_exec($parentItemName, $parentFields, $keyField, $ids, $foreignKey); foreach ($childs as $child) { self::parseItemStatement($child, $childItemName, $childFields); Lms_Item::initStructure(Lms_Item::getClassName($childItemName)); $relation = Lms_Item_Relations::get($parentItemName, $childItemName); if (!$relation) { $linkatorItemName = Lms_Item::getLinkator($parentItemName, $childItemName); $subRelation = Lms_Item_Relations::get($parentItemName, $linkatorItemName); $newKeys = array_unique(Lms_Item_Store::getAllFieldValues($newScalarPKs, Lms_Item::getTableName($parentItemName), $subRelation['parent_key'])); self::load($linkatorItemName, array($child), $subRelation['foreign_key'], $newKeys, $subRelation['foreign_key']); } else { if (count($childFields)) { if ($relation && !in_array($relation['foreign_key'], $childFields)) { array_unshift($childFields, $relation['foreign_key']); } $struct = Lms_Item::getStruct($childItemName); foreach ($struct->getPk() as $fieldName) { if (!in_array($fieldName, $childFields)) { array_unshift($childFields, $fieldName); } } } $newKeys = array_unique(Lms_Item_Store::getAllFieldValues($newScalarPKs, Lms_Item::getTableName($parentItemName), $relation['parent_key'])); self::_exec($childItemName, $childFields, $relation['foreign_key'], $newKeys, $relation['foreign_key']); } } }
/** * Возвращает элементы/аттрибуты указанные в пути xpath * * @param string $xpath * @return mixed */ public function getChilds($xpath) { if (!$xpath) { return $this; } //разбор запроса $xpaths = explode("/", $xpath, 2); $xpathCurrentStep = array_shift($xpaths); $xpathNextStep = count($xpaths) ? array_shift($xpaths) : null; $predicat = array(); if (preg_match('{^(.*?)\\[(.*?)\\]$}', $xpathCurrentStep, $matches)) { $xpathCurrentStep = $matches[1]; $predicat[] = $matches[2]; } //запрашивается поле if (0 === strpos($xpathCurrentStep, '@')) { $xpathCurrentStep = substr($xpathCurrentStep, 1); return call_user_func(array($this, "get{$xpathCurrentStep}")); } //запрашивается зависимый объект подразумевая использование линкатора $thisItemName = Lms_Item::getItemName($this); $relation = Lms_Item_Relations::get($thisItemName, $xpathCurrentStep); if (!$relation) { $linkator = Lms_Item::getLinkator($thisItemName, $xpathCurrentStep); return $this->getChilds("{$linkator}/{$xpath}"); } //запрашивается зависимый объект имеющий прямую связь $subTableName = Lms_Item::getTableName($xpathCurrentStep); $foreignKey = $relation['foreign_key']; $parentKeyValue = $this->__getValue($relation['parent_key']); Lms_Item::initStructure(Lms_Item::getClassName($xpathCurrentStep)); if (Lms_Item_Relations::ONE == $relation['type']) { //связь 1 к 1 if (Lms_Item::getSimplePk($xpathCurrentStep) == $foreignKey) { try { $item = Lms_Item::create($xpathCurrentStep, $parentKeyValue); return $item->getChilds($xpathNextStep); } catch (Lms_Item_RecordNotExistsException $e) { return null; } } else { $this->completeIndexValues($xpathCurrentStep, $foreignKey, $parentKeyValue); $subPkValues = Lms_Item_Store::getIndexedValues($subTableName, $foreignKey, $parentKeyValue); if (count($subPkValues)) { $subPkValue = reset($subPkValues); try { $item = Lms_Item::create($xpathCurrentStep, $subPkValue); return $item->getChilds($xpathNextStep); } catch (Lms_Item_RecordNotExistsException $e) { return null; } } } } else { //связь 1 ко многим $this->completeIndexValues($xpathCurrentStep, $foreignKey, $parentKeyValue); $result = array(); $subPkValues = Lms_Item_Store::getIndexedValues($subTableName, $foreignKey, $parentKeyValue); foreach ($subPkValues as $subPkValue) { $item = Lms_Item::create($xpathCurrentStep, $subPkValue); $result[] = $item->getChilds($xpathNextStep); } $this->performHandlers($result, $predicat); return $result; } }
public static function getLinkator() { $items = func_get_args(); if (count($items) == 1 && is_array($items[0])) { //входящие параметры переданы массивом $items = $items[0]; } $relations = array(); foreach ($items as $key => $item) { $itemName = self::getItemName($item); $items[$key] = $itemName; self::initStructure(self::getClassName($itemName)); $relations[] = array_keys(Lms_Item_Relations::getAll($itemName)); } //Находим место пересечения связей $intersection = call_user_func_array('array_intersect', $relations); if (count($intersection) == 0) { throw new Lms_Item_Exception("Relation between " . implode(', ', $items) . " not found"); } if (count($intersection) > 1) { throw new Lms_Item_Exception("Ambiguity relations between " . implode(', ', $items)); } //Получаем имя линкатора $linkatorName = reset($intersection); return $linkatorName; }