Пример #1
0
 /**
  * Get the relation instance for the given relation name.
  *
  * @param  string $relation
  *
  * @return Relation
  * @throws BadRequestException
  */
 public function getRelation($relation)
 {
     $query = Relation::noConstraints(function () use($relation) {
         /** @var BaseModel $model */
         $model = $this->getModel();
         $relationType = $model->getReferencingType($relation);
         if (RelationSchema::HAS_MANY === $relationType) {
             return $model->getHasManyByRelationName($relation);
         } elseif (RelationSchema::MANY_MANY === $relationType) {
             return $model->getBelongsToManyByRelationName($relation);
         } elseif (RelationSchema::BELONGS_TO === $relationType) {
             return $model->getBelongsToByRelationName($relation);
         }
         return null;
     });
     if (!empty($query)) {
         return $query;
     }
     if (!method_exists($this->getModel(), $relation)) {
         throw new BadRequestException('Unknown relationship: ' . $relation);
     }
     return parent::getRelation($relation);
 }
Пример #2
0
 /**
  * Get the "has relation" base query instance.
  *
  * @param  string  $relation
  * @return \Illuminate\Database\Eloquent\Builder
  */
 protected function getHasRelationQuery($relation)
 {
     $me = $this;
     return Relation::noConstraints(function () use($me, $relation) {
         return $me->getModel()->{$relation}();
     });
 }
Пример #3
0
 /**
  * Makes the form object used for rendering a simple field type
  */
 protected function makeRenderFormField()
 {
     return $this->renderFormField = RelationBase::noConstraints(function () {
         $field = clone $this->formField;
         list($model, $attribute) = $this->getModelArrayAttribute($this->relationName);
         $relatedObj = $model->makeRelation($attribute);
         $query = $model->{$attribute}()->newQuery();
         if (in_array($this->relationType, ['belongsToMany', 'morphToMany', 'morphedByMany', 'hasMany'])) {
             $field->type = 'checkboxlist';
         } elseif (in_array($this->relationType, ['belongsTo', 'hasOne'])) {
             $field->type = 'dropdown';
             $field->placeholder = $this->emptyOption;
         }
         // It is safe to assume that if the model and related model are of
         // the exact same class, then it cannot be related to itself
         if ($model->exists && get_class($model) == get_class($relatedObj)) {
             $query->where($relatedObj->getKeyName(), '<>', $model->getKey());
         }
         // Even though "no constraints" is applied, belongsToMany constrains the query
         // by joining its pivot table. Remove all joins from the query.
         $query->getQuery()->getQuery()->joins = [];
         $treeTraits = ['October\\Rain\\Database\\Traits\\NestedTree', 'October\\Rain\\Database\\Traits\\SimpleTree'];
         if (count(array_intersect($treeTraits, class_uses($relatedObj))) > 0) {
             $field->options = $query->listsNested($this->nameFrom, $relatedObj->getKeyName());
         } else {
             $field->options = $query->lists($this->nameFrom, $relatedObj->getKeyName());
         }
         return $field;
     });
 }
Пример #4
0
 /**
  * Add a join clause to the query automatically using the informations of the relation
  * @param  string  $relations
  * @param  string  $type
  * @param  string  $operator
  * @param  boolean $where
  * @return \Illuminate\Database\Query\Builder|static
  */
 public function scopeJoinRelation($query, $relations, $type = 'inner', $operator = '=', $where = false)
 {
     $me = $this;
     $relations = (array) $relations;
     $joined = array();
     $joinRelation = function ($model, $names, $constraints) use($query, &$joinRelation, &$joined, $type, $operator, $where) {
         $name = array_shift($names);
         $relation = \Illuminate\Database\Eloquent\Relations\Relation::noConstraints(function () use($model, $name) {
             return $model->{$name}();
         });
         $related = $relation->getRelated();
         if (!in_array($name, $joined)) {
             $joined[] = $name;
             if (is_a($relation, '\\Illuminate\\Database\\Eloquent\\Relations\\HasOneOrMany')) {
                 $one = $relation->getQualifiedParentKeyName();
                 $two = $relation->getForeignKey();
             }
             if (is_a($relation, '\\Illuminate\\Database\\Eloquent\\Relations\\BelongsTo')) {
                 $one = $relation->getQualifiedForeignKey();
                 $two = $relation->getQualifiedOtherKeyName();
             }
             if (is_a($relation, '\\Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany')) {
                 $query->join($relation->getTable(), $relation->getForeignKey(), '=', $relation->getParent()->getQualifiedKeyName());
                 $one = $relation->getRelated()->getQualifiedKeyName();
                 $two = $relation->getOtherKey();
             }
             $query->join($related->getTable(), $one, $operator, $two, $type, $where);
             $relationQuery = $relation->getBaseQuery();
             call_user_func($constraints, $query);
             $query->getQuery()->mergeWheres($relationQuery->wheres, $relationQuery->getBindings());
         }
         if ($names) {
             $joinRelation($related, $names, $constraints);
         }
     };
     foreach ($relations as $name => $constraints) {
         if (is_numeric($name)) {
             list($name, $constraints) = array($constraints, function () {
             });
         }
         $joinRelation($me, explode('.', $name), $constraints);
     }
     return $query;
 }
Пример #5
0
 public function getRelationRecordCount($relation, $relation_count, $use_main_table = true)
 {
     $this->with($relation);
     // substitutes the model with a Builder instance
     $model = $this->model;
     $query = Relation::noConstraints(function () use($model, $relation, $relation_count) {
         return $model->getRelation($relation_count)->groupBy($this->relations[$relation]['table'] . '.' . $this->relations[$relation]['foreignKey'])->orderBy($this->relations[$relation]['count'], 'desc');
     });
     if ($model instanceof Builder) {
         $model = $model->getModel();
     }
     $table = $query->getQuery()->getModel()->getTable();
     $query->setModel($this->model->getModel());
     $query->getQuery()->getQuery()->from($table);
     if ($use_main_table) {
         $query->select(['main.*']);
     }
     foreach ($this->relations[$relation]['fields'] as $field => $name) {
         $query->selectRaw($field . ' as ' . $name);
     }
     if ($use_main_table) {
         $query->join($model->getTable() . ' as main', 'main.id', '=', $this->relations[$relation]['table'] . '.' . $this->relations[$relation]['foreignKey']);
     }
     // It is necessary to return the previous state of the model after
     // using "$this->with()", which substitutes the model with a Builder
     // instance.
     $this->resetModel();
     return $query;
 }
Пример #6
0
 /**
  * Get the relation instance for the given relation name.
  *
  * @param  string  $relation
  * @return \Illuminate\Database\Eloquent\Relations\Relation
  */
 public function getRelation($relation)
 {
     $me = $this;
     // We want to run a relationship query without any constrains so that we will
     // not have to remove these where clauses manually which gets really hacky
     // and is error prone while we remove the developer's own where clauses.
     $query = Relation::noConstraints(function () use($me, $relation) {
         return $me->getModel()->{$relation}();
     });
     $nested = $this->nestedRelations($relation);
     // If there are nested relationships set on the query, we will put those onto
     // the query instances so that they can be handled after this relationship
     // is loaded. In this way they will all trickle down as they are loaded.
     if (count($nested) > 0) {
         $query->getQuery()->with($nested);
     }
     return $query;
 }
Пример #7
0
 public function getRelationRecordCount($relation, $relation_count, $use_main_table = true)
 {
     $this->with($relation);
     $model = $this->model;
     $query = Relation::noConstraints(function () use($model, $relation, $relation_count) {
         return $model->getRelation($relation_count)->groupBy($this->relations[$relation]['table'] . '.' . $this->relations[$relation]['foreignKey'])->orderBy($this->relations[$relation]['count'], 'desc');
     });
     if ($model instanceof Builder) {
         $model = $model->getModel();
     }
     $table = $query->getQuery()->getModel()->getTable();
     $query->setModel($this->model->getModel());
     $query->getQuery()->getQuery()->from($table);
     if ($use_main_table) {
         $query->select(['main.*']);
     }
     foreach ($this->relations[$relation]['fields'] as $field => $name) {
         $query->selectRaw($field . ' as ' . $name);
     }
     if ($use_main_table) {
         $query->join($model->getTable() . ' as main', 'main.id', '=', $this->relations[$relation]['table'] . '.' . $this->relations[$relation]['foreignKey']);
     }
     return $query;
 }
Пример #8
0
 /**
  * Makes the form object used for rendering a simple field type
  */
 protected function makeRenderFormField()
 {
     return $this->renderFormField = RelationBase::noConstraints(function () {
         $field = clone $this->formField;
         $relationObject = $this->getRelationObject();
         $query = $relationObject->newQuery();
         list($model, $attribute) = $this->resolveModelAttribute($this->valueFrom);
         $relationType = $model->getRelationType($attribute);
         $relationModel = $model->makeRelation($attribute);
         if (in_array($relationType, ['belongsToMany', 'morphToMany', 'morphedByMany', 'hasMany'])) {
             $field->type = 'checkboxlist';
         } elseif (in_array($relationType, ['belongsTo', 'hasOne'])) {
             $field->type = 'dropdown';
         }
         $field->placeholder = $this->emptyOption;
         // It is safe to assume that if the model and related model are of
         // the exact same class, then it cannot be related to itself
         if ($model->exists && get_class($model) == get_class($relationModel)) {
             $query->where($relationModel->getKeyName(), '<>', $model->getKey());
         }
         // Even though "no constraints" is applied, belongsToMany constrains the query
         // by joining its pivot table. Remove all joins from the query.
         $query->getQuery()->getQuery()->joins = [];
         // Determine if the model uses a tree trait
         $treeTraits = ['October\\Rain\\Database\\Traits\\NestedTree', 'October\\Rain\\Database\\Traits\\SimpleTree'];
         $usesTree = count(array_intersect($treeTraits, class_uses($relationModel))) > 0;
         // The "sqlSelect" config takes precedence over "nameFrom".
         // A virtual column called "selection" will contain the result.
         // Tree models must select all columns to return parent columns, etc.
         if ($this->sqlSelect) {
             $nameFrom = 'selection';
             $selectColumn = $usesTree ? '*' : $relationModel->getKeyName();
             $result = $query->select($selectColumn, Db::raw($this->sqlSelect . ' AS ' . $nameFrom));
         } else {
             $nameFrom = $this->nameFrom;
             $result = $query->getQuery()->get();
         }
         $field->options = $usesTree ? $result->listsNested($nameFrom, $relationModel->getKeyName()) : $result->lists($nameFrom, $relationModel->getKeyName());
         return $field;
     });
 }