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

Mapped relation with include function #107

Closed
IlCallo opened this issue Feb 2, 2018 · 4 comments
Closed

Mapped relation with include function #107

IlCallo opened this issue Feb 2, 2018 · 4 comments

Comments

@IlCallo
Copy link
Contributor

IlCallo commented Feb 2, 2018

I've observed a weird behaviour I cannot explain.
When I put both a mapping and an include function, the system breaks if I return from the include function something that isn't the object the mapped transformer expects.

Example code:

class GroupTransformer extends Transformer
{
    /**
     * A list of autoloaded default relations.
     *
     * @var array
     */
    protected $load = [
        'members' => UserTransformer::class,
    ];

    /**
     * Transform the model.
     *
     * @param \App\Group $group
     * @return array
     */
    public function transform(Group $group): array
    {
        return [
             // stuff
        ];
    }

    /**
     * Include group members
     *
     * @param \App\Group $group
     * @return array
     */
    public function includeMembers(Group $group)
    {
        return $group->members->map(function (User $member) {
            return array_add(transformation($member)->transform(), 'pivot', [
                'admin' => $member->pivot->admin,
                'created_at' => $member->pivot->created_at,
            ]);
        });
    }
}

As you can see, I need to use the includeMembers until there's a feature like whenIncludedBy we discussed some time ago.
The error I get is Argument 1 passed to App\Transformers\UserTransformer::transform() must be an instance of App\User, array given and I'm pretty sure it's because the includeMembers result (which is an array) is given as a parameter for the transformation with the UserTransformer mapping.
Even so, I don't understand why it is trying to transform it after the includeMembers is used...

I think I don't actually need to eager load members in this case so I can just avoid doing it (removing the mapping) and everything works as expected, but maybe it can happen that someone wants to both eager-load data and apply a custom function.

Is this expected behaviour? If yes, is it possible to add a note on the documentation saying to avoid putting a mapping and an include function on the same relation?

@flugg
Copy link
Owner

flugg commented Feb 2, 2018

The “include” methods are supposed to return the untransformed data. Fractal also requires this data to be wrapped in a resource, but this package will wrap it in a resource for you. After obtaining a resource Fractal will then resolve the transformer from the resource and transform the related data.

So in your case you actually end up attempting to transform the data twice. If you remove the transformer mapping it should use the fallback transformer the second transform, which doesn’t complain about it being an array and will just output the data untouched. However, keep in mind this isn’t really by the book and we should look into supporting a more robust way to handle your scenario like the whenIncludedBy option.

@flugg
Copy link
Owner

flugg commented Feb 6, 2018

I think maybe we should close this and the issue for pivots and open a new issue for Conditional Attributes as I'm pretty sure that's the direction I want to go with this

@IlCallo
Copy link
Contributor Author

IlCallo commented Feb 6, 2018

I agree

@flugg
Copy link
Owner

flugg commented Feb 7, 2018

Closing in favor of #109

@flugg flugg closed this as completed Feb 7, 2018
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

2 participants