├── .styleci.yml ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── art ├── banner.png ├── banner1.png ├── carbon.png ├── carbon.svg ├── example-dark.svg ├── example-dark.svg.png ├── example-light.png ├── example-light.svg ├── messages.png ├── syntax-dark.png ├── syntax-dark.svg ├── syntax-light.png └── syntax-light.svg ├── composer.json ├── resources └── views │ └── components │ ├── alert-error.blade.php │ ├── alert-info.blade.php │ ├── alert-message.blade.php │ ├── alert-success.blade.php │ ├── alert-warning.blade.php │ ├── errors.blade.php │ └── messages.blade.php └── src ├── FlashMessageServiceProvider.php ├── Http └── Middleware │ └── ShareMessagesFromSession.php ├── Message.php ├── View └── Components │ ├── AbstractAlert.php │ ├── Alert.php │ ├── AlertError.php │ ├── AlertInfo.php │ ├── AlertMessage.php │ ├── AlertSuccess.php │ ├── AlertWarning.php │ ├── Errors.php │ └── Messages.php ├── ViewFlashMessageBag.php └── helpers.php /.styleci.yml: -------------------------------------------------------------------------------- 1 | preset: recommended 2 | tab-width: 4 3 | finder: 4 | exclude: 5 | - "tests" 6 | name: 7 | - "*.php" 8 | not-name: 9 | - "*Stub.php" 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `laravel-flash-message` will be documented in this file. 4 | 5 | ## 1.4.0 - 2025-02-17 6 | 7 | - Add Laravel 12 support 8 | 9 | ## 1.3.0 - 2024-01-27 10 | 11 | - Add PHP 8.4 support 12 | - Drop Laravel 8 support 13 | 14 | ## 1.2.0 - 2024-02-28 15 | 16 | - Add Laravel 11 support 17 | - Add PHP 8.3 support 18 | 19 | ## 1.1.0 - 2023-05-01 20 | 21 | - Add Laravel 10 support 22 | 23 | ## 1.0.0 - 2022-12-18 24 | 25 | - initial release 26 | 27 | ### Breaking changes 28 | 29 | Blade component are now namespaced instead of prefixed. This means that usage of the components should be changed from the old prefix syntax 30 | 31 | ```blade 32 | // no longer supported 33 | ``` 34 | 35 | to the new namespace syntax 36 | 37 | ```blade 38 | // new syntax 39 | ``` 40 | 41 | The session and view keys are also removed from the configuration, leaving the configuration with using the hardcoded value `messages` for both. 42 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) bilfeldt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flash multiple advanced messages with both text, messages and links 2 | 3 | ![bilfeldt/laravel-flash-message](/art/banner.png?raw=true) 4 | 5 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/bilfeldt/laravel-flash-message.svg?style=flat-square)](https://packagist.org/packages/bilfeldt/laravel-flash-message) 6 | [![GitHub Tests Action Status](https://github.com/bilfeldt/laravel-flash-message/actions/workflows/run-tests.yml/badge.svg)](https://github.com/bilfeldt/laravel-flash-message/actions/workflows/run-tests.yml) 7 | [![StyleCI Code Style Status](https://github.styleci.io/repos/416473017/shield)](https://github.styleci.io/repos/416473017/shield) 8 | [![Total Downloads](https://img.shields.io/packagist/dt/bilfeldt/laravel-flash-message.svg?style=flat-square)](https://packagist.org/packages/bilfeldt/laravel-flash-message) 9 | 10 | An opinionated solution for flashing multiple advanced messages from the backend and showing these on the frontend using prebuild customizable Tailwind CSS alert blade components. 11 | 12 | ## Installation 13 | 14 | Install the package via composer and you are ready to add messages and show these on the frontend. 15 | 16 | ```bash 17 | composer require bilfeldt/laravel-flash-message 18 | ``` 19 | 20 | You are now ready to use the blade components to show the messages on the frontend. 21 | 22 | **Optional:** In case you wish to use the [message flashing](https://laravel.com/docs/master/responses#redirecting-with-flashed-session-data) feature allowing messages to be made available on the next request (useful in combination with redirects) simply add the `ShareMessagesFromSession` middleware to the `web` group defined in `app/Http/Kernel.php` just after the `ShareErrorsFromSession` middleware: 23 | 24 | ```php 25 | // app/Http/Kernel.php 26 | 27 | /** 28 | * The application's route middleware groups. 29 | * 30 | * @var array 31 | */ 32 | protected $middlewareGroups = [ 33 | 'web' => [ 34 | \App\Http\Middleware\EncryptCookies::class, 35 | \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, 36 | \Illuminate\Session\Middleware\StartSession::class, 37 | \Laravel\Jetstream\Http\Middleware\AuthenticateSession::class, 38 | \Illuminate\View\Middleware\ShareErrorsFromSession::class, 39 | \Bilfeldt\LaravelFlashMessage\Http\Middleware\ShareMessagesFromSession::class, // <------ ADDED HERE 40 | \App\Http\Middleware\VerifyCsrfToken::class, 41 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 42 | ], 43 | ... 44 | ``` 45 | 46 | ## Usage 47 | 48 | ### Alert blade components 49 | 50 | Simple usage of the alert blade components (`message`, `info`, `success`, `warning`, `error`): 51 | 52 | ```blade: 53 | 54 | ```blade 55 | 61 | ``` 62 | 63 | ### Validation errors 64 | 65 | Validation errors are made available as `$errors` by default in Laravel and it is possilbe to render these easily using: 66 | 67 | ```blade 68 | 72 | ``` 73 | 74 | ### Passing notifications from the backend 75 | 76 | The most basic usage of this package is creating a message inside a controller and passing it to the view: 77 | 78 | ```php 79 | title('This is important') 97 | ->addMessage('account', 'There is 10 days left of your free trial') 98 | ->addLink('Read more', 'https://example.com/signup'); 99 | 100 | return view('posts')->withMessage($message); 101 | } 102 | } 103 | ``` 104 | 105 | ### Redirects 106 | 107 | Sometimes a redirect is returned to the user instead of a view. In that case the message must be flashed to the session so that they are available on the subsequent request. This is simply done by flashing the `$message`: 108 | 109 | ```php 110 | title('This is important') 128 | ->addMessage('account', 'There is 10 days left of your free trial') 129 | ->addLink('Read more', 'https://example.com/signup'); 130 | 131 | return redirect('/posts')->withMessage($message); // This will flash the message to the Laravel session 132 | } 133 | } 134 | ``` 135 | 136 | Note that for this to work you will need to add the `ShareMessagesFromSession` middleware to `app/Http/Kernel.php` as described in the [installation section](#installation) above. 137 | 138 | In the situations where we need to flash a message to session without access to a redirect, like in a Laravel Livewire component, then we have added a small helper method `session_message($message)` which does the same. 139 | 140 | ### Adding message from anywhere in the code 141 | 142 | Messages can be adding bacially anywhere in the codebase using the `View` facade. Although most usecases will be adding the messages from the controller, then this feature can be really powerful for example conjunction with middlewares: 143 | 144 | ```php 145 | \Illuminate\Support\Facades\View::withMessage($message); 146 | ``` 147 | 148 | ### Multiple message bags 149 | 150 | There might be situations where it can be usefull to have multiple "MessageBags" (the same approach as Laravel usese for the validation messages) and in this case one can name the bag like so: 151 | 152 | ```php 153 | return view('posts')->withMessage($message, 'bag-name'); 154 | // or 155 | return redirect('/posts')->withMessage($message, 'bag-name'); 156 | ``` 157 | 158 | and when displaying the messages simply pass the bag name as well: 159 | 160 | ```php 161 | 162 | ``` 163 | 164 | ## Tip 165 | 166 | You might have a layout where you would always like to flash the messages above the main content or just below the title. You can simply add the `` to your layout file in the place you would like the messages to show and that way you do not need to call this in multiple views. In order to avoid issues with the `$messages` not being set in case the `ShareMessagesFromSession` has not been applied then it advised to show the message like so: 167 | 168 | ```php 169 | @isset($messages) 170 | 171 | @endif 172 | ``` 173 | 174 | If you need to show specific messages at a specific location simply use a [named message bag](#multiple-message-bags) for these messages and show them at the desired location 175 | 176 | ## Alternatives / Supplements 177 | 178 | This package is useful when working with blade files and passing messages from the backend to the frontend during rendering. If you are looking for *toast* (popup) messages instead have a look at these awesome packages: 179 | - [usernotnull/tall-toasts](https://github.com/usernotnull/tall-toasts) for the [TALL stack](https://tallstack.dev/) 180 | - [https://php-flasher.github.io/](https://php-flasher.github.io/) 181 | 182 | ## Testing 183 | 184 | ```bash 185 | composer test 186 | ``` 187 | 188 | ## Changelog 189 | 190 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 191 | 192 | ## Credits 193 | 194 | - [Anders Bilfeldt](https://github.com/bilfeldt): Main package developer 195 | - [iAmine](https://tailwindcomponents.com/u/iaminos): The [Alert blade components](https://tailwindcomponents.com/component/alerts-components) 196 | - [Showcode.app](https://showcode.app/): Service for creating terminal mockups 197 | - [Beyond Code](https://banners.beyondco.de/): Banner generator 198 | 199 | ## License 200 | 201 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 202 | -------------------------------------------------------------------------------- /art/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilfeldt/laravel-flash-message/2ee68a9087180990d6230ed478fcc0d50fccf485/art/banner.png -------------------------------------------------------------------------------- /art/banner1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilfeldt/laravel-flash-message/2ee68a9087180990d6230ed478fcc0d50fccf485/art/banner1.png -------------------------------------------------------------------------------- /art/carbon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilfeldt/laravel-flash-message/2ee68a9087180990d6230ed478fcc0d50fccf485/art/carbon.png -------------------------------------------------------------------------------- /art/example-dark.svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilfeldt/laravel-flash-message/2ee68a9087180990d6230ed478fcc0d50fccf485/art/example-dark.svg.png -------------------------------------------------------------------------------- /art/example-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilfeldt/laravel-flash-message/2ee68a9087180990d6230ed478fcc0d50fccf485/art/example-light.png -------------------------------------------------------------------------------- /art/messages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilfeldt/laravel-flash-message/2ee68a9087180990d6230ed478fcc0d50fccf485/art/messages.png -------------------------------------------------------------------------------- /art/syntax-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilfeldt/laravel-flash-message/2ee68a9087180990d6230ed478fcc0d50fccf485/art/syntax-dark.png -------------------------------------------------------------------------------- /art/syntax-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilfeldt/laravel-flash-message/2ee68a9087180990d6230ed478fcc0d50fccf485/art/syntax-light.png -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bilfeldt/laravel-flash-message", 3 | "description": "Flash multiple messages using Laravels default session message flashing system", 4 | "keywords": [ 5 | "bilfeldt", 6 | "laravel", 7 | "laravel-flash-message" 8 | ], 9 | "homepage": "https://github.com/bilfeldt/laravel-flash-message", 10 | "license": "MIT", 11 | "authors": [ 12 | { 13 | "name": "Anders Bilfeldt", 14 | "email": "abilfeldt@gmail.com", 15 | "role": "Developer" 16 | } 17 | ], 18 | "require": { 19 | "php": "~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", 20 | "illuminate/contracts": "^9.0 || ^10.0 || ^11.0 || ^12.0" 21 | }, 22 | "require-dev": { 23 | "nunomaduro/collision": "^7.0 || ^8.0", 24 | "orchestra/testbench": "^8.0 || ^9.0 || ^10.0", 25 | "phpunit/phpunit": "^10.0 || ^11.0" 26 | }, 27 | "autoload": { 28 | "psr-4": { 29 | "Bilfeldt\\LaravelFlashMessage\\": "src" 30 | }, 31 | "files": [ 32 | "src/helpers.php" 33 | ] 34 | }, 35 | "autoload-dev": { 36 | "psr-4": { 37 | "Bilfeldt\\LaravelFlashMessage\\Tests\\": "tests" 38 | } 39 | }, 40 | "scripts": { 41 | "test": "./vendor/bin/testbench package:test --no-coverage", 42 | "test-coverage": "vendor/bin/phpunit --coverage-html coverage" 43 | }, 44 | "config": { 45 | "optimize-autoloader": true, 46 | "preferred-install": "dist", 47 | "sort-packages": true, 48 | "allow-plugins": { 49 | "pestphp/pest-plugin": true 50 | } 51 | }, 52 | "extra": { 53 | "laravel": { 54 | "providers": [ 55 | "Bilfeldt\\LaravelFlashMessage\\FlashMessageServiceProvider" 56 | ] 57 | } 58 | }, 59 | "minimum-stability": "dev", 60 | "prefer-stable": true 61 | } 62 | -------------------------------------------------------------------------------- /resources/views/components/alert-error.blade.php: -------------------------------------------------------------------------------- 1 | 46 | -------------------------------------------------------------------------------- /resources/views/components/alert-info.blade.php: -------------------------------------------------------------------------------- 1 | 46 | -------------------------------------------------------------------------------- /resources/views/components/alert-message.blade.php: -------------------------------------------------------------------------------- 1 | 46 | -------------------------------------------------------------------------------- /resources/views/components/alert-success.blade.php: -------------------------------------------------------------------------------- 1 | 46 | -------------------------------------------------------------------------------- /resources/views/components/alert-warning.blade.php: -------------------------------------------------------------------------------- 1 | 46 | -------------------------------------------------------------------------------- /resources/views/components/errors.blade.php: -------------------------------------------------------------------------------- 1 | @if ($errors->getBag($bag)->any()) 2 | 9 | @endif 10 | 11 | -------------------------------------------------------------------------------- /resources/views/components/messages.blade.php: -------------------------------------------------------------------------------- 1 | @foreach($messages->getBag($bag) as $message) 2 | 9 | @endforeach 10 | -------------------------------------------------------------------------------- /src/FlashMessageServiceProvider.php: -------------------------------------------------------------------------------- 1 | loadViewsFrom(__DIR__.'/../resources/views', self::VIEW_COMPONENT_NAMESPACE); 24 | 25 | $this->publishes([ 26 | __DIR__.'/../resources/views' => resource_path('views/vendor/'.self::VIEW_COMPONENT_NAMESPACE), 27 | ], 'flash-views'); 28 | 29 | Blade::componentNamespace('Bilfeldt\\LaravelFlashMessage\\View\\Components', self::VIEW_COMPONENT_NAMESPACE); 30 | 31 | // This is used when adding a message from a controller: view('posts-index')->withMessage(...) 32 | View::macro('withMessage', function (Message $message, string $bag = 'default'): View { 33 | /** @var ViewFlashMessageBag $viewFlashMessageBag */ 34 | $viewFlashMessageBag = \Illuminate\Support\Facades\View::shared('messages', new ViewFlashMessageBag()); 35 | 36 | \Illuminate\Support\Facades\View::share('messages', $viewFlashMessageBag->push($message, $bag)); 37 | 38 | return $this; 39 | }); 40 | 41 | // This is used when adding a message from the View Facade: \Illuminate\Support\Facades\View::withMessage(...) 42 | Factory::macro('withMessage', function (Message $message, string $bag = 'default'): Factory { 43 | /** @var ViewFlashMessageBag $viewFlashMessageBag */ 44 | $viewFlashMessageBag = \Illuminate\Support\Facades\View::shared('messages', new ViewFlashMessageBag()); 45 | 46 | \Illuminate\Support\Facades\View::share('messages', $viewFlashMessageBag->push($message, $bag)); 47 | 48 | return $this; 49 | }); 50 | 51 | // This is used when adding messages from a controller: view('posts-index')->withMessages(...) 52 | View::macro('withMessages', function (array $messages, string $bag = 'default'): View { 53 | /** @var ViewFlashMessageBag $viewFlashMessageBag */ 54 | $viewFlashMessageBag = \Illuminate\Support\Facades\View::shared('messages', new ViewFlashMessageBag()); 55 | 56 | /** @var \Bilfeldt\LaravelFlashMessage\Message $message */ 57 | foreach ($messages as $message) { 58 | $viewFlashMessageBag->push($message, $bag); 59 | } 60 | \Illuminate\Support\Facades\View::share('messages', $viewFlashMessageBag); 61 | 62 | return $this; 63 | }); 64 | 65 | // This is used when adding messages from the View Facade: \Illuminate\Support\Facades\View::withMessages(...) 66 | Factory::macro('withMessages', function (array $messages, string $bag = 'default'): Factory { 67 | /** @var ViewFlashMessageBag $viewFlashMessageBag */ 68 | $viewFlashMessageBag = \Illuminate\Support\Facades\View::shared('messages', new ViewFlashMessageBag()); 69 | 70 | /** @var \Bilfeldt\LaravelFlashMessage\Message $message */ 71 | foreach ($messages as $message) { 72 | $viewFlashMessageBag->push($message, $bag); 73 | } 74 | \Illuminate\Support\Facades\View::share('messages', $viewFlashMessageBag); 75 | 76 | return $this; 77 | }); 78 | 79 | /** 80 | * Flash a container of errors to the global errors bag. 81 | * 82 | * Note that the view already has a method 'withErrors' but that does not share them globally like this method. 83 | * 84 | * @param \Illuminate\Contracts\Support\MessageProvider|array|string $provider 85 | * @param string $key 86 | * 87 | * @return $this 88 | * 89 | * @see https://github.com/laravel/framework/pull/39459 90 | */ 91 | View::macro('addErrors', function ($provider, $key = 'default'): View { 92 | /** @var ViewErrorBag $viewErrorBag */ 93 | $viewErrorBag = \Illuminate\Support\Facades\View::shared('errors', new ViewErrorBag()); 94 | 95 | if ($viewErrorBag->hasBag($key)) { 96 | $viewErrorBag->getBag($key)->merge($provider); 97 | } else { 98 | $viewErrorBag->put($key, $this->formatErrors($provider)); 99 | } 100 | 101 | \Illuminate\Support\Facades\View::share('errors', $viewErrorBag); 102 | 103 | return $this; 104 | }); 105 | 106 | // This is used to add a message from a controller when returning a redirect: redirect()->withMessage($message) 107 | RedirectResponse::macro('withMessage', function (Message $message, string $bag = 'default'): RedirectResponse { 108 | session_message($message, $bag); 109 | 110 | return $this; 111 | }); 112 | 113 | // This is used to add messages from a controller when returning a redirect: redirect()->withMessage([$message1, $message2]) 114 | RedirectResponse::macro('withMessages', function (array $messages, string $bag = 'default'): RedirectResponse { 115 | /** @var \Bilfeldt\LaravelFlashMessage\Message $message */ 116 | foreach ($messages as $message) { 117 | session_message($message, $bag); 118 | } 119 | 120 | return $this; 121 | }); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/Http/Middleware/ShareMessagesFromSession.php: -------------------------------------------------------------------------------- 1 | view = $view; 29 | } 30 | 31 | /** 32 | * Handle an incoming request. 33 | * 34 | * @param \Illuminate\Http\Request $request 35 | * @param \Closure $next 36 | * 37 | * @return mixed 38 | */ 39 | public function handle($request, Closure $next) 40 | { 41 | // If the current session has an "messages" variable bound to it, we will share 42 | // its value with all view instances so the views can easily access messages 43 | // without having to bind. An empty collection is set when there aren't any messages. 44 | $this->view->share( 45 | 'messages', 46 | ViewFlashMessageBag::make($request->session()->get('messages') ?: []) 47 | ); 48 | 49 | // Putting the messages in the view for every view allows the developer to just 50 | // assume that some messages are always available, which is convenient since 51 | // they don't have to continually run checks for the presence of messages. 52 | 53 | return $next($request); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Message.php: -------------------------------------------------------------------------------- 1 | level(self::LEVEL_INFO); 35 | } 36 | 37 | public static function success(string $text): self 38 | { 39 | return self::make($text)->level(self::LEVEL_SUCCESS); 40 | } 41 | 42 | public static function warning(string $text): self 43 | { 44 | return self::make($text)->level(self::LEVEL_WARNING); 45 | } 46 | 47 | public static function error(string $text): self 48 | { 49 | return self::make($text)->level(self::LEVEL_ERROR); 50 | } 51 | 52 | public static function make(string $text): self 53 | { 54 | return new self($text); 55 | } 56 | 57 | public function __construct(string $text, string $level = self::LEVEL_MESSAGE) 58 | { 59 | $this->level($level); 60 | $this->text($text); 61 | $this->title = ''; 62 | $this->links = []; 63 | $this->messages = new MessageBag(); 64 | } 65 | 66 | //====================================================================== 67 | // SETTERS 68 | //====================================================================== 69 | 70 | public function level(string $level): self 71 | { 72 | if (!in_array($level, self::levels())) { 73 | throw new \DomainException("Invalid message level: $level"); 74 | } 75 | 76 | $this->level = $level; 77 | 78 | return $this; 79 | } 80 | 81 | public function text(string $text): self 82 | { 83 | $this->text = $text; 84 | 85 | return $this; 86 | } 87 | 88 | public function title(string $title): self 89 | { 90 | $this->title = $title; 91 | 92 | return $this; 93 | } 94 | 95 | public function messages(array $messages): self 96 | { 97 | $this->messages = new MessageBag($messages); 98 | 99 | return $this; 100 | } 101 | 102 | public function addMessage(string $field, string ...$messages): self 103 | { 104 | if (empty($messages)) { 105 | $this->messages->merge([$field]); 106 | } else { 107 | foreach ($messages as $message) { 108 | $this->messages->add($field, $message); 109 | } 110 | } 111 | 112 | return $this; 113 | } 114 | 115 | public function addLink(string $text, string $url): self 116 | { 117 | $this->links[$text] = $url; 118 | 119 | return $this; 120 | } 121 | 122 | public function links(array $links): self 123 | { 124 | foreach ($links as $text => $url) { 125 | $this->addLink($text, $url); 126 | } 127 | 128 | return $this; 129 | } 130 | 131 | //====================================================================== 132 | // GETTERS 133 | //====================================================================== 134 | 135 | public function getLevel(): string 136 | { 137 | return $this->level; 138 | } 139 | 140 | public function getText(): string 141 | { 142 | return $this->text; 143 | } 144 | 145 | public function getTitle(): string 146 | { 147 | return $this->title; 148 | } 149 | 150 | public function getMessageBag(): MessageBag 151 | { 152 | return $this->messages; 153 | } 154 | 155 | public function getLinks(): array 156 | { 157 | return $this->links; 158 | } 159 | 160 | public function toArray(): array 161 | { 162 | return [ 163 | 'level' => $this->level, 164 | 'title' => $this->title, 165 | 'message' => $this->text, 166 | 'messageBag' => $this->messages, 167 | 'links' => $this->links, 168 | ]; 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/View/Components/AbstractAlert.php: -------------------------------------------------------------------------------- 1 | text = $text; 17 | $this->title = $title; 18 | $this->messages = $messages; 19 | $this->links = $links; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/View/Components/Alert.php: -------------------------------------------------------------------------------- 1 | level = $level; 19 | $this->text = $text; 20 | $this->title = $title; 21 | $this->messages = $messages; 22 | $this->links = $links; 23 | } 24 | 25 | public function render() 26 | { 27 | switch ($this->level) { 28 | case Message::LEVEL_MESSAGE: 29 | return view('flash::components.alert-message'); 30 | case Message::LEVEL_INFO: 31 | return view('flash::components.alert-info'); 32 | case Message::LEVEL_SUCCESS: 33 | return view('flash::components.alert-success'); 34 | case Message::LEVEL_WARNING: 35 | return view('flash::components.alert-warning'); 36 | case Message::LEVEL_ERROR: 37 | return view('flash::components.alert-error'); 38 | default: 39 | throw new \InvalidArgumentException('Invalid alert level: '.$this->level); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/View/Components/AlertError.php: -------------------------------------------------------------------------------- 1 | bag = $bag; 14 | } 15 | 16 | public function render() 17 | { 18 | return view('flash::components.messages'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/ViewFlashMessageBag.php: -------------------------------------------------------------------------------- 1 | $messages) { 33 | $viewFlashMessageBag->put($bag, Collection::make($messages)->values()); // values() is used since we are not interested in the keys which is a uuid when using session flashing 34 | } 35 | 36 | return $viewFlashMessageBag; 37 | } 38 | 39 | /** 40 | * Checks if a named MessageBag exists in the bags. 41 | * 42 | * @param string $key 43 | * 44 | * @return bool 45 | */ 46 | public function hasBag($key = 'default'): bool 47 | { 48 | return isset($this->bags[$key]); 49 | } 50 | 51 | /** 52 | * Get a MessageBag instance from the bags. 53 | * 54 | * @param string $key 55 | * 56 | * @return \Illuminate\Support\Collection|\Bilfeldt\LaravelFlashMessage\Message[] 57 | */ 58 | public function getBag($key) 59 | { 60 | return Arr::get($this->bags, $key) ?: new Collection([]); 61 | } 62 | 63 | /** 64 | * Get all the bags. 65 | * 66 | * @return array 67 | */ 68 | public function getBags() 69 | { 70 | return $this->bags; 71 | } 72 | 73 | /** 74 | * Add a new Message collection. 75 | * 76 | * @param string $key 77 | * @param \Illuminate\Support\Collection|\Bilfeldt\LaravelFlashMessage\Message[] $messages 78 | * 79 | * @return \Bilfeldt\LaravelFlashMessage\ViewFlashMessageBag 80 | */ 81 | public function put($key, \Illuminate\Support\Collection $messages): self 82 | { 83 | $this->bags[$key] = $messages; 84 | 85 | return $this; 86 | } 87 | 88 | /** 89 | * Add a new Message collection. 90 | * 91 | * @param \Bilfeldt\LaravelFlashMessage\Message $message 92 | * @param string $key 93 | * 94 | * @return \Bilfeldt\LaravelFlashMessage\ViewFlashMessageBag 95 | */ 96 | public function push(Message $message, string $key = 'default'): self 97 | { 98 | $this->bags[$key] = $this->getBag($key)->push($message); 99 | 100 | return $this; 101 | } 102 | 103 | /** 104 | * Get the number of messages in the default bag. 105 | * 106 | * @return int 107 | */ 108 | public function count(): int 109 | { 110 | return $this->getBag('default')->count(); 111 | } 112 | 113 | /** 114 | * Dynamically call methods on the default bag. 115 | * 116 | * @param string $method 117 | * @param array $parameters 118 | * 119 | * @return mixed 120 | */ 121 | public function __call($method, $parameters) 122 | { 123 | return $this->getBag('default')->$method(...$parameters); 124 | } 125 | 126 | /** 127 | * Dynamically access a view message bag. 128 | * 129 | * @param string $key 130 | * 131 | * @return \Illuminate\Support\Collection|\Bilfeldt\LaravelFlashMessage\Message[] 132 | */ 133 | public function __get($key) 134 | { 135 | return $this->getBag($key); 136 | } 137 | 138 | /** 139 | * Dynamically set a view message bag. 140 | * 141 | * @param string $key 142 | * @param \Illuminate\Support\Collection|\Bilfeldt\LaravelFlashMessage\Message[] $value 143 | * 144 | * @return void 145 | */ 146 | public function __set($key, $value) 147 | { 148 | $this->put($key, $value); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/helpers.php: -------------------------------------------------------------------------------- 1 | flash('messages'.'.'.$bag.'.'.Str::orderedUuid(), $message); 19 | 20 | // Note that we are using ordered uuid as keys and flashing each message individually to the storage instead of 21 | // flashing the entire ViewFlashMessageBag object. This is because flashing the entire object will require 22 | // fetching it from session, adding new messages and re-flashing. During this process any already flashed 23 | // messages will be re-flashed and hence be shown for an "extra" request. 24 | // Despite this "bug" this is how Laravel does it with errors. I expect this can cause problems especially 25 | // when being used in Livewire. See https://github.com/laravel/framework/blob/master/src/Illuminate/Http/RedirectResponse.php#L131 26 | /* 27 | $messages = session()->get('messages', new \Bilfeldt\LaravelFlashMessage\ViewFlashMessageBag()); 28 | 29 | if (! $messages instanceof \Bilfeldt\LaravelFlashMessage\ViewFlashMessageBag) { 30 | $messages = new \Bilfeldt\LaravelFlashMessage\ViewFlashMessageBag; 31 | } 32 | 33 | session()->flash('messages', $messages->push($message, $bag)); 34 | */ 35 | } 36 | } 37 | --------------------------------------------------------------------------------