Add subselect queries to count the relations.

@param  mixed $relations
@return $this
5672
public function withCount( $relations )
	{
		if ( is_null( $this->query->columns ) )
		{
			$this->query->select( ['*'] );
		}

		$relations = is_array( $relations ) ? $relations : func_get_args();

		foreach ( $this->parseWithRelations( $relations ) as $name => $constraints )
		{
			// Here we will get the relationship count query and prepare to add it to the main query
			// as a sub-select. First, we'll get the "has" query and use that to get the relation
			// count query. We will normalize the relation name then append _count as the name.
			$relation = $this->getHasRelationQuery( $name );

			$query = $relation->getRelationCountQuery( $relation->getRelated()->newQuery(), $this );

			$query->callScope( $constraints );

			$query->mergeModelDefinedRelationConstraints( $relation->getQuery() );

			$this->selectSub( $query->toBase(), snake_case( $name ) . '_count' );
		}

		return $this;
	}
525766
public function on($relation): Statement
    {
        if (count($this->ons) >= count($this->joins)) {
            trigger_error('关联时,关联关系过多', E_USER_ERROR);
        }
        $this->ons[] = $relation;
        return $this;
    }
683554
function with(array $relations, array $where = null, $order = null, $limit = 0, $offset = 0) {
		$qthis = $this->conn->quoteName($this->getName());
		$query = $this->getQueryWriter()->reset();
		$query->write("SELECT", "$qthis.*", "FROM", $qthis);
		foreach ($relations as $relation) {
			if (!($relation instanceof Table\Reference)) {
				$relation = static::resolve($relation)->getRelation($this->getName());
			}
			if ($this->getName() === $relation->foreignTable) {
				$query->write("JOIN", $relation->referencedTable)->write("ON");
				foreach ($relation as $key => $ref) {
					$query->criteria(
						array(
							"{$relation->referencedTable}.{$ref}=" => 
								new QueryExpr("{$relation->foreignTable}.{$key}")
						)
					);
				}
			} else {
				$query->write("JOIN", $relation->foreignTable)->write("ON");
				foreach ($relation as $key => $ref) {
					$query->criteria(
						array(
							"{$relation->referencedTable}.{$ref}=" => 
								new QueryExpr("{$relation->foreignTable}.{$key}")
						)
					);
				}
			}
		}
		if ($where) {
			$query->write("WHERE")->criteria($where);
		}
		if ($order) {
			$query->write("ORDER BY", $order);
		}
		if ($limit) {
			$query->write("LIMIT", $limit);
		}
		if ($offset) {
			$query->write("OFFSET", $offset);
		}
		return $this->execute($query);
	}
964095
public function addRelation(Relation $relation)
    {
        switch (get_class($relation)) {
            case BelongsTo::class:
                $this->relations['belongsTo'][] = $relation;
                break;

            case BelongsToMany::class:
                $this->relations['belongsToMany'][] = $relation;
                break;

            case HasOne::class:
                $this->relations['hasOne'][] = $relation;
                break;

            case HasMany::class:
                $this->relations['hasMany'][] = $relation;
                break;

            case HasManyThrough::class:
                $this->relations['hasManyThrough'][] = $relation;
                break;

            default:
                throw new \Exception("Unknown relation type " . get_class($relation));
        }
    }
1326946
protected function associateRelationModels(string $relationName, EloquentCollection $relationModels): self
    {
        $relation = $this->getRelationInstance($relationName);

        $relation->match(
            $this->models->all(),
            $relationModels,
            $relationName
        );

        return $this;
    }
340894
public static function with($relations)
    {
        if (is_string($relations)) $relations = func_get_args();

        $instance = new static;

        return $instance->newQuery()->with($relations);
    }
160794
public function initRelation(array $models, $relation)
    {
        foreach ($models as $model) {
            $model->setRelation($relation, $this->getDefaultFor($model));
        }

        return $models;
    }
1008598
public function addRelationSelectColumns($relation)
    {
        $join = $this->joins[$relation];
        call_user_func(array($join->getTableMap()->getPeerClassname(), 'addSelectColumns'), $this, $join->getRelationAlias());

        return $this;
    }
1101202
public function load($relations)
    {
        if (count($this->items) > 0) {
            if (is_string($relations)) {
                $relations = func_get_args();
            }

            $query = $this->first()->newQuery()->with($relations);

            $this->items = $query->eagerLoadRelations($this->items);
        }

        return $this;
    }
800304
protected function hasOneOrManyDeepFromRelations(array $relations)
    {
        if (is_array($relations[0])) {
            $relations = $relations[0];
        }

        $related = null;
        $through = [];
        $foreignKeys = [];
        $localKeys = [];

        foreach ($relations as $i => $relation) {
            $method = $this->hasOneOrManyDeepRelationMethod($relation);

            [$through, $foreignKeys, $localKeys] = $this->$method($relation, $through, $foreignKeys, $localKeys);

            if ($i === count($relations) - 1) {
                $related = get_class($relation->getRelated());
            } else {
                $through[] = get_class($relation->getRelated());
            }
        }

        return [$related, $through, $foreignKeys, $localKeys];
    }
876074
protected function addManyRelation(string $relation)
    {
        if (!in_array($relation, $this->manyRelations)) {
            $this->manyRelations[] = $relation;
        }
    }
1308048
public function load($relations = [])
	{
		$this->addRelations($relations);
		
		$this->clearQueue();

		$this->queueUnresolvedObjects($this->data, $this->relations);

		$this->loadQueue();
	}
684938
public function loadMissing($relations)
    {
        $relations = is_string($relations) ? func_get_args() : $relations;

        $this->newCollection([$this])->loadMissing($relations);

        return $this;
    }
421952
public function addRelation(Relation $relation) {
        $relation->setPrimaryModel($this);

        $this->_relations[$relation->getAlias()] = $relation;
        $this->_aliases[$relation->getRelatedClass()] = $relation->getAlias();
        $this->reserved[] = $relation->getAlias();

        $this->on('relation', $relation);

        return $this;
    }
708266
public function countWhereHas($relation, array $where = [], array $whereHas = [])
    {
        $query = $this->make();

        $query = $this->applyWhere($query, $where);

        $query = $query->whereHas($relation, function ($q) use ($whereHas) {
            $this->applyWhere($q, $whereHas);
        });

        return $query->count();
    }
325518
public function createWith(array $attributes, array $relations) {
        // Collect the model attributes and label in the form of ['label' => $label, 'attributes' => $attributes]
        // as expected by the Query Builder.
        $attributes = $this->prepareForCreation($this->model, $attributes);
        $model = ['label' => $this->model->getTable(), 'attributes' => $attributes];

        /**
         * Collect the related models in the following for as expected by the Query Builder:
         *
         *  [
         *       'label' => ['Permission'],
         *       'relation' => [
         *           'name' => 'photos',
         *           'type' => 'PHOTO',
         *           'direction' => 'out',
         *       ],
         *       'values' => [
         *           // A mix of models and attributes, doesn't matter really..
         *           ['url' => '', 'caption' => ''],
         *           ['url' => '', 'caption' => '']
         *       ]
         *  ]
         */
        $related = [];
        foreach ($relations as $relation => $values) {
            $name = $relation;
            // Get the relation by calling the model's relationship function.
            if (!method_exists($this->model, $relation))
                throw new QueryException("The relation method $relation() does not exist on " . get_class($this->model));

            $relationship = $this->model->$relation();
            // Bring the model from the relationship.
            $relatedModel = $relationship->getRelated();

            // We will first check to see what the dev have passed as values
            // so that we make sure that we have an array moving forward
            // In the case of a model Id or an associative array or a Model instance it means that
            // this is probably a One-To-One relationship or the dev decided not to add
            // multiple records as relations so we'll wrap it up in an array.
            if (!is_array($values) || Helpers::isAssocArray($values) || $values instanceof Model)
                $values = [$values];

            $label = $relationship->getRelated()->getTable();
            $direction = $relationship->getEdgeDirection();
            $type = $relationship->getRelationType();

            // Hold the models that we need to attach
            $attach = [];
            // Hold the models that we need to create
            $create = [];
            // Separate the models that needs to be attached from the ones that needs
            // to be created.
            foreach ($values as $value) {
                // If this is a Model then the $exists property will indicate what we need
                // so we'll add its id to be attached.
                if ($value instanceof Model and $value->exists === true) {
                    $attach[] = $value->getKey();
                }
                // Next we will check whether we got a Collection in so that we deal with it
                // accordingly, which guarantees sending an Eloquent result straight in would work.
                elseif ($value instanceof Collection) {
                    $attach = array_merge($attach, $value->lists('id'));
                }
                // Or in the case where the attributes are neither an array nor a model instance
                // then this is assumed to be the model Id that the dev means to attach and since
                // Orientdb node Ids are always an int then we take that as a value.
                elseif (!is_array($value) && !$value instanceof Model) {
                    $attach[] = intval($value);
                }
                // In this case the record is considered to be new to the market so let's create it.
                else
                    $create[] = $this->prepareForCreation($relatedModel, $value);
            }

            $relation = compact('name', 'type', 'direction');
            $related[] = compact('relation', 'label', 'create', 'attach');
        }

        $result = $this->query->createWith($model, $related);

        $models = $this->resultsToModels($this->model->getConnectionName(), $result);
        return (!empty($models)) ? reset($models) : null;
    }
1080589
public function setRelation($relation, $relationColumn = null)
    {
        $this->relation = $relation;
        $this->relationColumn = $relationColumn;

        return $this;
    }