Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ufodisko's avatar

Using Gate auth to check if a user is a moderator - getting Missing argument 3 for Illuminate\Auth\AuthServiceProvider

I use the Gate facade to check if a user is the post owner or the creator of a subreddit before allowing him to edit or even view the edit link on the view.

However, I'm having trouble check if a user is a moderator of a given subreddit. The logged in user has already been placed as a moderator for that subreddit but whenever I visit it, I get the following error

ErrorException in AuthServiceProvider.php line 18:

Missing argument 3 for Illuminate\Auth\AuthServiceProvider::Illuminate\Auth{closure}() (View: C:\xampp\htdocs\reddit\resources\views\partials\post.blade.php) (View: C:\xampp\htdocs\reddit\resources\views\partials\post.blade.php)

Here are my tables

    users: id, name, email... 
    posts: id, user_id, subreddit_id...
    subreddits: id, name, user_id (to designate the owner of the sub)
    moderators: id, user_id, subreddit_id...

Here's the Gate implemention inside AuthServiceProvider

    $gate->define('update-post', function ($user, $post, $subreddit) {
            // Check if user is subreddit owner
            if ($user->id === $post->subreddit->user->id) {
                return true;
            }

            // Check if user is the post author
            if ($user->id === $post->user_id) {
                return true;
            }
            // this is where I'm having trouble
            if($user->id === $subreddit->moderator->user_id) {
                return true;
            }

            return false;
    });

Then on post.blade.php I check if the user has access before showing him the html markup and this is where the page breaks.

    @can('update-post', $post, $subreddit)
        <a href="{{ action('PostsController@edit', [$post->id]) }}">Edit</a>
    @endcan
0 likes
25 replies
mstnorris's avatar

Check what the value of your variables are as it appears that it is missing the third argument, namely $subreddit.

Also, what happens when you remove the [] around the $post->id?

@can('update-post', $post, $subreddit)
        <a href="{{ action('PostsController@edit', $post->id) }}">Edit</a>
    @endcan
ufodisko's avatar

@mstnorris I think the problem was I need to pass $post and $subreddit in an array like so [$post, $subreddit]

Now I'm getting a different error

ErrorException in AuthServiceProvider.php line 29:

Trying to get property of non-object (View: C:\xampp\htdocs\reddit\resources\views\partials\post.blade.php) (View: C:\xampp\htdocs\reddit\resources\views\partials\post.blade.php)

It's referring to $subreddit->moderator->user_id but how else can I access the moderator's user_id?

1 like
mstnorris's avatar

Are you importing Gate properly at the top?

use Gate;

Have you set up the relevant relationship on the Subreddit and Moderator models? If you have, then that Subreddit doesn't have a Moderator.

Try:

$subreddit->moderator()->user_id
ufodisko's avatar

Here are my relations for Subreddit

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

    public function posts() {
        return $this->hasMany('App\Post');
    }

    public function moderators() {
        return $this->belongsToMany('App\User','moderators');
    }

And Moderator

public function subreddit() {
        return $this->belongsTo('App\Subreddit');
    }

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

    public function posts() {
        return $this->belongsTo('App\Post');
    }

I'm positive that at least 1 moderator exists for that subreddit, the record is in the db.

ufodisko's avatar

@mstnorris Yes I am using Gate at the top. and using $subreddit->moderators()->user_id gives

Undefined property: Illuminate\Database\Eloquent\Relations\BelongsToMany::$user_id (View: C:\xampp\htdocs\reddit\resources\views\partials\post.blade.php) (View: C:\xampp\htdocs\reddit\resources\views\partials\post.blade.php)

moderators() with s

mstnorris's avatar

You don't have a moderator relationship on you Subreddit model. That's why you're having trouble as you're calling it like a one-to-many relationship, yet you've set up a many-to-many.

mstnorris's avatar

That depends on what you need.

Explain what the use case is between a subreddit and moderators? Does asubreddit have one or many moderators?

ufodisko's avatar

@mstnorris

Subreddits have many moderators, and many posts.

Here I am simply checking if the logged in user_id is the same as user_id of moderators table related to the subreddit the post belongs to.

mstnorris's avatar

@ufodisko Before we go any further, you're relationships aren't right. Take a look at them and the documentation to help you out. Before we continue, this is undoubtedly causing issues.

hasOne <=> belongsTo

hasMany <=> belongsTo

belongsToMany <=> belongsToMany
ufodisko's avatar

@mstnorris can you be more specific as to where I got the relationships wrong? Because everything else works. I've read the documentation and followed the instructions.

Here are all 3 models and their relations.

Subreddit Model

class Subreddit extends Model
{
    protected $fillable = [
        'name',
        'description'
    ];

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

    public function posts() {
        return $this->hasMany('App\Post');
    }

    public function moderators() {
        return $this->hasMany('App\User', 'moderators');
    }
}

Post Model

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $fillable = [
        'title',
        'link',
        'text',
        'image',
        'subreddit_id'
    ];

    // this was preventing the Votes relation from working..
    //    protected $primaryKey = 'subreddit_id';

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

    public function subreddit() {
        return $this->belongsTo('App\Subreddit');
    }

    public function votes() {
        return $this->hasMany('App\Vote');
    }

    public function moderators() {
        return $this->hasMany('App\Moderator');
    }
}

Moderator Model

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Moderator extends Model
{
    protected $table = 'moderators';

    protected $fillable = ['user_id', 'subreddit_id'];

    public function subreddit() {
        return $this->belongsTo('App\Subreddit');
    }

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

    public function posts() {
        return $this->belongsTo('App\Post');
    }
}
mstnorris's avatar

Can a Moderator, moderate more than one Subreddit?

ufodisko's avatar

@mstnorris yes, he can.

And a post belongs to only one subreddit and has many moderators as well.

mstnorris's avatar

In that case you need a Many-to-Many relationship between Subreddits and Moderators.

Subreddit Model

public function moderators() {
    return $this->belongsToMany('App\Moderator');
}

Moderator Model

public function subreddits() {
    return $this->belongsToMany('App\Subreddit');
}

Also, please show your migrations too as that will be affected by the change in relationships. As mentioned above you'll need to create a moderator_subreddit pivot table.

ufodisko's avatar

@mstnorris still getting the same error

Undefined property: Illuminate\Database\Eloquent\Relations\BelongsToMany::$user_id (View: C:\xampp\htdocs\reddit\resources\views\partials\post.blade.php) (View: C:\xampp\htdocs\reddit\resources\views\partials\post.blade.php)

Please note that I am also linking App\User in the Subreddit Model

public function moderators() {
        return $this->belongsToMany('App\User', 'moderators');
}
mstnorris's avatar

@ufodisko I suggest that you think about how your models relate to one another. If it helps, use http://laravelsd.com as you'll be able to visualise it clearly. You can also export your database migrations too.

Going back to your original question, were you ever passing three arguments?

ufodisko's avatar

@mstnorris What do you mean by was I ever passing 3 arguments? I don't understand the question.

I just tried something, changed the relation on Subreddit Model to belongsTo

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

I am getting a different error now

Undefined property: App\Subreddit::$moderators (View: C:\xampp\htdocs\reddit\resources\views\partials\post.blade.php) (View: C:\xampp\htdocs\reddit\resources\views\partials\post.blade.php)

mstnorris's avatar

@ufodisko I've cloned it, set up the database (I can't seed it as you don't have a PermissionsTableSeeder), what should I see.

Please explain your app to me and I'll try my best to help.

ufodisko's avatar

@mstnorris First you need to open AuthServiceProvider and add the following method.

public function boot(GateContract $gate)
    {
        parent::registerPolicies($gate);

        $gate->define('update-post', function ($user, $post, $subreddit) {
            // Check if user is subreddit owner
            if ($user->id === $post->subreddit->user->id) {
                return true;
            }

            // Check if user is the post author
            if ($user->id === $post->user_id) {
                return true;
            }

            if ($user->id === $subreddit->moderators->user_id) {
                return true;
            }

            return false;
        });

        $gate->define('update-sub', function($user, $subreddit) {
            if($user->id === $subreddit->user->id) {
                return true;
            }

            return false;
        });
    }

After that you need to

  • Register for an account
  • Create New Subreddit (create sub link)
  • Create New Post (create post link)
  • Assign A mod to your sub (My subreddit link in the user menu)

And that's it, you don't need to seed. But I think you'll get an error once you run it due to the issue we're trying to solve.

ufodisko's avatar

@mstnorris Oh and be sure to change the ajax requests url to relative urls on the views. I forgot to change them before committing.

mstnorris's avatar

The project isn't loading for me, not even the homepage.

It's late here. I'll take a look in the morning.

Dario's avatar

You were just required to add the $user model. @can('update-post', $user, $post, $subreddit) @edit', [$post->id]) }}">Edit @endcan

Please or to participate in this conversation.