/** Process all search query joins * * @param \Phalcon\Mvc\Model\Relation $relation * @param array $joinPath * @return array|bool */ protected function _processJoins(Relation $relation, array $joinPath) { $refModel = $relation->getReferencedModel(); $refModel = new $refModel(); $refFields = $relation->getReferencedFields(); $options = $relation->getOptions(); $dataSourceIn = $refModel->queryBuilder(); $dataSourceIn->setColumn($refFields); $relation = array_shift($joinPath); if ($joinPath) { if (!($ids = $this->_processJoins($relation, $joinPath))) { return false; } $fields = $relation->getFields(); $where = "(" . $fields . " IN (" . implode($ids, ",") . "))"; } else { //$dataSourceIn->joinPath($joinPath); $where = $this->_filter->filterWhere($dataSourceIn); } $dataSourceIn->andWhere($where); //$dataSourceIn->columnsId(); $result = $dataSourceIn->getQuery()->execute()->toArray(); if (count($result) == 0) { return false; } $ids = []; $adapter = $dataSourceIn->getModel()->getReadConnection(); foreach ($result as $row) { $ids[] = $adapter->escapeString($row[$refFields]); } return $ids; }
/** * ez access to the "foreign" model depicted by the relationship */ private function getModel() { if ($this->model == null) { $name = $this->relation->getReferencedModel(); $this->model = new $name(); } return $this->model; }
/** * @param array $relationsArray * @param \Phalcon\Mvc\Model $model * @param \Phalcon\Mvc\Model\Relation $relation */ public function save(array $relationsArray, $model, $relation) { $relationAlias = $relation->getOption('alias'); $needDeleteRelations = $this->getNeedDelete($relationsArray, $model, $relation); $this->delete($needDeleteRelations); foreach ($relationsArray as $relationData) { $relationData = Params::convertDate($relationData, $this->getDI()); if (empty($relationData['id'])) { $this->create($relationData, $model, $relationAlias); } else { $this->update($relationData, $model, $relationAlias); } } }
/** * @param \Phalcon\Mvc\Model $model * @param \Phalcon\Mvc\Model\Relation $relation * @param bool $isConvertToArray * @return array|Model\Resultset|\Phalcon\Mvc\Model|void */ private function getAssignRelation(Model $model, Relation $relation, $isConvertToArray = true) { $alias = $relation->getOption('alias'); if (!$alias) { return; } $data = $model->{$alias}; return $data && $isConvertToArray ? $data->toArray() : $data; }
/** * get the name of the parent model (w/o namespace) * * @return string or false */ public function getParent() { $name = $this->relation->getReferencedModel(); return $name::$parentModel; }
/** * load the query object for a hasManyToMany relationship * build most of the joins manually since by reference relationship in the model isn't working so well * this support joins to distant tables with parent models * * @param Relation|PhalconRelation $relation * @return array */ protected function getHasManyToManyRecords($relation) { $refModelNameSpace = $relation->getReferencedModel(); $intermediateModelNameSpace = $relation->getIntermediateModel(); // determine the key to search against $field = $relation->getFields(); $referencedField = $relation->getReferencedFields(); $intermediateFields = $relation->getIntermediateReferencedFields(); $config = $this->getDI()->get('config'); $modelNameSpace = $config['namespaces']['models']; $mm = $this->getDI()->get('modelsManager'); /** @var Builder $query */ $query = $mm->createBuilder()->from($intermediateModelNameSpace)->join($refModelNameSpace, $refModelNameSpace . ".{$referencedField} = " . $intermediateModelNameSpace . ".{$intermediateFields}"); $columns = array(); // join in parent record if one is detected $parentName = $relation->getParent(); if ($parentName) { // load parent model /** @var BaseModel $parentModel */ $parentModelNameSpace = $modelNameSpace . $parentName; $parentModel = new $refModelNameSpace(); // load reference relationship $parentRelationship = $parentModel->getRelation($parentName); $columns[] = "{$parentModelNameSpace}.*"; $query->join($parentModelNameSpace, "{$parentModelNameSpace}." . $parentRelationship->getReferencedFields() . " = {$refModelNameSpace}." . $parentRelationship->getFields(), $parentModelNameSpace); } // Load the main record field at the end, so they are not overwritten $columns[] = $refModelNameSpace . ".*, " . $intermediateModelNameSpace . ".*"; $query->columns($columns); if (isset($this->baseRecord[$field])) { $fieldValue = $this->baseRecord[$field]; } else { // fall back to using the primaryKeyValue $fieldValue = $this->primaryKeyValue; } $whereField = $intermediateModelNameSpace . '.' . $relation->getIntermediateFields(); $query->where("{$whereField} = \"{$fieldValue}\""); $result = $query->getQuery()->execute(); return $this->loadRelationRecords($result, $relation); }
protected final function hasMany(NgModelBase $model, ModelRelation $relation) { // check options for alias $opts = $relation->getOptions(); if (!isset($opts["alias"])) { return; } // build needed variable(s) $references = $relation->getReferencedFields(); $modelRelation = $relation->getReferencedModel(); $query = new Query(); $query->addCondition(new SimpleCondition($references, Operator::OP_EQUALS, $model->getId())); // fetch resultset try { $handler = new Crud(); /** @type Resultset $resultSet */ $resultSet = $handler->read(new $modelRelation(), $query, false); unset($handler); } catch (CrudException $e) { throw new Exception($e->getMessage()); } // check and prepare data.links if (!isset($this->data["links"][$references])) { $this->data["links"][$references] = array(); } // check and prepare linked if (!isset($this->linked[$references])) { $this->linked[$references] = array(); } foreach ($resultSet as $ngModel) { /** @type NgModelBase $ngModel */ // check if this model already populated if (in_array($ngModel->getId(), $this->hasManyIds)) { continue; } // check if this model already in our data.links if (in_array($ngModel->getId(), $this->data["links"][$references])) { continue; } // put relation id on data.links $this->data["links"][$references][] = (int) $ngModel->getId(); // envelope model into relation data $relationData = $this->envelope->envelope($ngModel); // check if relationData already in our linked if (in_array($relationData, $this->linked[$references])) { continue; } // put relation data on our linked $this->linked[$references][] = $relationData; } }
/** * Setups a relation n-m between two models * * @param \Phalcon\Mvc\ModelInterface $model * @param string|array $fields * @param string $intermediateModel * @param string|array $intermediateFields * @param string|array $intermediateReferencedFields * @param string $referencedModel * @param string|array $referencedFields * @param array|null $options * @return \Phalcon\Mvc\Model\Relation * @throws Exception */ public function addHasManyToMany($model, $fields, $intermediateModel, $intermediateFields, $intermediateReferencedFields, $referencedModel, $referencedFields, $options = null) { if (is_object($model) === false || $model instanceof ModelInterface === false || is_string($intermediateModel) === false || is_string($referencedModel) === false || is_array($options) === false && is_null($options) === false) { throw new Exception('Invalid parameter type.'); } $entityName = strtolower(get_class($model)); $intermediateEntity = strtolower($intermediateModel); $referencedEntity = strtolower($referencedModel); $keyRelation = $entityName . '$' . $referencedEntity; if (isset($this->_hasManyToMany[$keyRelation]) === false) { $relations = array(); } else { $relations = $this->_hasManyToMany[$keyRelation]; } //Check if the number of fields is the same from the model to the intermediate model if (is_array($intermediateFields) === true && count($fields) !== count($intermediateFields)) { throw new Exception('Number of referenced fields are not the same'); //@note sic! } //@note this check is doing the same as the check before: //Check if the number of fields is the same from the intermediate model to the //referenced model //Create a relationship instance $relation = new Relation(4, $referencedModel, $fields, $referencedFields, $options); //Set extended intermediate relation data $relation->setIntermediateRelation($intermediateFields, $intermediateModel, $intermediateFields); if (isset($options['alias']) === true) { $lowerAlias = strtolower($options['alias']); } else { $lowerAlias = $referencedEntity; } //Append a new relationship $relations[] = $relation; //Update the global alias $this->_aliases[$entityName . '$' . $lowerAlias] = $relation; //Update the relations $this->_hasManyToMany[$keyRelation] = $relations; //Get existing relations by model if (isset($this->_hasManyToManySingle[$entityName]) === false) { $singleRelations = array(); } else { $singleRelations = $this->_hasManyToManySingle[$entityName]; } //Append a new relationship $singleRelations[] = $relation; //Update relations by model $this->_hasManyToManySingle[$entityName] = $singleRelations; return $relation; }