Closed geoidesic closed 4 years ago
My suggested solution is that a Trait be added to support this feature. The reason I suggest this is that crud-json-api
is a bit of a strange beast – it's intended to support the JSONAPI spec but as it's an extension of crud
it only really extends that libraries existing features so as to make them JSONAPI compliant. However there are parts of the JSONAPI spec that fall outside of the remit of crud
. This is one such example.
One way around this is to add a Trait that can be used optionally to add this functionality. E.g.
trait CrudJsonApiControllerTrait
{
/**
* related method
*
* @return \Cake\Http\Response|null
*/
public function related()
{
$pass = $this->request->getParam('pass');
$id = $pass[0];
$relation = $pass[1];
$this->Crud->on('beforePaginate', function (\Cake\Event\Event $event) use ($id, $relation) {
$event->getSubject()->query
->innerJoinWith(ucfirst($relation))
->where([ucfirst($relation) . '.id' => (int) $id]);
});
return $this->Crud->execute('index');
}
}
Along with which you will need the route...
$routes->connect('/{relation}/{id}/dishes', ['controller' => 'Dishes', 'action' => 'related'], ['id' => '\d+', 'pass' => ['id', 'relation']]);
Now you can make a crud controller support this part of the JSONAPI spec by simply setting the corresponding route and using this Trait.
This is already supported, but perhaps not documented.
You need to create a nested resource route as per https://book.cakephp.org/4/en/development/routing.html#creating-nested-resource-routes
You can then use $this->request->getParam('article_id')
within the controller. I recommend using the hinted at prefix
routing for the relationship controllers.
I would also recommend using a crud action instead of a trait (In keeping with the action object pattern used in Crud)
Good to know about the nested resource route option, however It still requires custom controllers / actions. It would be better I think if this plugin handled that internally. I'm just not sure how to implement that.
I.e. given such a URL, one should not have to custom build an Action, the plugin should recognise the URL format and apply the where clause automatically. Wouldn't you agree?
I would also recommend using a crud action instead of a trait (In keeping with the action object pattern used in Crud)
That makes sense.
The crud-json-api
plugin doesn't have any custom actions, it relies solely on the standard CRUD actions supplied by crud
. So maybe the way forward is to add custom Actions to the crud-json-api
plugin that cater for these special cases.
These can then be mapped in the component config e.g.:
$this->loadComponent('Crud.Crud', [
'actions' => [
'Crud.Index',
'Crud.View',
'Crud.Add',
'Crud.Edit',
'Crud.Delete',
'Crud.Bulk',
'CrudJsonApi.RelationshipsIndex`,
'CrudJsonApi.RelationshipsEdit`
],
I would also recommend using a crud action instead of a trait (In keeping with the action object pattern used in Crud)
I'm busy trying this but I don't seem to have access to the request data in a crud action class.
E.g. in my trait I had an action method like this:
public function updaterelationships()
{
$request = $this->request;
$id = $request->getParam('id');
$foreignTableName = $request->getParam('foreignTableName');
$data = $request->getData();
And $data
would then hold the request body i.e.:
Array
(
[data] => Array
(
[0] => Array
(
[type] => dishes
[id] => 3c9b642f-6682-4b7a-aff2-000000000043
)
)
)
However, once I refactor it as RelationshipsAction::_patch
then I don't seem to have access to the request body any longer. E.g.
class RelationshipsAction extends BaseAction
{
protected function _patch()
{
print_r($this->_request()->getData())
yields an empty array.
Any ideas? Obviously I need access to the request body to process it.
Fixed in current version of cake-4.x
branch.
According to the Spec: https://jsonapi.org/format/#fetching-relationships One should be able to fetch just the related data for a given record using URL of the following format:
This doesn't not work with
crud-json-api
, it gives an error:My routes look like this: