Skip to content
This repository was archived by the owner on Oct 20, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions app/app/Http/Controllers/FormRedirectController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class FormRedirectController
{
public function show(Request $request)
{
return view('form.redirect');
}

public function submit()
{
return redirect()->route('form.simple')->withErrors([
'name' => 'Custom validation message from redirect',
]);
}
}
11 changes: 11 additions & 0 deletions app/resources/views/form/redirect.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@extends('layout')

@section('content')

FormRedirect

<x-splade-form class="form-simple">
<button type="submit">Submit</button>
</x-splade-form>

@endsection
4 changes: 4 additions & 0 deletions app/routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use App\Http\Controllers\FileFormController;
use App\Http\Controllers\FilepondController;
use App\Http\Controllers\FormComponentsController;
use App\Http\Controllers\FormRedirectController;
use App\Http\Controllers\FormRelationsController;
use App\Http\Controllers\FormViewController;
use App\Http\Controllers\LazyController;
Expand Down Expand Up @@ -92,6 +93,9 @@

Route::view('flash', 'flash')->name('flash');

Route::get('form/redirect', [FormRedirectController::class, 'show'])->name('form.redirect.show');
Route::post('form/redirect', [FormRedirectController::class, 'submit'])->name('form.redirect.submit');

Route::view('form/simple', 'form.simple')->name('form.simple');
Route::post('form/simple', SimpleFormController::class)->name('form.simple.submit');
Route::view('form/emit', 'form.emit')->name('form.emit');
Expand Down
12 changes: 12 additions & 0 deletions app/tests/Browser/FormTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ public function it_can_show_the_errors()
});
}

/** @test */
public function it_can_show_the_errors_from_a_redirect()
{
$this->browse(function (Browser $browser) {
$browser->visit('/form/redirect')
->waitForText('FormRedirect')
->press('Submit')
->waitForText('Custom validation message from redirect')
->assertSee('Custom validation message from redirect');
});
}

/** @test */
public function it_can_submit_data_to_a_get_endpoint()
{
Expand Down
5 changes: 5 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,11 @@ parameters:
count: 1
path: src/Http/SpladeMiddleware.php

-
message: "#^Parameter \\#1 \\$callback of method Illuminate\\\\Support\\\\Collection\\<int\\|string,array\\<Illuminate\\\\Support\\\\ViewErrorBag\\>\\>\\:\\:each\\(\\) expects callable\\(array\\<Illuminate\\\\Support\\\\ViewErrorBag\\>, int\\|string\\)\\: mixed, Closure\\(Illuminate\\\\Support\\\\ViewErrorBag\\)\\: void given\\.$#"
count: 1
path: src/Http/SpladeMiddleware.php

-
message: "#^Parameter \\#1 \\$key of method Illuminate\\\\Contracts\\\\Session\\\\Session\\:\\:get\\(\\) expects string, array\\<TKey of \\(int\\|string\\), TValue\\>\\|bool given\\.$#"
count: 1
Expand Down
47 changes: 38 additions & 9 deletions src/Http/SpladeMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Illuminate\Routing\UrlGenerator;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\MessageBag;
use Illuminate\Support\Str;
use Illuminate\Support\ViewErrorBag;
use Illuminate\Validation\ValidationException;
Expand Down Expand Up @@ -54,8 +55,10 @@ public function handle(Request $request, Closure $next)
$this->splade->resetRehydrateComponentCounter();
$this->splade->resetPersistentLayoutKey();

/** @var Session */
$session = session()->driver();
$session->forget('errors');

$errorsFromRedirect = $session->pull('errors', new ViewErrorBag);

/** @var Response $response */
$response = $next($request);
Expand All @@ -74,7 +77,7 @@ public function handle(Request $request, Closure $next)
}

// Gather the required meta data for the app.
$spladeData = $this->spladeData($session);
$spladeData = $this->spladeData($session, $errorsFromRedirect);

// The response should redirect away from the Splade app.
if ($redirect = $this->shouldRedirectsAway($response)) {
Expand Down Expand Up @@ -353,26 +356,47 @@ private function parseModalContent(string $content): ?string
/**
* Returns all error messages from the session.
*
* @param \Illuminate\Contracts\Session\Session $session
* @param \Illuminate\Support\ViewErrorBag $viewErrorBag
* @return array
*/
private function allErrorMessages(Session $session): array
private function allErrorMessages(ViewErrorBag $viewErrorBag): array
{
/** @var ViewErrorBag */
$viewErrorBag = $session->get('errors', new ViewErrorBag);

return collect($viewErrorBag->getBags())
->flatMap->getMessages()
->toArray();
}

/**
* Merges all bags from all view errors bags into one.
*
* @param \Illuminate\Support\ViewErrorBag[] ...$viewErrorsBags
* @return \Illuminate\Support\ViewErrorBag
*/
private function mergeViewErrorBags(...$viewErrorsBags): ViewErrorBag
{
$mergedViewBag = new ViewErrorBag;

collect($viewErrorsBags)->each(function (ViewErrorBag $viewErrorBag) use ($mergedViewBag) {
collect($viewErrorBag->getBags())->each(function (MessageBag $bag, string $key) use ($mergedViewBag) {
$mergedBag = $mergedViewBag->hasBag($key)
? $mergedViewBag->getBag($key)
: tap(new MessageBag, fn ($bag) => $mergedViewBag->put($key, $bag));

$mergedBag->merge($bag);
});
});

return $mergedViewBag;
}

/**
* This methods returns all relevant data for a Splade page view.
*
* @param \Illuminate\Contracts\Session\Session $session
* @param \Illuminate\Support\ViewErrorBag $errorsFromRedirect
* @return object
*/
private function spladeData(Session $session): object
private function spladeData(Session $session, ViewErrorBag $errorsFromRedirect): object
{
$flashData = config('splade.share_session_flash_data')
? collect($session->get('_flash.old', []))
Expand All @@ -384,12 +408,17 @@ private function spladeData(Session $session): object

$excludeHead = $this->splade->isLazyRequest() || $this->splade->isRehydrateRequest();

$mergedViewErrorBag = $this->mergeViewErrorBags(
$session->get('errors', new ViewErrorBag),
$errorsFromRedirect
);

return (object) [
'head' => $excludeHead ? [] : $this->splade->head()->toArray(),
'modal' => $this->splade->isModalRequest() ? $this->splade->getModalType() : null,
'modalTarget' => $this->splade->getModalTarget() ?: null,
'flash' => (object) $flash,
'errors' => (object) $this->allErrorMessages($session),
'errors' => (object) $this->allErrorMessages($mergedViewErrorBag),
'shared' => (object) Arr::map($this->splade->getShared(), fn ($value) => value($value)),
'toasts' => array_merge(
$session->pull(static::FLASH_TOASTS, []),
Expand Down