How to fix call to undefined function can() in Laravel Spatie

A common error encountered when implementing the Laravel Spatie package. Using it in the initial tries, you might come up with a call to undefined function can() error.

Solutions for undefined function can()

The most common reason for this error is, we forget to implement Authorizable on User Model.

The common reason behind this error is when you forget to implement Authorizable on a User Model.

and then used the trait: 

Solution 01

Lets say, we want to register permissions for users and want to check if logged in user has specific permission. For example, user 10, has permissions to edit an article. To check permission we use Auth::user()->can(‘edit articles’)

Suppose you want to register some permissions for multiple users and need to confirm the a specific logged in user has a permission applied. For example, user Alice, has the permission to update a record. To check this, we normally use Auth::user()->can(‘update articles’).

The code below shows the PermissionMiddleware, where we check a user’s permission. All permissions should be defined in this user model.

class PermissionMiddleware
    public function handle($request, Closure $next, $permission)
        if (app('auth')->guest()) {
            throw UnauthorizedException::notLoggedIn();

        $permissions = is_array($permission)
            ? $permission
            : explode('|', $permission);

        foreach ($permissions as $permission) {
            if (app('auth')->user()->can($permission)) {
                return $next($request);

        throw UnauthorizedException::forPermissions($permissions);

You will add Authorizable to this model to solve the undefined function can() issue.

use Illuminate\Contracts\Auth\Access\Authorizable;
use Laravel\Lumen\Auth\Authorizable;

Solution 02

The solution above works while using a User model. However, while using a custom user model, we should create a UserView Model as shown below.


namespace App\Models;

use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Foundation\Auth\Access\Authorizable;             // <-- add import
use Spatie\Permission\Traits\HasRoles;
use Laravel\Sanctum\HasApiTokens; 

class UserView extends Model implements AuthenticatableContract,
                                        AuthorizableContract    // <-- add interface
    use Authenticatable;
    use Authorizable;                                           // <-- add trait
    use HasFactory;
    use HasRoles;
    use HasApiTokens;

    // ... other code ...

Here you will explicitly call the Authorizable interface and trait. Notice the extracted code lines as shown below.


Leave a Comment