Question: Make single Schema Class and other things
mtangoo opened this issue · comments
Hi,
am currently in search of right JSONApi library to use. I was reading your implementation and I found it using few classes (Model, Schema and Encoder -- did I miss anything else). Now looking at schema it needs ID and Attributes. Now I use Laravel's Eloquent models for data in non-Laravel homegrown framework that am trying to add JSONAPI ability. Now I have questions:
- Is there a way I can tell the library about how to fetch attributes and id apart from current way (I'm thinking of making schema class that gets Model in its c'tor and returns the attributes and id but wanted to know if there is easier way)
- Does the library provide a class for taking data from JSONAPI request and create an Object of that class from data?
Tanks for the library and time.
Hi,
The library is framework agnostic and do not rely on any specific Model
classes (do not require). You can view Schema
as an adapter for models you use (Eloquent, Doctrine, plain classes or else). As you can see in wiki you can use any ORM you like.
I'm thinking of making schema class that gets Model in its c'tor and returns the attributes and id but wanted to know if there is easier way)
I think the way it works now is easier. You create Schemes
each of them can 'transform' your models to format which Encoder
understands. The library would reuse Schema
instances (they do not store any data from models) which is way more efficient than creating 1 schema for every 1 model.
Does the library provide a class for taking data from JSONAPI request and create an Object of that class from data?
The library do not provide parser for JSON API documents. The reason is that IMHO it cannot be developed in generic and efficient way. For example
- should it parse meta and links? For CRUD it's not necessary but for 'generic' parser it should be done
- how to deal with polymorphic data? For typical usage it's not needed though for 'generic' solution it should be done. And even if added it would be very opinionated.
- what parser should do with attributes/meta/links in relationships? For create and update only type + id is needed. So parsing the rest would slow the parser.
I feel I have answered the question and I don't have any feedback from you. I'm closing the question. If you have any further questions please don't hesitate to ask.
Thank you a lot. For sure you ave answered them with details. Sorry for the feedback, I got caught with some other thing. However one thing is still not clear in your answer:
I think the way it works now is easier. You create Schemes each of them can 'transform' your models to format which Encoder understands. The library would reuse Schema instances (they do not store any data from models) which is way more efficient than creating 1 schema for every 1 model.
If my model have uniform interface they implement that provides all information schema needs, shouldn't I have a single schema that deals with it all? Something like
interface IModel
{
public function getAttributes();
public function getId();
}
Then I will have just a single Schema with something like
class AuthorSchema extends SchemaProvider
{
protected $resourceType = 'people';
public function getId($model)
{
/** @var Author $author */
return $author->getId();
}
public function getAttributes($author)
{
/** @var Author $author */
return $author->getAttributes();
}
}
Then with every model I just Plugin the same Schema. What's your opinion on that?
Sure you can do that and have one Schema
for all models. Though $resourceType
must have different values and there are usually requirements that differ from schema to schema. They 'might'/'might not' have links/meta/paging info/relationships/defaut include paths/etc so in general case it's better to support multiple schemes.
If you feel you can have 1 schema for all I would recommend something like
abstract class BaseSchema extends SchemaProvider
{
...
}
class AuthorSchema extends BaseSchema
{
protected $resourceType = 'people';
}
I see your point. I have not looked deep, but my impression was the support for all those (links/meta/paging info/relationships/etc) is similar to what I have read in getId() and getAttributes(). Is that so?
As of resourceType, why is it hard-corded instead of flexible function like getId() is? IMHO it kill flexibility of Schema that is already there in other functions.
As you can see they are protected and cannot be used outside of the class. They are not used directly in the class as well (only via getters). You can override the following methods and be good (default implemnetation below)
/**
* @inheritdoc
*/
public function getResourceType()
{
return $this->resourceType;
}
/**
* @inheritdoc
*/
public function getSelfSubUrl($resource = null)
{
return $resource === null ? $this->selfSubUrl : $this->selfSubUrl . '/' . $this->getId($resource);
}
the reason is that defining 1 property is easier than 2 methods.
overriding them is better method. I didn't knew that method exists. Let me work with information I have. I will be coming back for questions in issues (unless there is other specific place).
I appreciate your time and help. Thank you!
This library is built on interfaces. It means you can replace any part of the lib with your interface implementation. You don't like default SchemaProvider
? No probs. You can implement SchemaProviderInterface
the way you like and it will work absolutely fine.
Is it possible to pass instance of schema instead of string of the class name? I tried that and got
Catchable fatal error: Argument 1 passed to Neomerx\JsonApi\Schema\SchemaProvider::__construct() must be an instance of Neomerx\JsonApi\Contracts\Schema\SchemaFactoryInterface, none given
I ask that because I want to configure some internal properties of my schema before sending it to encoder.