Vilfago's avatar
Level 20

Laravel 5.7 - Policy issue

Hi everyone,

I updated from 5.6 to 5.7, and get a "ReflectionFunction::__construct() expects parameter 1 to be string, array given" error. I'm unable to find which change cause this, and how to solve it. Any help will be appreciated.

Context : I built a forum with many categories (named channel in Laracasts), and create policies to allow user to CRUD posts on each category depending on their roles. In order to manage access for guest in the same way (with a list of authorizations and prohibitions), I use several middlewares :

  • check if the user is authenticated
  • if not, log the guest in the "Guest" guard, and change the default guard to guest
  • used the standard Authorize middleware ( \Illuminate\Auth\Middleware\Authorize::class)
  • update the default guard to "web" in the last middleware.

Result : When a user is logged, there is no issue, everything worked fine. When a guest is on the website, Àuthorize` middleware work great, and the guest can see only category/channel that is has the right to see.

The error come from a line in Blade Template :

@can('create', $category) 

Which is the same as

<?php if (app(\Illuminate\Contracts\Auth\Access\Gate::class)->check('create', $category)): ?>

And thus, I have the following steps until the error (all in /Illuminate/Auth/Access/Gate.php) :

     * Determine if all of the given abilities should be granted for the current user.
     *
     * @param  iterable|string  $abilities
     * @param  array|mixed  $arguments
     * @return bool
     */
    public function check($abilities, $arguments = [])
    {
        return collect($abilities)->every(function ($ability) use ($arguments) {
            try {
                return (bool) $this->raw($ability, $arguments); // <- Line 258 on which Arguments below are supplied
            } catch (AuthorizationException $e) {
                return false;
            }
        });
    }

 Arguments
  1.  "create"
  2. array:1 [0 => ForumCategory {#917}  ]
        // After calling the authorization callback, we will call the "after" callbacks
        // that are registered with the Gate, which allows a developer to do logging
        // if that is required for this application. Then we'll return the result.
        return $this->callAfterCallbacks(
            $user, $ability, $arguments, $result // <- Line 327 on which Arguments below are supplied
        );

Arguments
1. null
2. "create"
3.  array:1 [0 => ForumCategory {#917} ]
4. null
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @param  string  $ability
     * @param  array  $arguments
     * @param  bool  $result
     * @return void
     */
    protected function callAfterCallbacks($user, $ability, array $arguments, $result)
    {
        foreach ($this->afterCallbacks as $after) {
            if (! $this->canBeCalledWithUser($user, $after)) {  // <- Line 454 on which Arguments below are supplied
                continue;
            }
 
            $afterResult = $after($user, $ability, $result, $arguments);
 
            $result = $result ?? $afterResult;
        }
 
        return $result;
    }

 Arguments
1. null
2. array:2 [ 
    0 => GateCollector {#658}, 
    1 => "addCheck"
]
    protected function canBeCalledWithUser($user, $class, $method = null)
    {
        if (! is_null($user)) {
            return true;
        }
 
        if (! is_null($method)) {
            return $this->methodAllowsGuests($class, $method); 
        }
 
        return $this->callbackAllowsGuests($class); // <- Line 349 on which Arguments below are supplied
    }

 Arguments
1.  array:2 [ 
    0 => GateCollector {#658}, 
    1 => "addCheck"
]
    /**
     * Determine if the callback allows guests.
     *
     * @param  callable  $callback
     * @param  array  $arguments
     * @return bool
     */
    protected function callbackAllowsGuests($callback)
    {
        $parameters = (new ReflectionFunction($callback))->getParameters();  // <- Line 387 on which Arguments below are supplied
 
        return isset($parameters[0]) && $this->parameterAllowsGuests($parameters[0]);
    }

 Arguments
1.  array:2 [ 
    0 => GateCollector {#658}, 
    1 => "addCheck"
]

And thus, the error ReflectionFunction::__construct() expects parameter 1 to be string, array given.

I don't know what I have to change to don't have this array provided by the framework...

Thank you for any help !

Vilfago

0 likes
3 replies
Vilfago's avatar
Vilfago
OP
Best Answer
Level 20

The issue come from DebugBar 3.x

Issue solved in disabling debugbar or setting gate collector to false in debugbar's config.

2 likes

Please or to participate in this conversation.