class = $entityProperty->class; $this->multiple = $entityProperty->multiple; $this->allowInline = $entityProperty->allowInline; $this->mode = $entityProperty->mode; $this->localKey = $entityProperty->localKey; $this->relatedKey = $entityProperty->relatedKey; $this->pivotTable = $entityProperty->pivotTable; $this->pivotLocalKey = $entityProperty->pivotLocalKey; $this->pivotRelatedKey = $entityProperty->pivotRelatedKey; $this->eagerLoad = $entityProperty->eagerLoad; // Initialize goal entity. $this->entity = new ($this->getClass())(); } /** * Create a new related entity. * @return Entity A new related entity instance. */ public function newEntity(): Entity { return $this->entity->new(); } /** * Determine if the property can be inline loaded. * @return bool True if the property can be inline loaded. */ public function canInlineLoad(): bool { return !$this->isMultiple() && $this->isInlineAllowed(); } /** * Build a query to retrieve relations for the given entities. * @param Entity[] $entities Entities for which to retrieve relations. * @return EntityQuery Built entities query. * @throws UnknownDatabaseException */ public function queryFor(array $entities): EntityQuery { // Initialize query. $query = $this->entity->query(); if (empty($entities)) // No entities, return a simple query without conditions. return $query; // Get a reference entity. $referenceEntity = array_first($entities); // Entity primary key. $entityPrimaryKey = array_first_or_val($referenceEntity->getPrimaryFields()); // Get keys from entities list. $entitiesKeys = array_column($entities, $entityPrimaryKey); switch ($this->getMode()) { // Build query depending on the relation mode. case EntityPropertyMode::LOCAL: $query ->select(new Raw("\"{$referenceEntity->getTableName()}\".\"$entityPrimaryKey\" AS \"__reference_key\"")) // Generate SELECT for the related entity. ->select(...$this->entity->sqlSelectFields()) ->innerJoin($referenceEntity->getTableName())->on( "{$this->entity->getTableName()}.".( $this->getRelatedKey() ?? array_first_or_val($this->entity->getPrimaryFields()) ), "=", "{$referenceEntity->getTableName()}.".( $this->getLocalKey() ?? str_snake_singularize($this->entity->getTableName())."_id" ), )->whereIn( "{$referenceEntity->getTableName()}.$entityPrimaryKey", $entitiesKeys ); break; case EntityPropertyMode::RELATED: $query ->select(new Raw("\"{$this->entity->getTableName()}\".\"".( $this->getRelatedKey() ?? str_snake_singularize($referenceEntity->getTableName())."_id" )."\" AS \"__reference_key\"")) // Generate SELECT for the related entity. ->select(...$this->entity->sqlSelectFields()) ->whereIn( "{$this->entity->getTableName()}.".( $this->getRelatedKey() ?? str_snake_singularize($referenceEntity->getTableName())."_id" )."", $entitiesKeys ); break; case EntityPropertyMode::PIVOT: $query ->select(new Raw("\"{$this->entity->getTableName()}\".\"".( $this->getPivotLocalKey() ?? str_snake_singularize($referenceEntity->getTableName())."_id" )."\" AS \"__reference_key\"")) // Generate SELECT for the related entity. ->select(...$this->entity->sqlSelectFields()) ->innerJoin($this->getPivotTable())->on( "{$query->getTableName()}.".( $this->getRelatedKey() ?? $query->getPrimaryKeyName() ), "=", "{$this->getPivotTable()}.".( $this->getPivotLocalKey() ?? str_snake_singularize($query->getTableName())."_id" ), ) ->whereIn( "{$this->getPivotTable()}.".( $this->getPivotLocalKey() ?? str_snake_singularize($referenceEntity->getTableName())."_id" ), $entitiesKeys ); break; } return $query; } /** * Setup inline loading for the current property in an entity query. * @param EntityQuery $query The entity query to alter. * @return void */ public function setupInlineLoading(EntityQuery $query): void { switch ($this->getMode()) { // Add join depending on the relation mode. case EntityPropertyMode::LOCAL: $query ->leftJoin($this->entity->getTableName())->on( "{$query->getTableName()}.".( $this->getLocalKey() ?? str_snake_singularize($this->entity->getTableName())."_id" ), "=", "{$this->entity->getTableName()}.".( $this->getRelatedKey() ?? array_first_or_val($this->entity->getPrimaryFields()) ), ); break; case EntityPropertyMode::RELATED: $query ->leftJoin($this->entity->getTableName())->on( "{$query->getTableName()}.".( $this->getLocalKey() ?? $query->getPrimaryKeyName() ), "=", "{$this->entity->getTableName()}.".( $this->getRelatedKey() ?? str_snake_singularize($query->getTableName())."_id" ), ); break; case EntityPropertyMode::PIVOT: $query ->leftJoin($this->getPivotTable())->on( "{$query->getTableName()}.".( $this->getLocalKey() ?? $query->getPrimaryKeyName() ), "=", "{$this->getPivotTable()}.".( $this->getPivotLocalKey() ?? str_snake_singularize($query->getTableName())."_id" ), ) ->leftJoin($this->entity->getTableName())->on( "{$this->getPivotTable()}.".( $this->getPivotRelatedKey() ?? str_snake_singularize($this->entity->getTableName())."_id" ), "=", "{$this->entity->getTableName()}.".( $this->getRelatedKey() ?? array_first_or_val($this->entity->getPrimaryFields()) ), ); break; } } }