Hey there,
Forgive me if I read incorrectly, but I don't think there's any documentation about validating relationships as part of a new resource creation, such as the request body shown in the example under http://jsonapi.org/format/#document-resource-objects
The current solution I'm using is to manually construct the relationships validator and set it on the main resource validator. eg.
$validator = $this->getResourceObjectValidator(...)
$validator->setRelationshipsValidator(new RelationshipsValidator([
'relationshipName' => $this->getHasOneValidator('relationship_type')
]);
Although I'm not 100% sure that this is the recommended method.
If you would like me to submit a change to README to that effect under content validation, I'm happy to do that too.
@mosen
Thanks for your message. I need to sit down and write some proper documentation at some point but unfortunately the project that I've created this package for is burning all of my time at the moment. Better documentation will come at some point!
What you're currently doing above works, but there's handy helper methods that make it easier to write. What you've written above can be rewritten as:
$validator = $this->getResourceObjectValidator(...)
->hasOne('relationshipName', 'relationshipType');
You can also use hasMany() as a helper for adding a hasMany relationship. These helper methods are chainable, so you you call many in a row.
Both hasOne() and hasMany() take the relationship name as the first argument and a relationship type for the second. If your relationship can accept multiple types (i.e. it's polymorphic) then pass in an array of types for the second argument.
Both these helper methods take an optional third argument of options (in an array) that can be set on either the HasOneValidator or HasManyValidator that is created. E.g. you could do the following:
$validator = $this->getResourceObjectValidator(...)
->hasOne('relationshipName', 'relationshipType', [
'required' => true,
'allowEmpty' => false,
'callback' => function (ResourceIdentifierInterface $identifier) {
return Person::where('id', $identifier->getId())->exists();
}
]);
required is whether the client must have provided the relationship in the resource object that was sent. allowEmpty is whether the relationship can be empty (null for has-one, empty array for has-many).
If provided, the callback is invoked by the validator to check that the actual id provided by the client is valid. This callback is only called if all other validation on the relationship passes - i.e. you can trust that $identifier passed in to the callback has the correct resource type on it and there is an id value.
For a has-many validator, the callback is provided with an instance of ResourceIdentifierCollectionInterface.
Let me know if you have any questions! I'm going to leave this issue open as a reminder that I need to add better documentation for validation.
Thanks a bunch, that really cleared up everything I was missing on validation.
howdy @lindyhopchris
I've been checking out the relationship management with creating/updating a resource and I've stumbled upon this issue...I have a few questions I hope you can help me with:
relationshipName and relationshipType look like? I'm having trouble distinguishing them (especially the relationshipType).hasOne() and hasMany(), what are the default values for required, allowEmpty and callback?required and have the rest as default? What would each value default to?Thank you so much in advance.
@nickelozz
No problem...
$relationshipName is the key of the relationship on the resource object that is being validated. $relationshipType is the type of the resource on the inverse side of the relationship (I probably should have called the variable $resourceType). E.g. if you are validating a post resource object that has an author relationship, where the author is a person resource object, then $relationshipName would be author and $relationshipType would be person.allowEmpty is true, required is false. callback is null, i.e. no callback to execute in the validation. I use the callback to check that the provided id for the relationship actually exists (normally a database query).@lindyhopchris excellent!! tyvm sir :smiley:
Hi @lindyhopchris !
I have the same question, how can I validate relationships object's data?
I tried to use $relationships->hasOne('key', 'type', true, false) in relationshipRules method, but I think that this method just for checking exist of object.
How can I add some validation rules to this object?
Hi @mandryka
The relationship validation checks that the relationship object is correct according to the JSON API spec, and it also checks via the store that the related resource exists. Additionally it checks allowEmpty and required depending on the settings.
If you need to validate the actual relationship identifier that was sent, pass a Closure for the next argument as per here:
https://github.com/cloudcreativity/json-api/blob/master/src/Contracts/Validators/RelationshipsValidatorInterface.php#L55-L56
Alternatively you can pass an instance of AcceptRelatedResourceInterface which would allow you to use dependency injection within that instance if you resolve it out of the container.
If you're still stuck or can't figure out how to do what you're trying to achieve, then create a new issue with an explanation of what you're trying to validate and I'll be able to help.
@lindyhopchris thanks a lot!
I created AcceptRelatedEntity class, which implements AcceptRelatedResourceInterface
and added validation for related entity to accept(...). Also I used ErrorCreatorTrait for adding errors.
Might be able to close this one, since it seems like everything has been rewritten 馃槃
Yeah, good point.
Most helpful comment
@lindyhopchris thanks a lot!
I created
AcceptRelatedEntityclass, which implementsAcceptRelatedResourceInterfaceand added validation for related entity to
accept(...). Also I usedErrorCreatorTraitfor adding errors.