Skip to content

Commit

Permalink
feature #53365 [DoctrineBridge] Allow EntityValueResolver to return…
Browse files Browse the repository at this point in the history
… a list of entities (HypeMC)

This PR was merged into the 7.1 branch.

Discussion
----------

[DoctrineBridge] Allow `EntityValueResolver` to return a list of entities

| Q             | A
| ------------- | ---
| Branch?       | 7.1
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Issues        | Fix #53236 (sort of)
| License       | MIT

Makes the following possible:
```php
#[Route('/{author_id}', name: 'app_test')]
public function index(
    #[MapEntity(class: Post::class, expr: 'repository.findBy({"author": author_id}, {}, 10)')]
    iterable $posts
): Response {
// ...
}
```

This is actually something that used to be possible with the SensioFrameworkExtraBundle.

Commits
-------

165524c [DoctrineBridge] Allow `EntityValueResolver` to return a list of entities
  • Loading branch information
nicolas-grekas committed Apr 18, 2024
2 parents 0d0bda1 + 165524c commit 58705a1
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ private function getCriteria(Request $request, MapEntity $options, ObjectManager
return $criteria;
}

private function findViaExpression(ObjectManager $manager, Request $request, MapEntity $options): ?object
private function findViaExpression(ObjectManager $manager, Request $request, MapEntity $options): object|iterable|null
{
if (!$this->expressionLanguage) {
throw new \LogicException(sprintf('You cannot use the "%s" if the ExpressionLanguage component is not available. Try running "composer require symfony/expression-language".', __CLASS__));
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Bridge/Doctrine/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ CHANGELOG
---

* Deprecate the `DoctrineExtractor::getTypes()` method, use `DoctrineExtractor::getType()` instead
* Allow `EntityValueResolver` to return a list of entities

7.0
---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ public function testExpressionFailureReturns404()

$manager->expects($this->once())
->method('getRepository')
->with(\stdClass::class)
->willReturn($repository);

$language->expects($this->once())
Expand Down Expand Up @@ -329,6 +330,7 @@ public function testExpressionMapsToArgument()

$manager->expects($this->once())
->method('getRepository')
->with(\stdClass::class)
->willReturn($repository);

$language->expects($this->once())
Expand All @@ -343,6 +345,48 @@ public function testExpressionMapsToArgument()
$this->assertSame([$object], $resolver->resolve($request, $argument));
}

public function testExpressionMapsToIterableArgument()
{
$manager = $this->createMock(ObjectManager::class);
$registry = $this->createRegistry($manager);
$language = $this->createMock(ExpressionLanguage::class);
$resolver = new EntityValueResolver($registry, $language);

$request = new Request();
$request->attributes->set('id', 5);
$request->query->set('sort', 'ASC');
$request->query->set('limit', 10);
$argument = $this->createArgument(
'iterable',
new MapEntity(
class: \stdClass::class,
expr: $expr = 'repository.findBy({"author": id}, {"createdAt": request.query.get("sort", "DESC")}, request.query.getInt("limit", 10))',
),
'arg1',
);

$repository = $this->createMock(ObjectRepository::class);
// find should not be attempted on this repository as a fallback
$repository->expects($this->never())
->method('find');

$manager->expects($this->once())
->method('getRepository')
->with(\stdClass::class)
->willReturn($repository);

$language->expects($this->once())
->method('evaluate')
->with($expr, [
'repository' => $repository,
'request' => $request,
'id' => 5,
])
->willReturn($objects = [new \stdClass(), new \stdClass()]);

$this->assertSame([$objects], $resolver->resolve($request, $argument));
}

public function testExpressionSyntaxErrorThrowsException()
{
$manager = $this->getMockBuilder(ObjectManager::class)->getMock();
Expand All @@ -364,6 +408,7 @@ public function testExpressionSyntaxErrorThrowsException()

$manager->expects($this->once())
->method('getRepository')
->with(\stdClass::class)
->willReturn($repository);

$language->expects($this->once())
Expand Down

0 comments on commit 58705a1

Please sign in to comment.