Skip to content
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

Relationship validation of object/array #335

Closed
dklesev opened this issue Apr 4, 2019 · 4 comments
Closed

Relationship validation of object/array #335

dklesev opened this issue Apr 4, 2019 · 4 comments
Milestone

Comments

@dklesev
Copy link

dklesev commented Apr 4, 2019

Example: An Owner can have many Pets. A Pet has only one Owner.

But if I try to send invalid PATCH (array of Owners):

{
    "data": {
        "type": "pets",
        "id": "1",
        "attributes": {
            "someValue": true
        },
        "relationships": {
            "owner": {
                "data": [{
                    "type": "owners",
                    "id": "1"
                }]
            }
        } 
    }
}

(Type member is not a string, or is empty. at /var/www/vendor/cloudcreativity/laravel-json-api/src/Object/IdentifiableTrait.php:47)

or an invalid PATCH (Pet object)

{
    "data": {
        "type": "owners",
        "id": "1",
        "attributes": {
            "someValue": true
        },
        "relationships": {
            "pets": {
                "data": {
                    "type": "pets",
                    "id": "1"
                }
            }
        } 
    }
}

(Argument 1 passed to CloudCreativity\LaravelJsonApi\Object\ResourceIdentifier::fromArray() must be of the type array, string given)

I get an HTTP 500 (see errors above).

How or where to check if relationship is a valid Array (HasMany) or object (HasOne)?

@lindyhopchris
Copy link
Member

Hi. If a pet has only one owner, the owner relationship should be to-one as follows:

{
    "data": {
        "type": "pets",
        "id": "1",
        "attributes": {
            "someValue": true
        },
        "relationships": {
            "owner": {
                "data": {
                    "type": "owners",
                    "id": "1"
                }
            }
        } 
    }
}

Then in reverse, an owner can have multiple pets i.e. to-many, so your other request should be:

{
    "data": {
        "type": "owners",
        "id": "1",
        "attributes": {
            "someValue": true
        },
        "relationships": {
            "pets": {
                "data": [{
                    "type": "pets",
                    "id": "1"
                }]
            }
        } 
    }
}

You're getting a 500 response because the code is expecting you to validate whether you've been sent the right kind of relationship - i.e. to-one or to-many. For example, your pets validator should have the following rule:

return [
  'owner.type' => 'required|in:owners'
];

And your owners validator:

return [
  'pets' => 'array',
  'pets.*.type' => 'in:pets',
];

@dklesev
Copy link
Author

dklesev commented Apr 5, 2019

Personally, I don't think the validation by the developer should be explicitly specified here, because "the code" knows if it's a To-One or a To-Many relationship. I mean isn't it more convenient to include it in the Core/Package instead of defining same/similar rules for other resources?

And if I try to add "pets" => "array" rule, it is just ignored. But maybe it's my fault somewhere.

@lindyhopchris
Copy link
Member

lindyhopchris commented Apr 5, 2019

Yeah you're right... I think this is because historically there hasn't been a way to work this out, but as you say there is now. Will add it to the to-do list.

Note to self: add methods to the store interface to check whether a relation is to-one or to-many. This can be answered by detecting the interface of the adapter's relation. Need to work out what to do if the relation doesn't exist on the adapter - reject or allow? Presumably reject. Could also potentially store the inverse resource type on the relation, which would mean both the validator and the routing stack could gain access to it.

@lindyhopchris
Copy link
Member

Closing in favour of the linked issue in the new package (above). This is entirely possible in the new package because the spec validators have access to field information (derived from the resource schema). I think I've probably already implemented rejecting invalid relationships in the new package - but I've just created the above issue to double check before marking it off as done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants