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

What's the best way to go about hiding fields on the transformer domain? #226

Closed
pavankataria opened this issue Sep 20, 2015 · 5 comments
Closed

Comments

@pavankataria
Copy link

Hey @philsturgeon (or anyone else). I ended up buying your book, it was a good investment. Learned quite a bit on some REST theory, and other topics too. I learned about Fractal and had a quick question.

I'm looking to hide some fields on the presentation layer, i.e. in the transformer class:
$fieldsTohide for example without blacklisting in my model class.

is it currently possible to do so in Fractal? If not, do you mind suggesting how this can be achieved?

I have a list of nested relationships that I transformer with Fractal.
Great package btw, does a lot of the transform processing for me.

@brayniverse
Copy link

Do you mean how can you be specific about what fields you return or is there a way to filter the results based on some passed query string parameter?

The former of the two is available out of the box so I'm going to presume you meant the latter and offer this solution.

public function transform(User $user)
{
    return $this->filterFields([
        'name' => (string) $user->name,
        'email' => (string) $user->email,
        'age' => (int) $user->age
    ]);
}

protected function filterFields(array $user)
{
    $fields = isset($_GET['fields']) ? explode(',', $_GET['fields']) : array_keys($user);

    return array_intersect_key($user, array_flip((array) $fields));
}

If no fields parameter is present the filterFields method will return the unmodified data. However, if the parameter is present it will compare the fields to the keys on the provided array and only return whatever is matched.

I hope this helps.

@brayniverse
Copy link

Hm after posting that I gave it some thought and if you'd like to filter included data this solution will need some modification.

@hugofcampos
Copy link

This works well, but the global var makes tests harder. Wondering if there is any solution to that.

@willishq
Copy link
Member

I would suggest doing something like so:

use League\Fractal\TransformerAbstract;

class UserTransformer extends TransformerAbstract
{
    public function __construct($fields = null)
    {
        $this->fields = $fields;
    }

    public function transform(User $user)
    {
        return $this->transformWithFieldFilter([
            'name' => (string) $user->name,
            'email' => (string) $user->email,
            'age' => (int) $user->age
        ]);
    }

    protected function transformWithFieldFilter($data)
    {
        if (is_null($this->fields)) {
            return $data;
        }

        return array_intersect_key($data, array_flip((array) $this->fields));
    }
}

Then, when you use your transformer, you pass through the fields to transform:

use League\Fractal;

$fields = $request->get('fields');

$resource = new Fractal\Resource\Item($book, new UserTransformer($fields));

@imjohnbon
Copy link

imjohnbon commented Jun 29, 2016

For anyone who finds this via a Google search or something in the future, if you want this to work so you can pass multiple fields to an endpoint like this: /endpoint?fields=id,created_at,whatever

You can adjust the above code in the following way:

protected function transformWithFieldFilter($data)
{
    if (is_null($this->fields)) {
        return $data;
    }

    $fields = explode(',', $this->fields);

    return array_intersect_key($data, array_flip($fields));
}

IllyaMoskvin added a commit to art-institute-of-chicago/data-aggregator that referenced this issue Sep 22, 2017
Specifically, this param takes effect after all other transformations
are complete. In other words, it's not acting on the model attributes
per se, but rather on the fields displayed in the API.

See thephpleague/fractal#226
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants