The dependent framework-agnostic package has a number of changes. Below lists the changes you will need to make
to your application. However, if you are also extending underlying package functionality you will also need to refer
to the v0.5 to v0.6 upgrade notes here:
cloudcreativty/json-api Upgrade Notes
Paging config is now defined on a per-API basis, so you need to move your paging config into your API namespace
config in the json-api.php config file. We have updated the comment blocks to reflect this; you can find those
in the config/json-api.php file within this package.
Before:
return [
'namespaces' => [
'v1' => [
'url-prefix' => '/api/v1',
'supported-ext' => null,
],
],
// ...
'pagination' => [
'params' => [
'page' => null,
'per-page' => null,
],
'meta' => [
'key' => null,
'current-page' => 'page',
'per-page' => 'size',
'first-item' => null,
'last-item' => null,
'total' => null,
'last-page' => 'last',
],
]
];After:
return [
'namespaces' => [
'v1' => [
'url-prefix' => '/api/v1',
'supported-ext' => null,
'paging' => [
'page' => null,
'per-page' => null,
],
'paging-meta' => [
'current-page' => 'page',
'per-page' => 'size',
'first-item' => null,
'last-item' => null,
'total' => null,
'last-page' => 'last',
],
],
],
];If you are extending the AbstractAuthorizer class and implementing your own constructor, you will need to
inject an instance of CloudCreativity\JsonApi\Contracts\Repositories\ErrorRepositoryInterface into the parent
constructor. This change means you can now add errors to the error collection on your authorizer using the string
keys for error objects held within your json-api-errors config file. For example:
public function canRead($record, EncodingParametersInterface $parameters)
{
if (!\Auth::check()) {
$this->addError('access-denied');
return false;
}
return true;
}Note that the recommended way to create error objects is via the error repository (which holds your error config) because it provides opportunities to add in translation etc of errors in the future.
You will also need to implement the canModifyRelationship method. This was previously implemented in the abstract
class but the previous implementation no longer works because of the change below.
Update authorization can now access the resource sent by the client. At the point the authorizer is invoked, the resource will have been validated to check that it complies with the JSON API spec but it will not have been checked that it is valid according to your business logic - i.e. attributes and relationships will not have been validated against the specific rules for that resource type.
Change the canUpdate method from this:
canUpdate($record, EncodingParametersInterface $parameters)to:
// CloudCreativity\JsonApi\Contracts\Object\ResourceInterface;
canUpdate(
$record,
ResourceInterface $recource,
EncodingParametersInterface $parameters
) Relationship modification authroization can now access the relationship sent by the client, as per the update authorization changes above.
Change the canModifyRelationship method from this:
public function canModifyRelationship(
$relationshipKey,
$record,
EncodingParametersInterface $parameters
)to:
// CloudCreativity\JsonApi\Contracts\Object\RelationshipInterface
public function canModifyRelationship(
$relationshipKey,
$record,
RelationshipInterface $relationship,
EncodingParametersInterface $parameters
)The request class is no longer injected into the parent constructor. This change was necessary to support Laravel 5.3.
Instead you now need to implement the getRequestHandler method and return a string of the fully qualified class
name of the handler that is to be used. If you were not calling the parent constructor, you must now call it.
For example in an Eloquent controller, this:
public function __construct(
Posts\Request $request,
Posts\Hydrator $hydrator,
Posts\Search $search
) {
parent::__construct(new Post(), $request, $hydrator, $search);
}Must be changed to:
public function __construct(Posts\Hydrator $hydrator, Posts\Search $search)
{
parent::__construct(new Post(), $hydrator, $search);
}
protected function getRequestHandler()
{
return Posts\Request::class;
}The method signature of all the action methods have changed - they now all receive the validated JSON API request object as they first argument.
For example, this:
public function read($resourceId) {}Has become this:
use CloudCreativity\JsonApi\Contracts\Http\Requests\RequestInterface as JsonApiRequest;
// ...
public function read(JsonApiRequest $request) {}Use the request object to get the resource id, relationship name and document (the JSON API request content). Refer to the interface for methods available.
The saving, saved, creating, created, updating, updated method hooks now receive the resource provided
by the client as the second method argument. (This object passed implements
CloudCreativity\JsonApi\Contracts\Object\ResourceInterface.)
In addition, these methods are no longer implemented in the parent class. This means you can use whatever method signature you want, including type-hinting the first argument as the specific class of model that is being handled by the controller.
You now need to always inject a search object into the Eloquent controller, otherwise the controller will return a
501 Not Implemented response for the index action.
Previously the controller would list all models and would allow a find-many request (i.e. the client providing
a list of ids as the id filter). If you have not written your own search class for the model being handled by
your controller and want to maintain the previous behaviour, inject a SearchAll instance via your constructor:
use CloudCreativity\LaravelJsonApi\Search\SearchAll;
public function __construct(SearchAll $search)
{
parent::__construct(new Post(), null, $search);
}The namespace of the AbstractHydrator has changed from CloudCreativity\LaravelJsonApi\Hydrator\AbstractHydrator
to CloudCreativity\JsonApi\Hydrator\AbstractHydrator.
Class CloudCreativity\LaravelJsonApi\Http\Requests\AbstractRequest has been removed. Instead you should extend
CloudCreativity\JsonApi\Http\Requests\RequestHandler.
Note that the constructor for this new class has the authorizer as the first argument and the validators as the second (i.e. it is the other way round from what it was before). We've made this change because authorization occurs before validation, so it makes more sense for the arguments to be this way round.
The method signature for the errors method has changed. To maintain the old behaviour use error instead (it
accepts an error collection as well as a single error).
The JSON API specification recommends using hyphens for member names, e.g. foo-bar. The Eloquent schema now uses
this recommendation as its default behaviour. E.g. a model key of foo_bar will be serialized as foo-bar.
To maintain the old behaviour (of using the model key for the member key), set the $hyphenated property on your
schema to false. If you want to implement your own logic, overload the keyForAttribute method.
If you have irregular mappings of model keys to attribute keys, you can define these in your $attributes property,
e.g.
protected $attributes = [
'foo',
'bar',
'foo_bar' // will be dasherized to 'foo-bar' by default
'baz' => 'bat' // model key `baz` will be serialized to attribute key `bat`
];We've merged the abstract sorted search class into the abstract search class, to simplify things.
You'll need to change:
use CloudCreativity\LaravelJsonApi\Search\AbstractSortedSearch;
class Search extends AbstractSortedSearch
{
}to:
use CloudCreativity\LaravelJsonApi\Search\AbstractSearch;
class Search extends AbstractSearch
{
}If you are overloading the constructor, you will need to call the parent constructor and provide it with the following two dependencies:
CloudCreativity\JsonApi\Contracts\Http\HttpServiceInterface
CloudCreativity\JsonApi\Contracts\Pagination\PaginatorInterfaceWhen working out what column to use for a sort parameter, the sort parameter will automatically be snake cased if your model uses snake attributes. If it does not use snake attributes, the parameter will be camel cased.
If you have irregular mappings of search params to column names, add that mapping to your $sortColumns property,
e.g. $sortColumns = ['foo-bar' => 'baz_bat'].
If you want to use a completely different logic for converting search params to column names, overload the
columnForField() method.
The classes that provide validators for individual resource types generally extend AbstractValidatorProvider. This
now receives the resource type that is being validated into its public methods, and this is now passed down through
the internal methods. You'll therefore need to make the changes described below.
This change has been made so that a single validator provider can be used for multiple resource types if desired. Although you are likely to keep a validator provider per resource type (because attribute and relationship rules will be specific to a resource type), this has given us the capability to implement a generic validator provider capable of validating any resource type according to the JSON API spec.
If you have implemented a constructor, you will need to type hint the following interface and pass it to the parent constructor:
CloudCreativity\LaravelJsonApi\Contracts\Validators\ValidatorFactoryInterfaceYou can remove the $resourceType property as it is no longer required.
You'll need to adjust the signature of the following abstract methods, from:
attributeRules($record = null)
relationshipRules(RelationshipsValidatorInterface $relationships, $record = null)
filterRules()to:
attributeRules($resourceType, $record = null)
relationshipRules(RelationshipsValidatorInterface $relationships, $resourceType, $record = null)
filterRules($resourceType)The filterRules method is actually no longer abstract, so if you are returning an empty array from it you can delete
it.
The signatures of other protected methods have also changed to pass down this additional argument. If you have
implemented any other methods, check the abstract class for the new argument order.