/** * @param string $recordId * @param string $associationName * @param ResourceFilter $filter * @return array The hasMany resources with one relationships and a link to their many relationships * @throws AssociationNotFoundException */ public function getHasMany($recordId, $associationName, $filter) { if (!$this->hasIdentifier()) { return null; } try { // Fetch the collection from the associated name $associatedCollection = $this->findCollectionFromAssociatedName($associationName); } catch (CollectionNotFoundException $exc) { throw new AssociationNotFoundException($associationName); } // Create instance of the model we want to query $model = App::make($this->getThisCollection()->getEntityClassName()); // Find the the entry recordId $model = $model->findOrFail($recordId); $relationships = []; // Fetch the relationships from the associated collection foreach ($associatedCollection->getRelationships() as $index => $relationship) { // Need the method's name instead of the table $relationships[] = $relationship->getField(); } // Retrieve the method name $associatedMethodName = ''; // foreach($this->getThisCollection()->getRelationships() as $index => $rel) { // var_dump($rel->getPivot()->getIntermediaryTableName()); // var_dump($rel->getField().' '.$associationName); // if ($rel->getField() == $associationName) { // $associatedMethodName = $index; // } // } // Query all the associated entry with their relationships' entry $resourceQueryBuilder = $model->{$associationName}()->with($relationships)->getQuery(); $thisTableName = null; try { $associatedTableName = $model->{$associationName}()->getTable(); $thisTableName = $model->{$associationName}()->getRelationName(); } catch (BadMethodCallException $e) { $thisTableName = null; } // add the filters to the query $this->filterQueryBuilder($filter, $this->getThisCollection(), $resourceQueryBuilder, $thisTableName); // Count number of associated entry $countQueryBuilder = clone $resourceQueryBuilder; $countQueryBuilder->getQuery()->orders = null; $totalNumberOfRows = $countQueryBuilder->count(); // Paginate the result $this->paginateQueryBuilder($resourceQueryBuilder, $filter); // Generate resources from the query $returnedResources = $this->loadResourcesFromQueryBuilder($resourceQueryBuilder, $associatedCollection); return ForestResource::formatResourcesJsonApi($returnedResources, $totalNumberOfRows); }
/** * @param string $recordId * @param string $associationName * @param ResourceFilter $filter * @return object[] The hasMany resources with one relationships and a link to their many relationships * @throws AssociationNotFoundException * @throws CollectionNotFoundException * @throws RelationshipNotFoundException */ public function getHasMany($recordId, $associationName, $filter) { if (!$this->hasIdentifier()) { return null; } try { $associatedCollection = $this->findCollection($associationName); } catch (CollectionNotFoundException $exc) { throw new AssociationNotFoundException($associationName); } $thisAlias = 'resource'; $associationAlias = 'assoc'; $thisIdentifier = $this->getThisCollection()->getIdentifier(); $associationIdentifier = $associatedCollection->getIdentifier(); /** * This part contains an awful but necessary workaround to associate this collection and associated collection * because ManyToMany relationships are not necessarily defined on both sides. * @link http://stackoverflow.com/questions/5432404/doctrine-2-dql-how-to-select-inverse-side-of-unidirectional-many-to-many-query/15444719#15444719 */ $associationFieldName = $this->getThisCollection()->getRelationship($associationName)->getField(); $resourceQueryBuilder = $this->getRepository()->createQueryBuilder($thisAlias); $resourceQueryBuilder->join($associatedCollection->getEntityClassName(), $associationAlias, Expr\Join::WITH, '1 = 1')->join($thisAlias . '.' . $associationFieldName, 'assoc2')->where($thisAlias . '.' . $thisIdentifier . ' = :id')->setParameter('id', $recordId)->andWhere('assoc2.' . $associationIdentifier . ' = ' . $associationAlias . '.' . $associationIdentifier); $this->filterQueryBuilder($resourceQueryBuilder, $filter, $this->getThisCollection(), $associationAlias); $countQueryBuilder = clone $resourceQueryBuilder; $totalNumberOfRows = $countQueryBuilder->select($countQueryBuilder->expr()->count($associationAlias . '.' . $associationIdentifier))->getQuery()->getSingleScalarResult(); $this->paginateQueryBuilder($resourceQueryBuilder, $filter); $resourceQueryBuilder->select($associationAlias); $returnedResources = $this->loadResourcesFromQueryBuilder($resourceQueryBuilder, $associatedCollection); return Resource::formatResourcesJsonApi($returnedResources, $totalNumberOfRows); }