framework: Using url helper in config files breaks Artisan

Implementing Socialite, I decided to use the url() helper to generate my absolute redirect URLs, for example:

return [
    'facebook' => [
        'redirect' => url('auth/redirect/facebook'),
    ],
];

Although the HTTP application continues to work normally, I’ve noticed that any subsequent Artisan commands fail with the following RuntimeException:

Error Output: PHP Catchable fatal error: Argument 2 passed to Illuminate\Routing\UrlGenerator::__construct() must be an instance of Illuminate\Http\Request, null given, called in /home/vagrant/Sites/southsidewrestling.co.uk/vendor/laravel/framework/src/Illuminate/Routing/RoutingServiceProvider.php on line 56 and defined in /home/vagrant/Sites/southsidewrestling.co.uk/vendor/laravel/framework/src/Illuminate/Routing/UrlGenerator.php on line 81

This also occurs if I try to resolve the helper in its “longhand” form:

return [
    'facebook' => [
        'redirect' => app('url')->to('auth/redirect/facebook'),
    ],
];

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 6
  • Comments: 20 (12 by maintainers)

Most upvoted comments

Nope.

@grahamcampbell I want my OAuth redirect URLs to be based on my app’s current domain. That seems a pretty standard use case to me?

Having been bitten by this exact same issue, I’d like to throw my own 2¢ in.

I think having to explicitly define an application’s URL in the .env introduces unnecessary extra onus on users of the framework, and therefore greater opportunity for errors. Following your advice, my application’s base URL could be three different values defined in three different places:

  • The URL Laravel detected from the request
  • APP_URL in my .env file
  • The url defined in config/app.php (Using env('APP_URL') can fix this piece, but that’s aside from my point)

Clearly the detected value should take precedence, and it does under most circumstances. But by explicitly using APP_URL in services.php I have created an instance where, regardless of what URL my application is actually running under, a hard coded value will be used instead. Granted, in this example if my application’s URL is different than what the OAuth provider is configured to expect I will be getting an error no matter what. But the error should be relating to URL mismatch, not because I’m being redirected to a domain name different than my application’s.

Furthermore, looking through the documentation on helper functions I see url(), route(), and env() all defined as peers. How am I to know that I can use one of these in some contexts but not the others? And why should all of them work when the request is web based, but not from the command line? Yes artisan doesn’t handle web based requests, but from reading the comments in config/app.php, that’s why there is that url key in there.

Finally, a bit of a philosophical question that is certainly beyond the scope of this topic but makes me curious. I absolutely agree that configuration files should not be dynamic. But if that’s the case, why are these config files PHP, and not something like Yaml or JSON? Why even introduce the opportunity for extra syntax and logic in these files in the first place?

</rant>

All that aside, @GrahamCampbell, I do appreciate your help in explaining a workaround. I just disagree on whether that workaround should be necessary. Thanks!

Following @crynobone, I implemented this in an app today by setting the value in my ConfigServiceProvider as follows:

public function register()
{
    config([
        'services.facebook.redirect' => url('auth/callback/facebook'),
    ]);
}

Configs are loaded really early and probably not meant to use anything from the framework except Dotenv.

@GrahamCampbell

Take a look at how I do this: https://github.com/StyleCI/StyleCI/blob/master/config/services.php#L50.

The link is broken. Could you provide an alternative link for the example? Thank you in advance.

Yeh, you can’t do that. You should only use plain strings, etc in the config. If you config is dynamic, you’re missusing it.

@shahrukh4 That approach doesn’t really work on staging/production servers though where you can’t edit code, does it?

@amitshahc This has long been solved. Relative URLs in config files will be expanded to the absolute URL.

From https://laravel.com/docs/5.8/socialite#configuration:

If the redirect option contains a relative path, it will automatically be resolved to a fully qualified URL.

yeh but i am using 5.5 which has this issue. so for those using earlier versions can have this solution.

I solved this by this: Put all dynamic values into the .env `

‘google’ => [ ‘client_id’ => env(‘AUTH_GOOGLE_CLIENT_ID’), ‘client_secret’ => env(‘AUTH_GOOGLE_CLIENT_SECRET’), ‘redirect’ => env(‘APP_URL’).‘/auth/google/callback’, ]`

I figured out the problem, when you are running any artisan command you should avoid using helper functions in any of your config files. Just comment those and try to run artisan command after running that uncomment your config files.

//in config/'any_file.php'
return [
   'name'	=> 'Larvel',
   'url'	=> url('/')
];

//just change and uncomment url() helper
return [
   'name'	=> 'Larvel',
    //'url'	=> url('/)
];