FriendsOfCake / crud-json-api

Build advanced JSON API Servers with almost no code.
https://crud-json-api.readthedocs.io/
MIT License
56 stars 32 forks source link

belongsToMany association via `through` table is not generating correctly formatted results. #128

Closed geoidesic closed 4 years ago

geoidesic commented 4 years ago

I have the following route:

Router::prefix('api', function (RouteBuilder $routes) {
    JsonApiRoutes::mapModels(['Enquiries'], $routes);

I have an through association defined on EnquiriesTable:

 $this->belongsToMany('Clients', ['through' => 'EnquiryContacts', 'className' => 'People', 'conditions' => ['role_id' => 3], 'foreignKey' => 'enquiry_id', 'targetForeignKey' => 'person_id']);

I've managed to get this association to correctly save a record to the EnquiryContacts table.

However when I try to retrieve the associated records via the generated relationships URL:

api/enquiries/b1c71787-84b9-4a51-a577-3fcae1e395f1/relationships/clients

The data I get back looks like this:

{
    "links": {
        "self": "/api/enquiries/b1c71787-84b9-4a51-a577-3fcae1e395f1/relationships/clients",
        "related": "/api/enquiries/b1c71787-84b9-4a51-a577-3fcae1e395f1/clients"
    },
    "data": [
        {
            "type": "people",
            "id": "3c9b642f-6682-4b7a-aff2-000000000020"
        }
    ]
}

Which is not according to the JSON:API spec, I don't think. Also I get this same data back from other similar associations for which no records have been saved, so it is not respecting the conditions config option of the route when fetching data.

geoidesic commented 4 years ago

I tried to simplify this in order to remove some possible problems. Firstly, instead of a through table, I used a join table and removed the need for a role_id condition. So the schema for the join becomes this:

        $this->table('enquiry_clients')
            ->addColumn('enquiry_id', 'uuid')
            ->addColumn('person_id', 'uuid')
            ->addColumn('role_id', 'integer', ['signed' => false, 'default' => 3])
            ->addColumn('created', 'datetime')
            ->addColumn('modified', 'datetime')
            ->create();

and the association like so:

$this->belongsToMany('Clients', ['joinTable' => 'enquiry_clients', 'className' => 'People', 'foreignKey' => 'enquiry_id', 'targetForeignKey' => 'person_id']);

The result is no different to the above – it still saves the association correctly but when retrieving the data via the relationships link it is exactly as shown n the OP.

The only notable difference is that now the other similar associations don't return the same data. E.g. the representatives association, which now returns the following:

{
    "links": {
        "self": "/api/enquiries/2c1e6c31-6eba-4fa1-b066-8e203644b738/relationships/representatives",
        "related": "/api/enquiries/2c1e6c31-6eba-4fa1-b066-8e203644b738/representatives"
    },
    "data": []
}
geoidesic commented 4 years ago

This is not a well described issue: this effectively describes a whole bunch of bugs, so I will close this and create new issues which isolate the bugs better.