-
-
Notifications
You must be signed in to change notification settings - Fork 908
Rework to improve and simplify identifiers management #3664
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
55cae9d
to
e384651
Compare
Very important feature +++ 1 @soyuka can i help you ? |
There are several issues with this:
I'll let you know when and if we're testing it would love feedbacks. Thanks for the help. |
7dd65dd
to
7f94689
Compare
@@ -0,0 +1,85 @@ | |||
# Feature: JSON relations with plain identifiers support |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't it be removed?
@@ -12,6 +12,7 @@ Feature: Using custom identifier on resource | |||
"name": "My Dummy" | |||
} | |||
""" | |||
Then print last JSON response |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To remove.
features/main/operation.feature
Outdated
@@ -63,3 +63,23 @@ Feature: Operation support | |||
Scenario: Get a 404 response for the disabled item operation | |||
When I send a "GET" request to "/disable_item_operations/1" | |||
Then the response status code should be 404 | |||
|
|||
@createSchema | |||
Scenario: Get a book by it's ISBN |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scenario: Get a book by it's ISBN | |
Scenario: Get a book by its ISBN |
@@ -64,19 +63,13 @@ public function supports(string $resourceClass, string $operationName = null, ar | |||
* | |||
* @throws RuntimeException | |||
*/ | |||
public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) | |||
public function getItem(string $resourceClass, $identifiers, ?string $operationName = null, array $context = []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not typehinted to avoid BC? Maybe add a typehint comment for 3.0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed I didn't touch the interfaces yet but I can update them, this needs to target 3.0 though.
@@ -49,5 +50,6 @@ public function build(ContainerBuilder $container) | |||
$container->addCompilerPass(new GraphQlQueryResolverPass()); | |||
$container->addCompilerPass(new GraphQlMutationResolverPass()); | |||
$container->addCompilerPass(new MetadataAwareNameConverterPass()); | |||
// $container->addCompilerPass(new IdentifiedByResourceMetadataFactoryPass()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
b1ccb46
to
c689332
Compare
1dc650e
to
d3c0a44
Compare
Ease identifiers processing with breaking changes
d3c0a44
to
0db3206
Compare
@soyuka when it will be released? |
Hi @soyuka, sorry but my code is breaking (only in CI 😄 ) since 2.6 release. Unfortunately there isn't an UPGRADE guide, so I have to ask. I get the following error:
So I think I am on the right track with this PR/feature. The object is the only one which does not use <?php
namespace App\Entity;
/**
* @API\ApiResource(
* collectionOperations={
* "get": {
* "method": "GET",
* "path": "/benutzer.{_format}",
* "normalization_context": {"groups": {"benutzer_collection_output"}},
* },
* },
* itemOperations={
* "get": {
* "method": "GET",
* "path": "/benutzer/{id}.{_format}",
* "requirements": {"id": "%uuid_format%"},
* "normalization_context": {"groups": {"benutzer_item_output"}},
* },
* },
* attributes={
* "order": {"anzeigename": "ASC"},
* },
* )
* @API\ApiFilter(BooleanFilter::class)
* @ORM\Entity(repositoryClass="App\Repository\BenutzerRepository")
* @ORM\Table(
* name="benutzer",
* indexes={
* @ORM\Index(name="benutzer_anzeigename_idx", columns={"anzeigename"})
* },
* uniqueConstraints={
* @ORM\UniqueConstraint(name="benutzer_kontoname", columns={"kontoname"}),
* },
* )
*/
class Benutzer implements UserInterface
{
/**
* @API\ApiProperty(identifier=true, writable=false)
* @ORM\Column(name="object_guid", type="guid")
* @ORM\Id
* @Serial\Groups({
* "benutzer_collection_output",
* "benutzer_item_output",
* "fall_item_output",
* })
* @Assert\Uuid
*
* @var string
*/
private $objectGuid;
// ...
} I think I need a custom IRI converter from now on, am I right? |
Mhh it should not break on this I think it's a bug. Do you really have to declare the
Or specify
to see if it works? |
Thanks for your feedback 👍 Unfortunately this doesn't work. I used your code snippets like this: * itemOperations={
* "get": {
* "method": "GET",
-* "path": "/benutzer/{id}.{_format}",
-* "requirements": {"id": "%uuid_format%"},
+* "path": "/benutzer/{objectGuid}.{_format}",
+* "requirements": {"objectGuid": "%uuid_format%"},
* "normalization_context": {"groups": {"benutzer_item_output"}},
* },
* }, and (but only one at a time) like this: * attributes={
+* "identifiers": {"id": {"objectGuid", Benutzer::class}},
* "order": {"anzeigename": "ASC"},
* }, but also tried this: * itemOperations={
* "get": {
* "method": "GET",
* "path": "/benutzer/{id}.{_format}",
* "requirements": {"id": "%uuid_format%"},
+* "identifiers": {"id": {"objectGuid", Benutzer::class}},
* "normalization_context": {"groups": {"benutzer_item_output"}},
* },
* }, Where can I find some documentation for the "identifiers" ? 🤔 My tests are failing, I add one for reference: /**
* @test
*/
public function canBeSerializedWithDefaultSerializationGroup(): void
{
/** @var Entity\RamicroAkte $ramicroAkte */
$ramicroAkte = self::fixtureFactory()->createOne(Entity\RamicroAkte::class);
$serializer = self::formatAndContextSpecificSerializer('json');
$serialized = $serializer->serialize($ramicroAkte);
$iriResolver = self::iriResolver();
$expected = self::jsonEncoder()->encode([
'aktenzeichen' => $ramicroAkte->getAktenzeichen(),
'fall' => $iriResolver->iriFor($ramicroAkte->getFall()),
'gegnerischeBank' => $iriResolver->iriFor($ramicroAkte->getGegnerischeBank()),
'id' => $ramicroAkte->getId(),
'benutzer' => $iriResolver->iriFor($ramicroAkte->getBenutzer()),
]);
self::assertJsonStringEqualsJsonString($expected, $serialized);
} for bootstrapping the IRI Resolver: final protected static function iriResolver(): Util\Serializer\IriResolver
{
$iriConverter = self::$container->get(Core\Api\IriConverterInterface::class);
return new Util\Serializer\IriResolver($iriConverter);
} and my IRI Resolver itself: <?php
declare(strict_types=1);
namespace App\Tests\Util\Serializer;
use ApiPlatform\Core\Api\IriConverterInterface;
final class IriResolver
{
private IriConverterInterface $iriConverter;
public function __construct(IriConverterInterface $iriConverter)
{
$this->iriConverter = $iriConverter;
}
public function iriFor(?object $item): ?string
{
if (null === $item) {
return null;
}
return $this->iriConverter->getIriFromItem($item);
}
/**
* @return string[]
*/
public function irisFor(object ...$items): array
{
return array_map(function (object $item): string {
return $this->iriConverter->getIriFromItem($item);
}, $items);
}
} cc @localheinz |
* itemOperations={
* "get": {
* "method": "GET",
-* "path": "/benutzer/{id}.{_format}",
-* "requirements": {"id": "%uuid_format%"},
+* "path": "/benutzer/{objectGuid}.{_format}",
+* "requirements": {"objectGuid": "%uuid_format%"},
* "normalization_context": {"groups": {"benutzer_item_output"}},
* },
* }, Is working. |
Basically my idea was to specify on the operation what it's identifiers are. This helps a lot with identifiers parsing etc.
The code speaks for itself. I still need to find a solution for composite identifiers, for example we can deprecate them but keep an option:
Would work and force a single identifier in the route path even if there were several.