Skip to content

Issues with middleware share and merging props down to controllers #776

@ludo237

Description

@ludo237

PHP package version

2.0.6

Inertia adapter(s) affected (if any)

  • React
  • Vue 3
  • Svelte
  • Not Applicable

Backend stack

Laravel 12.x
PHP 8.4
Bun 1.22
Composer 2.x

Describe the problem

As I stated in this small X thread I have created a middleware called "HandleSeo" which basically does this

<?php

declare(strict_types=1);

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Symfony\Component\HttpFoundation\Response;

final class HandleSeo
{
    public function handle(Request $request, Closure $next): Response
    {
        // Share default meta data before the response is built
        Inertia::share('meta', $this->getDefaultSeoMeta($request));

        return $next($request);
    }

    /**
     * @return array<string, mixed>
     */
    private function getDefaultSeoMeta(Request $request): array
    {
        $appUrl = config('app.url');
        $currentUrl = $request->url();

        return [
            'title' => 'The awesome website,
            'description' => 'The awesome website description'
            ],
        ];
    }
}

This is added inside the middleware web stack in bootstrap/app.php

 ->withMiddleware(function (Middleware $middleware): void {
        $middleware->encryptCookies(except: ['appearance', 'sidebar_state']);

        $middleware
            ->web(
                append: [
                    Sentry::class,
                    HandleInertiaRequests::class,
                    HandleAppearance::class,
                    HandleSeo::class,
                    AddLinkHeadersForPreloadedAssets::class,
                ]);
    })

Now this works, both app.blade.php and Inertia <Head> work fine. The issue is when you want to override the props. For example I'd like to override the LoginController meta tag. I've tried with both merge and deepMerge but with no luck

final class LoginController extends Controller
{
    public function create(Request $request): Response
    {
       // Doesn't work
        return Inertia::render('auth/login', [
            Inertia::merge([
               'meta' => ['title' => 'Login into your awesome website']
            ])
        ]);

// Doesn't work
        return Inertia::render('auth/login', [
            Inertia::deepMerge([
               'meta' => ['title' => 'Login into your awesome website']
            ])
        ]);

// Doesn't work
        return Inertia::render('auth/login', [
            'meta' => Inertia::merge([
              'title' => 'Login into your awesome website'
            ])
        ]);
    }

// Doesn't work
        return Inertia::render('auth/login', [
            'meta' => Inertia::deepMerge([
              'title' => 'Login into your awesome website'
            ])
        ]);
    }
}

The only thing that works is this

final class LoginController extends Controller
{
    public function create(Request $request): Response
    {
       // It works
        return Inertia::render('auth/login', [
            'meta' => array_merge(
                   Inertia::getShared()['meta'],
                   $data,
              )
        ]);
   }
}

So yea the last solution work but I was wondering if there's a but in merge/deepMerge

Steps to reproduce

  • Create a middleware with Inertia::share and some data
  • Try to override the same key in a controller using deepMerge/merge

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions