-
-
Notifications
You must be signed in to change notification settings - Fork 81
SerializerInterface violates LSP #115
Description
Hi @tobscure
First of all, thanks for your efforts making this library. I was looking at the php libraries implementing jsonapi in order to pick one for one of my projects. There are a few of them worth trying, including yours. Unfortunately, it looks like that all of them suffer from the same issue.
Issue
They all have the similar idea of serializers - the logic which converts a business entity (model) into a json data object. And these serializers look pretty much similarly: they have a number of methods like getId($model)
, getAttributes($model)
which take the entity as a parameter. These methods know about their $model
s internal structure and they use this knowledge to extract the id, attributes or whatever is needed to build the json. Consider the example from readme:
use Tobscure\JsonApi\AbstractSerializer;
class PostSerializer extends AbstractSerializer
{
protected $type = 'posts';
public function getAttributes($post, array $fields = null)
{
return [
'title' => $post->title,
'body' => $post->body,
'date' => $post->date
];
}
}
PostSerializer
can only deal with $post
models. The getAttributes()
call will fail on everything else except a properly structured post object. But SerializerInterface
does not restrict the model to anything particular. What SerializerInterface
says is basically: you give me anything (@param mixed $model
) and I tell you its attributes. Therefore, PostSerializer
breaks the contract given by SerializerInterface
. It means violation of Liskov Substitution Principle.
Solution (well, a kind of)
Instead of these pseudo-universal serializers, we should have something like ResourceInterface
:
interface ResourceInterface
{
public function getType(): string;
public function getId(): string;
public function getAttributes(array $fields = null): array;
public function getLinks(): array;
public function getMeta(): array;
public function getRelationship($name): ?\Tobscure\JsonApi\Relationship;
}
And a use-case would be like
class PostResource implements ResourceInterface
{
protected $type = 'posts';
public function __construct($post)
{
// validate $post
}
public function getAttributes(array $fields = null)
{
return [
'title' => $this->post->title,
'body' => $this->post->body,
'date' => $this->post->date
];
}
}
$document->setData(new PostResource($post));
Since your library version is still 0.*, it is not too late to make backward-incompatible changes to fix this issue. Please let me know what you think.