Julian Arya
Julian Arya

Reputation: 13

Laravel authorize() assigns unexpected object to response

I have three Eloquent models for a recipe management application where User has many cookbook, cookbook has many recipes and so on (see below).

To authorize I'm using this policy:

public function view(User $user, Recipes $recipe) {
    return $user->id === $recipe->cookbook->user_id;
}

Here is the controller:

public function show($id) {
    $recipe = Recipes::find($id);
    $this->authorize('view', $recipe);

    return $recipe;
}

Testing this works fine, however I'm getting extra information in my response.

Unexpected Result

Expected Result

The response somehow gets assigned an extra object cookbook. After print testing the problem seems to lie on the line $recipe->cookbook->user_id; where if removed the result came to be as expected.

Am I overlooking something?

Models for Reference

User

class User extends Authenticatable
{
    use HasFactory, Notifiable, HasApiTokens;

    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    protected $hidden = [
        'password',
        'remember_token',
    ];

    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function cookbooks() {
        return $this->hasMany('App\Models\Cookbook');
    }

    public function recipes() {
        return $this->hasManyThrough('App\Models\Recipes', 'App\Models\Cookbook');
    }
}

Cookbook

class Cookbook extends Model
{
    use HasFactory;

    protected $guarded = ['user_id'];
    protected $fillable = [
        'cookbook_name',
    ];

    protected $casts = [
        'cookbook_shared_user' => 'string'
    ];

    public function user() {
        return $this->belongsTo('App\Models\User');
    }

    public function recipes() {
        return $this->hasMany('App\Models\Recipes');
    }
}

Recipe

class Recipes extends Model
{
    use HasFactory;

    protected $guarded = ['cookbook_id'];
    protected $fillable = [
        'recipe_name',
        'recipe_description',
        'recipe_video_url',
        'recipe_image_url'
    ];

    public function cookbook() {
        return $this->belongsTo('App\Models\Cookbook');
    }
}

Upvotes: 1

Views: 72

Answers (1)

Juan Eizmendi
Juan Eizmendi

Reputation: 1134

You're loading the relationship in your policy, exactly where you said:

$recipe->cookbook

Now in your controller, you can change your return to:

return $recipe->setAppends([]);

That will remove your appends like cookbook.

If you want more control you can use API Resources (Laravel way).

Upvotes: 1

Related Questions