/** * Выбирает связанную запись и подгружает ee в $this->joinedRelations. * Генерирует исключение, в случае если в модели не указан ключ связи для подгрузки связанной записи. * @param \Phalcon\Mvc\Model\Relation $relation * @return $this|void * @throws \PPA\Rest\Exception */ public function joinedRelation($relation) { $keyField = $relation->getOption(self::$referencesKeyOption); $relationAlias = $relation->getOption('alias'); $relationModel = @$this->{$relationAlias}; if (!$relationModel) { return; } switch ($relation->getType()) { case 0: // BelongsTo $this->joinedBelongsToRelation($relationModel, $relationAlias); break; case 2: // HasMany if (!$keyField) { return $this; /** throw new \PPA\Rest\Exception('If can use joinedRelation, you need to set ' . self::$referencesKeyOption . ' of relation ' . $relationAlias . ' in model ' . get_class($this)); **/ } $this->joinedHasManyRelation($relationModel, $relationAlias, $keyField); break; case 1: // HasManyToMany if (!$keyField) { return; } throw new \PPA\Rest\Exception('Sorry, relations with type HasManyToMany is not have implementations'); break; } return $this; }
/** * Standard method for processing relationships * build an intermediate list of related records * then normalize them for inclusion in the final response * * @param Relation|PhalconRelation $relation * @param array|Row $baseRecord * @throws HTTPException * @return mixed */ protected function processStandardRelationships($relation, $baseRecord) { // store parentModels for later use $parentModels = $this->model->getParentModels(true); // the intermediate set of related records $relatedRecords = []; // store a copy of all related record (PKIDs) // this must be attached w/ the parent records for joining purposes $relatedRecordIds = null; if ($parentModels and in_array($relation->getReferencedModel(), $parentModels)) { // skip any parent relationships because they are merged into the main record } else { $refType = $relation->getType(); $alias = $relation->getAlias(); // figure out if we have a preferred alias if (isset($alias)) { $refModelName = $alias; } else { $refModelName = $relation->getModelName(); } $config = $this->getDI()->get('config'); // harmonize relatedRecords switch ($refType) { case PhalconRelation::BELONGS_TO: // if fastBelongsTo is disabled, use the standard approach to loading belongsTo records if (!array_deep_key($config, 'feature_flags.fastBelongsTo')) { $relatedRecords = $this->getBelongsToRecord($relation); } else { // attempt a shortcut for some belongs to relationships // for simple belongsTo, pluck the related record out of base record since we know its in there // some belongsTo have parent records, revert to the older style to get a complete record if ($relation->getParent()) { $relatedRecords = $this->getBelongsToRecord($relation); } else { $relatedRecords = $this->loadRelationRecords([$baseRecord->{$refModelName}], $relation); } } break; case PhalconRelation::HAS_ONE: // ignore hasOne since they are processed like a parent relation // this means current logic will not merge in a parent's record for a hasOne relationship // it's an edge case but should be supported in the future break; case PhalconRelation::HAS_MANY_THROUGH: $relatedRecords = $this->getHasManyToManyRecords($relation); break; case PhalconRelation::HAS_MANY: if (!array_deep_key($config, 'feature_flags.fastHasMany')) { $relatedRecords = $this->getHasManyRecords($relation); } else { // register a future record request to be processed later $this->registerHasManyRequest($relation); } break; default: // wah! throw new HTTPException("Unknown relationship submitted!", 500, array('code' => '4984846846849494')); break; } // only normalize when some sort of resultset is returned, even an empty array if (isset($relatedRecords) && is_array($relatedRecords)) { return $this->normalizeRelatedRecords($baseRecord, $relatedRecords, $relation); } return true; } }