-
Notifications
You must be signed in to change notification settings - Fork 13
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
Add HydratorInterface::hydrateDocument(): stdClass #13
Comments
Yes, you are right, this method should be added to the interface. I would prefer this version though: public function hydrateSingleResource(Document $document); Unfortunately there is only one problem with it: it is a breaking change. :/ So my idea to deal with the situation would be to create a new interface something like What do you think about my ideas? |
Yeah, that also crossed my mind.
That is an option indeed... Something like: interface DocumentHydratorInterface extends HydratorInterface {
public function hydrateObject(Document $document);
} I think the return type should not be forced to As of PHP interface DocumentHydratorInterface extends HydratorInterface {
public function hydrateObject(Document $document) : object;
} |
Implemented in eba24d5 and c4cbab8 I changed some implementation details in Please test this new implementation, and if everything is OK I can release v2.1.0. |
nice! Will try to have a look this week 👍 |
@kocsismate I had a look and it works nice! And while we are at it: one point of consideration: would it be an idea to drop the So interface Hydrator {}
interface DocumentHydrator extends Hydrator {} instead of interface HydratorInterface {}
interface DocumentHydratorInterface extends HydratorInterface |
I really admire Mathias' work and blog posts, but I am not bought in this case. Somehow I always felt that having the |
However, I am still not exactly sure how to proceed with the Currently I'd favour the following scenario in case of
While in case of
The reason why I'd slightly prefer an empty Also, I think these two solutions do not differ much from each other from the end-user perspective. So instead of checking null: $dog = $hydrator->hydrateSingleResource($document);
if ($dog !== null) {
// ...
} The following should be checked: $dog = $hydrator->hydrateSingleResource($document);
if ($document->hasAnyPrimaryResources()) {
// ...
} The problem with the static analysis happens when the check for It won't happen when To also solve this issue, an exception could also be thrown when the document is empty so hydration should be done this way: if ($document->hasAnyPrimaryResources() === false) {
return;
}
$dog = $hydrator->hydrateSingleResource($document); Maybe it is a bit too strict 🤔 but the more I write about this topic, the more I prefer this solution as it eliminates the two possible issues mentioned (static analysis, missing attributes) while costing the same amount of I am really curious about your opinion if my reasoning makes sense to you or you think otherwise. |
Indeed, for people "not in to" static analysis: when using a high level of strictness, this: if($dog = $hydrator->hydrateSingleResource($document)){
echo $dog->name ' says woof!';
} will generate an error:
For me, I think that expecting a user to check for attributes to exist on an empty Example: abstracting JSON-API from user land code public function getHydratedObjectUsingFilter(Resource $resource, array $filter, array $includes = []) : ?stdClass
{
$request = $this->getFetchRequest($resource, $filter, [], $includes);
$response = $this->sendRequest($request);
return $this->getHydratedObjectFromJsonApiResponse($response);
}
private function getHydratedObjectFromJsonApiResponse(JsonApiResponse $response) : ?stdClass
{
return $response->hasDocument()
? $this->hydrateDocumentObject($response->document())
: null;
}
private function hydrateDocumentObject(Document $document) : ?stdClass
{
if ($document->isSingleResourceDocument()) {
return $this->getDocumentHydrator()->hydrateSingleResource($document);
}
//A single object is requested, but a collection is returned: the collection should contain at most one entry, for example when a filter is performed using a uniquely identifying attribute like user.email
$objects = $this->getDocumentHydrator()->hydrateCollection($document);
if (is_countable($objects)) {
if (count($objects) === 0) {
return null;
}
if (count($objects) === 1) {
return current($objects);
}
throw new LogicException(sprintf('At most one Resource expected in document, encountered: %d', count($objects)));
}
throw new LogicException(sprintf('Received non-countable hydration result of type %s', gettype($objects)));
} And eventually some abstraction levels up, the software that uses the API does not have to bother about the JSON-API: $user = $userRepository->findOneByEmail('user@domain.ext');
if($user === null){
$user = $this->createUser(/*.... */);
}
//continue dealing with $user In this case the responsibility for checking for Not sure this example makes sense though 😄 Bottomline: I think that reducing static analysis error messages should no influence such design decisions (too much)... Just my 2 cents! As you can see, I can abstract away the empty |
@holtkamp It's clear for me now that returning an empty For now, I'd still prefer the latter. Probably you are right that static analysis shouldn't be priority no. 1 but I think allowing users to omit |
Currently I (stil) mostly use the So I would say: keep this project neat, tidy and as strict as possible and go for the exceptions! 😄 |
👍 I implemented the change in my last commit. I'll release v2.1 very soon with it. :) Thank you very much for bringing up this problem and for the great discussion! Feel free to reopen the ticket if you find any problems with the new hydrator. |
Would it be an idea to add
to the
HydratorInterface
?Or even (not sure about this), one with a return type
This way IDE autocompletion also allows
hydrateObject()
when the HydratorInterface is used fetch the actual implementation from a DIC.The text was updated successfully, but these errors were encountered: