tobyzerner / json-api-server

A JSON:API server implementation in PHP.
https://tobyzerner.github.io/json-api-server/
MIT License
63 stars 21 forks source link

chore: allow mutation of resource fields #104

Closed SychO9 closed 3 months ago

SychO9 commented 4 months ago

Hello 👋🏼,

We have use case where a resource's different fields (namely: fields, endpoints and sorts) need to be extendable (addable, removable, mutatable).

This is only possible if the different methods go through one additional internal call that could enable mutation before caching and returning the final sets.

Of course, totally understandable if this change isn't deemed appropriate for the package.

Alson, this is the trait we are using for this (let me know if it's something that could be useful in the package as well) https://github.com/flarum/framework/blob/sm/json-api-server/framework/core/src/Api/Resource/Concerns/Extendable.php

Thanks!

tobyzerner commented 3 months ago

I understand where you're coming from here, but not keen to include this change in the package because then the interface methods are named resolve*, which is less natural if you're implementing the interface directly.

I would actually suggest that you should put your "default" fields/endpoints/filters/sorts in methods named something like default*, base*, or core*, and then have the extension logic in the interface methods. This makes it more explicit that those are just defaults which may be subject to change:

    // Subclass
    protected function defaultEndpoints()
    {
        return [];
    }

    // Parent class or trait
    public function endpoints(): array
    {
        if (! is_null($this->cachedEndpoints)) {
            return $this->cachedEndpoints;
        }

        $endpoints = $this->defaultEndpoints();

        foreach (array_reverse(array_merge([static::class], class_parents($this))) as $class) {
            if (isset(static::$endpointModifiers[$class])) {
                foreach (static::$endpointModifiers[$class] as $modifier) {
                    $endpoints = $modifier($endpoints, $this);
                }
            }
        }

        return $this->cachedEndpoints = $endpoints;
    }