spatie / laravel-menu

Html menu generator for Laravel
https://freek.dev/414-a-modern-package-to-generate-html-menus
MIT License
926 stars 82 forks source link

[L5.7] setActiveFromRequest() throws Exception after 'php artisan config:cache' #81

Closed axit-joost closed 6 years ago

axit-joost commented 6 years ago

Hi,

Today I observed that after running php artisan optimize, the method setActiveFromRequest() will throw an ErrorException: array_merge(): Argument #1 is not an array.

Using Laravel Telescope, I found that it is the spatie/url package, method fromString that does that array_merge(), using a parse_url() function that ends up not returning an array.

After running php artisan optimize:clear the exception goes away and everything is back to normal.

Through some trial and error, I was able to track it down to php artisan config:cache that is causing the interference.

I am currently running the following versions:

spatie/laravel-menu                 3.2.1           Html menu generator for Laravel
spatie/menu                         2.8.0           Html menu generator
spatie/url                          1.3.0           Parse, build and manipulate URL's

I believe those are the current releases.

I am not sure if this is the right place for this issue, but since spatie/url was installed as a dependency of spatie/menu and ultimately spatie/laravel-menu, I figured that this was a place to start.

I am also not sure why that config:cache is interfering with the urls?

Anyway, if you need more information, let me know.

sebastiandedeyne commented 6 years ago

Could you share afull stack trace of the error?

axit-joost commented 6 years ago

Sure, here you go:

[2018-11-21 15:50:31] local.ERROR: array_merge(): Argument #1 is not an array (View: /Users/axit-joost/Code/new-app/resources/views/vendor/adminlte/layouts/partials/sidebar.blade.php) (View: /Users/axit-joost/Code/new-app/resources/views/vendor/adminlte/layouts/partials/sidebar.blade.php) (View: /Users/axit-joost/Code/new-app/resources/views/vendor/adminlte/layouts/partials/sidebar.blade.php) (View: /Users/axit-joost/Code/new-app/resources/views/vendor/adminlte/layouts/partials/sidebar.blade.php) {"userId":1,"email":"j.jacobs@xit.nl","exception":"[object] (ErrorException(code: 0): array_merge(): Argument #1 is not an array (View: /Users/axit-joost/Code/new-app/resources/views/vendor/adminlte/layouts/partials/sidebar.blade.php) (View: /Users/axit-joost/Code/new-app/resources/views/vendor/adminlte/layouts/partials/sidebar.blade.php) (View: /Users/axit-joost/Code/new-app/resources/views/vendor/adminlte/layouts/partials/sidebar.blade.php) (View: /Users/axit-joost/Code/new-app/resources/views/vendor/adminlte/layouts/partials/sidebar.blade.php) at /Users/axit-joost/code/new-app/vendor/spatie/url/src/Url.php:51, ErrorException(code: 0): array_merge(): Argument #1 is not an array (View: /Users/axit-joost/Code/new-app/resources/views/vendor/adminlte/layouts/partials/sidebar.blade.php) (View: /Users/axit-joost/Code/new-app/resources/views/vendor/adminlte/layouts/partials/sidebar.blade.php) (View: /Users/axit-joost/Code/new-app/resources/views/vendor/adminlte/layouts/partials/sidebar.blade.php) at /Users/axit-joost/code/new-app/vendor/spatie/url/src/Url.php:51, ErrorException(code: 0): array_merge(): Argument #1 is not an array (View: /Users/axit-joost/Code/new-app/resources/views/vendor/adminlte/layouts/partials/sidebar.blade.php) (View: /Users/axit-joost/Code/new-app/resources/views/vendor/adminlte/layouts/partials/sidebar.blade.php) at /Users/axit-joost/code/new-app/vendor/spatie/url/src/Url.php:51, ErrorException(code: 0): array_merge(): Argument #1 is not an array (View: /Users/axit-joost/Code/new-app/resources/views/vendor/adminlte/layouts/partials/sidebar.blade.php) at /Users/axit-joost/code/new-app/vendor/spatie/url/src/Url.php:51, ErrorException(code: 0): array_merge(): Argument #1 is not an array at /Users/axit-joost/code/new-app/vendor/spatie/url/src/Url.php:51)
[stacktrace]
#0 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/View/Engines/PhpEngine.php(45): Illuminate\\View\\Engines\\CompilerEngine->handleViewException(Object(ErrorException), 1)
#1 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/View/Engines/CompilerEngine.php(59): Illuminate\\View\\Engines\\PhpEngine->evaluatePath('/Users/axit-joo...', Array)
#2 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/View/View.php(142): Illuminate\\View\\Engines\\CompilerEngine->get('/Users/axit-joo...', Array)
#3 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/View/View.php(125): Illuminate\\View\\View->getContents()
#4 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/View/View.php(90): Illuminate\\View\\View->renderContents()
#5 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Http/Response.php(42): Illuminate\\View\\View->render()
#6 /Users/axit-joost/code/new-app/vendor/symfony/http-foundation/Response.php(202): Illuminate\\Http\\Response->setContent(Object(Illuminate\\View\\View))
#7 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Router.php(747): Symfony\\Component\\HttpFoundation\\Response->__construct(Object(Illuminate\\View\\View))
#8 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Router.php(719): Illuminate\\Routing\\Router::toResponse(Object(Illuminate\\Http\\Request), Object(Illuminate\\View\\View))
#9 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Router.php(679): Illuminate\\Routing\\Router->prepareResponse(Object(Illuminate\\Http\\Request), Object(Illuminate\\View\\View))
#10 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(30): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#11 /Users/axit-joost/code/new-app/vendor/backpack/crud/src/app/Http/Controllers/CrudController.php(44): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#12 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(133): Backpack\\CRUD\\app\\Http\\Controllers\\CrudController->Backpack\\CRUD\\app\\Http\\Controllers\\{closure}(Object(Illuminate\\Http\\Request), Object(Closure))
#13 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#14 /Users/axit-joost/code/new-app/vendor/backpack/base/src/app/Http/Middleware/CheckIfAdmin.php(27): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#15 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Backpack\\Base\\app\\Http\\Middleware\\CheckIfAdmin->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#16 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#17 /Users/axit-joost/code/new-app/vendor/acacha/user/src/Http/Middleware/GuestUser.php(24): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#18 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Acacha\\User\\Http\\Middleware\\GuestUser->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#19 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#20 /Users/axit-joost/code/new-app/vendor/laravel/passport/src/Http/Middleware/CreateFreshApiToken.php(50): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#21 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Laravel\\Passport\\Http\\Middleware\\CreateFreshApiToken->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#22 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#23 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(41): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#24 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#25 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#26 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(75): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#27 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#28 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#29 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#30 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#31 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#32 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(63): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#33 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Session\\Middleware\\StartSession->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#34 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#35 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#36 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#37 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#38 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(66): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#39 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#40 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#41 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(104): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#42 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Router.php(681): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))
#43 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Router.php(656): Illuminate\\Routing\\Router->runRouteWithinStack(Object(Illuminate\\Routing\\Route), Object(Illuminate\\Http\\Request))
#44 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Router.php(622): Illuminate\\Routing\\Router->runRoute(Object(Illuminate\\Http\\Request), Object(Illuminate\\Routing\\Route))
#45 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Router.php(611): Illuminate\\Routing\\Router->dispatchToRoute(Object(Illuminate\\Http\\Request))
#46 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(176): Illuminate\\Routing\\Router->dispatch(Object(Illuminate\\Http\\Request))
#47 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(30): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}(Object(Illuminate\\Http\\Request))
#48 /Users/axit-joost/code/new-app/vendor/fideloper/proxy/src/TrustProxies.php(57): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#49 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Fideloper\\Proxy\\TrustProxies->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#50 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#51 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(31): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#52 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#53 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#54 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(31): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#55 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#56 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#57 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#58 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#59 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#60 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php(62): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#61 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#62 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#63 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(104): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#64 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(151): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))
#65 /Users/axit-joost/code/new-app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(116): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter(Object(Illuminate\\Http\\Request))
#66 /Users/axit-joost/code/new-app/public/index.php(55): Illuminate\\Foundation\\Http\\Kernel->handle(Object(Illuminate\\Http\\Request))
#67 /Users/axit-joost/.composer/vendor/laravel/valet/server.php(147): require('/Users/axit-joo...')
#68 {main}
"}

afbeelding

The string that arrives in Url::fromString is ":8025" which is weird, since that is the port of my local mailhog web interface.

Performing an php artisan optimize:clear and running the different *:cache commands manually, albeit with the ommission of config:cache, yields a working situation.

Digging a bit further, it seems that the data is already wrong in Activatable:

afbeelding

$this->url is already ":8025" there.

axit-joost commented 6 years ago

Heh,

Think I found something:

                ->link(
                    str_replace('https://', 'http://', env('APP_URL')) . ':8025',
                    '<i class="fa fa-fw fa-paper-plane-o"></i> Mailhog'
                )

Since mailhog is running non-SSL on my local dev machine, and since I have a link in the menu tree, I used a simple str_replace to rewrite https:// to http:// in the APP_URL in my .env. That value, it seems, yields null when running php artisan optimize or php artisan config:cache.

When I go and check the bootstrap/cache/config.php I do see app['url'] is set, so perhaps something is awry with that env() helper.

Your take?

axit-joost commented 6 years ago

Sigh. My bad.

https://laravel.com/docs/5.7/configuration#configuration-caching

A package has chosen to have the menu.php in the config/ folder. I assumed that it was safe to call env() there - as per the documentation of Laravel - however, the config:cache will only work for true configuration files that return [ 'key' => 'value'].

menu.php is simply a PHP file that uses spatie/menu to construct the menu using Macros. So when running config:cache, the 'value' for the configuration key menu is 1.

The sidebar menu partial will call Menu, which delegates to that menu.php in the config directory, which is calling env(), which returns null, as per the Laravel documentation.

Hence the error.

So this is not an issue with anything Spatie related, it is simply a bad design decision by a package vendor.

Thanks anyway for responding.