Framework: URL::defaults() does not work correctly with error 404

Created on 17 May 2020  路  13Comments  路  Source: laravel/framework

  • Laravel Version: 7.11.0
  • PHP Version: 7.4.6

Description:

When installing URL::defaults(['locale' => 'en']);//example in middleware and when returning 404 error I get the error:

Missing required parameters for [Route: front.index] [URI: {locale}]. (View: resources/views/components/menu.blade.php) 

If the record is found, then everything works correctly.

web.php

Route::prefix('{locale}')
    ->where(['locale' => '[a-zA-Z]{2}'])
    ->group(static function () {
        Route::get('/', 'HomeController@index')->name('index');
    });

```php
app/Http/Kernel.php

protected $middleware = [
...
LocaleMiddleware::class,
];

```php
\App\Http\Middleware\LocaleMiddleware

public function handle($request, Closure $next)
{
    URL::defaults(['locale' => 'en']);
    return $next($request);
}

```php
app/Models/News.php

public function resolveRouteBinding($value, $field = null): ?Model
{
return $this->whereJsonContains('slug->en', $value)->firstOrFail();
}

I tried to find what the problem was and just found a new instance of the class `RouteUrlGenerator` is being created in `vendor/laravel/framework/src/Illuminate/Routing/UrlGenerator.php:589` , but I did not find how to solve the problem to make RP

PS if add middlware to Route group - same result
```php
web.php

Route::prefix('{locale}')
    ->where(['locale' => '[a-zA-Z]{2}'])
    ->middleware(['locale'])
    ->group(static function () {
        Route::get('/', 'HomeController@index')->name('index');
    });
needs more info

Most helpful comment

Got it and found the bug. Patched in next patch release (tomorrow).

All 13 comments

Need a clearer explanation of how to recreate.

https://github.com/Hunternnm/url-defaults-error - example repo. https://github.com/Hunternnm/url-defaults-error/commit/72bba3c8bd2ef98265ddf9c26ae63fb0f725616a - commit with needed changes

Steps:

  1. Clone repo
  2. Copy .env.example to .env
  3. docker-compose up && php artisan migrate --seed
  4. php artisan serve
  5. Go to http://127.0.0.1:8000/en/ and see 2 "locale" dump (global middleware and for route group) and see right link to http://127.0.0.1:8000/en/ after Laravel
  6. Go to http://127.0.0.1:8000/en/news/my-slug and see 2 "locale" dump (work correctly)
  7. Go to http://127.0.0.1:8000/en/news/bad-slug and see Missing required parameters for [Route: front.index] [URI: {locale}]. (View: url-defaults-error/resources/views/errors/404.blade.php)
  8. Remove middleware locale in web.php. Global middleware execute, but not set defaults

I don't want an example repo. I want copy and pasteable instructions in this thread. Thanks.

Hmm, now I鈥檒l try to describe (though in the commit above it鈥檚 more obvious)

  1. Create LocaleMiddleware with content:
    public function handle($request, Closure $next)
    {
        URL::defaults(['locale' => 'en']);
        optional($request->route())->forgetParameter('locale');
        return $next($request);
    }

and add to global middleware and create named locale middleware

    protected $middleware = [
        \App\Http\Middleware\TrustProxies::class,
        \Fruitcake\Cors\HandleCors::class,
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        LocaleMiddleware::class,
    ];
  1. Create News model with slug json row. Add record:
        \App\News::insert([
            'slug' => json_encode([
                'en' => 'my-slug'
            ])
        ]);

In model add:

    protected $casts = [
        'slug' => 'array',
    ];

    public function resolveRouteBinding($value, $field = null): ?Model
    {
        return $this->whereJsonContains('slug->en', $value)->firstOrFail();
    }
  1. Create resource NewsController and add to web.php:
Route::prefix('{locale}')
    ->where(['locale' => '[a-zA-Z]{2}'])
    ->name('front.')
    ->middleware(['locale'])
    ->group(static function () {
        Route::get('/', static function () {
            return view('welcome');
        })->name('index');
        Route::resource('news', 'NewsController');
    });
  1. Create view welcome with content
<a href="{{ route('front.index') }}">Link to home with lang</a>
  1. Create custom resources/views/errors/404.blade.php with same content

  2. Start application and open http://127.0.0.1:8000/en/ . Content is right link

  3. Open http://127.0.0.1:8000/en/news/my-slug - also right link

  4. Open http://127.0.0.1:8000/en/news/bad-slug and see Missing required parameters for [Route: front.index] [URI: {locale}]. (View: url-defaults-error/resources/views/errors/404.blade.php)

  5. Remove middleware locale in web.php. Global middleware execute, but not set defaults, see same error

@taylorotwell The commit is small (only the changes that I wrote above), it may be more convenient to watch it. thank https://github.com/Hunternnm/url-defaults-error/commit/72bba3c8bd2ef98265ddf9c26ae63fb0f725616a

on /bad-slug

  • it returns 404 as expected with both the default and custom 404 page

also other links works as expected!

@sergeByishimo Does the version of Laravel and php match? Did you copy my repository or repeat it yourself? Before writing here, I asked 3 people to repeat this - everyone has a mistake like mine. Error only if create custom 404 error

No I didn't copy your repository but yes my

  • php version is PHP 7.4.6 (cli)
  • laravel version 7.11.0

maybe i can put up a repo and let you see for yourself!!

Screenshot from 2020-05-18 18-47-10

Screenshot from 2020-05-18 18-44-46

Screenshot from 2020-05-18 18-45-20

@sergeByishimo please insert in custom 404 this code

<a href="{{ route('front.index') }}">Link to home with lang</a>

if echo only text - work as expected, but if you need a value that I set in the middleware, I get an error

Aaah i get the error now!

so what you are trying to say is that when you put this link

<a href="{{ route('front.index') }}">Link to home with lang</a>

in a welcome blade it works, but when you put it in a custom 404 page it doesn't work!

I dont know if its me, but i didn't get it first! but it is sure giving the above error!

let me trace it back and see if i can know why, i'll let you know

On the 404 error page, I use the site header, the same as everywhere else, to help the user navigate to other pages. This link is an example, I have a bit more of them - to categories and other pages that use the locale.

My searches led only to what I indicated above: a new instance of the class RouteUrlGenerator is being created in vendor/laravel/framework/src/Illuminate/Routing/UrlGenerator.php:589

Thanks for the help and attention to my mistake. You're cool!

came back to say that it may definitely be a bug! because when you add locale parameter like this it works

<a href="{{ route('front.index', ['locale' => 'en']) }}">Link to home with lang</a>

and me too i was lead to find that because it creates a new instance of the RouteUrlGenerator class it becomes impossible for the UrlGenerator to recognize the defaults.

Hope we get feedback! Thanks to you too!

better title to make it more understandable

Route helper does not recognize URL::defaults() in a custom 404 page

Got it and found the bug. Patched in next patch release (tomorrow).

Was this page helpful?
0 / 5 - 0 ratings