Requirements
PHPFlasher helps you easily add flash notifications to your Symfony projects, improving user feedback with minimal setup.
PHP Version
Symfony Version
Using older PHP or Symfony versions?
If you need to use PHP < v8.2 or Symfony < v7.0, use PHPFlasher v1 instead. It supports PHP ≥ v5.3 and Symfony ≥ v2.0. Check out the v1 documentation here .
Installation
PHPFlasher is modular. You can install only the parts you need.
Run this command to install it:
composer require php-flasher/flasher-symfony
After installing, run this command to set up the required assets:
php bin/console flasher:install
Ready in under a minute!
That's it! No need for complex configuration - PHPFlasher works right out of the box with sensible defaults.
Best Practice
Commit the installed assets to your version control system to ensure everyone on your team has the same notification experience.
Usage
Basic Usage
Here's a basic example of using PHPFlasher in a Symfony controller:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class ProductController extends AbstractController
{
#[Route('/product/create', name: 'app_product_create')]
public function create(): Response
{
// Your logic to create a product
// Add a success notification
flash()->success('Product created successfully!');
return $this->redirectToRoute('app_product_list');
}
}
Pro Tip: Two Ways to Use PHPFlasher
PHPFlasher provides two ways to create notifications:
-
Helper function:
flash()->success('Message');
-
Dependency injection:
public function __construct(private FlasherInterface $flasher) {}
Notification Types
PHPFlasher supports different types of notifications:
// Success message
flash()->success('Your changes have been saved!');
// Error message
flash()->error('Something went wrong!');
// Warning message
flash()->warning('Please review your data before proceeding.');
// Info message
flash()->info('The system will be down for maintenance tonight.');
Your changes have been saved!
Something went wrong!
Please review your data before proceeding.
The system will be down for maintenance tonight.
Adding a Title
You can add a title to your notifications:
flash()->success('Your profile has been updated successfully.', 'Profile Updated');
Your profile has been updated successfully.
Notification Options
Customize your notifications with various options:
flash()
->option('position', 'top-center') // Position on the screen
->option('timeout', 5000) // How long to display (milliseconds)
->option('rtl', true) // Right-to-left support
->success('Your changes have been saved!');
Positioning
Timing
Control how long notifications display with the timeout
option (milliseconds).
Set to 0
to require manual dismissal.
Animations
Choose from various animations:
Common Examples
Here are some common examples of using PHPFlasher in your Symfony applications.
CRUD Operations
A complete example showing notifications for Create, Read, Update, and Delete operations:
<?php
namespace App\Controller;
use App\Entity\Article;
use App\Form\ArticleType;
use App\Repository\ArticleRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
#[Route('/articles')]
class ArticleController extends AbstractController
{
#[Route('/new', name: 'app_article_new', methods: ['GET', 'POST'])]
public function new(Request $request, ArticleRepository $articleRepository): Response
{
$article = new Article();
$form = $this->createForm(ArticleType::class, $article);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$articleRepository->save($article, true);
flash()->success('Article created successfully!', 'Success');
return $this->redirectToRoute('app_article_index');
}
return $this->render('article/new.html.twig', [
'article' => $article,
'form' => $form,
]);
}
#[Route('/{id}/edit', name: 'app_article_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, Article $article, ArticleRepository $articleRepository): Response
{
$form = $this->createForm(ArticleType::class, $article);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$articleRepository->save($article, true);
flash()->success('Article updated successfully!');
return $this->redirectToRoute('app_article_index');
}
return $this->render('article/edit.html.twig', [
'article' => $article,
'form' => $form,
]);
}
#[Route('/{id}', name: 'app_article_delete', methods: ['POST'])]
public function delete(Request $request, Article $article, ArticleRepository $articleRepository): Response
{
if ($this->isCsrfTokenValid('delete'.$article->getId(), $request->request->get('_token'))) {
$articleRepository->remove($article, true);
flash()->info('Article was deleted');
}
return $this->redirectToRoute('app_article_index');
}
}
Best Practice: Consistent Messaging
Use the same notification style and wording for similar operations across your application. This provides a consistent user experience.
Form Validation Feedback
Show validation errors with meaningful notifications:
<?php
namespace App\Controller;
use App\Entity\User;
use App\Form\RegistrationType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Annotation\Route;
class RegistrationController extends AbstractController
{
#[Route('/register', name: 'app_register')]
public function register(
Request $request,
UserPasswordHasherInterface $passwordHasher
): Response {
$user = new User();
$form = $this->createForm(RegistrationType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
// Hash the password
$user->setPassword($passwordHasher->hashPassword(
$user,
$form->get('plainPassword')->getData()
));
// Save the user
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
flash()->success('Your account has been created successfully!', 'Welcome!');
return $this->redirectToRoute('app_login');
} else {
// Show validation errors
flash()->error('Please fix the errors in the form.', 'Registration Failed');
}
}
return $this->render('registration/register.html.twig', [
'registrationForm' => $form->createView(),
]);
}
}
AJAX Support
PHPFlasher can be used with AJAX requests, but requires explicit handling in your JavaScript code:
#[Route('/api/save', name: 'api_save', methods: ['POST'])]
public function saveApi(Request $request): JsonResponse
{
// Process data...
$success = true; // Assuming operation succeeded
if ($success) {
return $this->json([
'status' => 'success',
'message' => 'Data saved successfully!'
]);
} else {
return $this->json([
'status' => 'error',
'message' => 'Failed to save data'
], 400);
}
}
// Import flasher in your JS file
import flasher from '@flasher/flasher';
document.getElementById('saveForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
fetch('/api/save', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
// Explicitly call flasher methods based on the response
if (data.status === 'success') {
flasher.success(data.message);
} else {
flasher.error(data.message);
}
})
.catch(error => {
console.error('Error:', error);
flasher.error('An unexpected error occurred');
});
});
Alternative: Dedicated Flash Message API
You can also create a dedicated endpoint that returns flash messages as part of your API response:
#[Route('/api/flash', name: 'api_flash', methods: ['GET'])]
public function getFlashMessages(): JsonResponse
{
// Get all flash messages as an array
$messages = flash()->render('array');
return $this->json($messages);
}
import flasher from '@flasher/flasher';
// Function to fetch and display flash messages
function fetchFlashMessages() {
fetch('/api/flash')
.then(response => response.json())
.then(messages => {
// Render the flash messages using PHPFlasher
flasher.render(messages);
})
.catch(error => {
console.error('Error fetching flash messages:', error);
});
}
// Call this after operations that might set flash messages on the server
// or periodically if needed
fetchFlashMessages();
Expert Tip: AJAX Integration
PHPFlasher requires explicit JavaScript calls to display notifications in AJAX scenarios. You have several options:
- 1 Call flasher methods directly in your JavaScript after receiving a response
- 2 Use the render() method with a dedicated endpoint that returns flash messages
- 3 Integrate with frameworks like InertiaJS to automatically include flash messages in each response
Using Dependency Injection
For more complex applications, you may prefer using dependency injection for better testability:
<?php
namespace App\Controller;
use App\Service\OrderService;
use Flasher\Prime\FlasherInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class OrderController extends AbstractController
{
public function __construct(
private OrderService $orderService,
private FlasherInterface $flasher,
) {}
#[Route('/order/process', name: 'app_order_process')]
public function processOrder(Request $request): Response
{
try {
$order = $this->orderService->processOrder($request->request->all());
$this->flasher->success(
sprintf('Order #%s has been processed successfully!', $order->getReference()),
'Order Confirmed'
);
return $this->redirectToRoute('app_order_confirmation', [
'reference' => $order->getReference()
]);
} catch (\Exception $e) {
$this->flasher->error(
'We could not process your order. Please try again.',
'Order Processing Failed'
);
return $this->redirectToRoute('app_order_checkout');
}
}
}
Best Practice: Dependency Injection
Using dependency injection with FlasherInterface
makes your code more testable and follows Symfony best practices. It's ideal for services and larger applications.
Configuration
If you want to change the default settings, you can publish the configuration file:
php bin/console flasher:install --config
This will create a file at
config/packages/flasher.yaml
with the following content:
# config/packages/flasher.yaml
flasher:
# Default notification library (e.g., 'flasher', 'toastr', 'noty', 'notyf', 'sweetalert')
default: flasher
# Path to the main PHPFlasher JavaScript file
main_script: '/vendor/flasher/flasher.min.js'
# List of CSS files to style your notifications
styles:
- '/vendor/flasher/flasher.min.css'
# Set global options for all notifications (optional)
# options:
# # Time in milliseconds before the notification disappears
# timeout: 5000
# # Where the notification appears on the screen
# position: 'top-right'
# Automatically inject JavaScript and CSS assets into your HTML pages
inject_assets: true
# Enable message translation using Symfony's translation service
translate: true
# URL patterns to exclude from asset injection and flash_bag conversion
excluded_paths:
- '/^\/_profiler/'
- '/^\/_fragment/'
# Map Symfony flash message keys to notification types
flash_bag:
success: ['success']
error: ['error', 'danger']
warning: ['warning', 'alarm']
info: ['info', 'notice', 'alert']
Common Configuration Examples
Change Default Position
# config/packages/flasher.yaml
flasher:
options:
position: 'bottom-right'
Change Default Timeout
# config/packages/flasher.yaml
flasher:
options:
timeout: 8000 # 8 seconds
Expert Advice
The default configuration works great for most projects. Only customize if you need specific behaviors like:
- Changing the default notification theme (Toastr, SweetAlert, etc.)
- Setting global position/timing for all notifications
- Using custom paths for assets
Converting Symfony Flash Messages
PHPFlasher automatically converts Symfony's native flash messages to PHPFlasher notifications, making migration easy:
// Your existing Symfony flash messages still work
$this->addFlash('success', 'Changes were saved!');
// They will be converted to PHPFlasher notifications automatically
// You can gradually migrate your codebase to use PHPFlasher directly
Presets
You can create a preset for a custom notification that you want to reuse in multiple
places. Add a presets
entry in
the configuration file.
What are presets?
Presets are pre-defined notification configurations that you can reuse throughout your application. They help maintain consistent messaging and reduce code duplication.
For example, create a preset named entity_saved
:
# config/packages/flasher.yaml
flasher:
presets:
entity_saved:
type: 'success'
message: 'Entity saved successfully'
title: 'Entity saved'
payment_received:
type: 'success'
message: 'Payment of %amount% has been received.'
title: 'Payment Confirmed'
options:
timeout: 8000
position: 'top-center'
account_locked:
type: 'error'
message: 'Your account has been locked due to multiple failed attempts.'
title: 'Security Alert'
options:
timeout: 0 # Requires manual dismissal
position: 'center'
To use the preset, call the preset()
method and pass the name of the preset:
<?php
class BookController extends AbstractController
{
#[Route('/book/save', name: 'app_book_save')]
public function save(): Response
{
// Save the book...
// Use a preset for the notification
flash()->preset('entity_saved');
return $this->redirectToRoute('app_book_list');
}
}
class PaymentController extends AbstractController
{
#[Route('/payment/confirm', name: 'app_payment_confirm')]
public function confirm(): Response
{
// Process payment...
// Use a preset with parameters
flash()->preset('payment_received', [
'amount' => '€50.00'
]);
return $this->redirectToRoute('app_payment_receipt');
}
}
The first example is the same as:
class BookController extends AbstractController
{
#[Route('/book/save', name: 'app_book_save')]
public function save(): Response
{
// Without preset, would need to do:
flash()->success('Entity saved successfully', 'Entity saved');
return $this->redirectToRoute('app_book_list');
}
}
Common Preset Use Cases
-
CRUD Operations
Create consistent notifications for create, update, and delete operations
-
User Feedback
Standardize welcome messages, payment confirmations, and other user communications
-
Error Handling
Create consistent error notifications with custom styling and actionable messages
Best Practice: Centralized Message Management
Store all your notification presets in one place to ensure consistent messaging across your application. This makes it easy to update notification wording or styling globally.
Dynamic Presets with Parameters
You can create more flexible presets using parameters:
# config/packages/flasher.yaml
flasher:
presets:
order_created:
type: 'success'
message: 'Order #%order_id% has been created successfully. Total: %amount%'
title: 'Order Created'
Then use the preset with parameters:
// Parameters are passed as an array
flash()->preset('order_created', [
'order_id' => '12345',
'amount' => '$99.99'
]);
// This will display: "Order #12345 has been created successfully. Total: $99.99"
Translations & RTL Support
PHPFlasher integrates perfectly with Symfony's translation system, making it easy to display notifications in multiple languages.
Basic Translation
Use the translate()
method to set the language for a notification:
// Translation will automatically use the current locale
flash()->success('The resource was created');
// Or explicitly specify a language
flash()->translate('fr')->success('The resource was created');
flash()->translate('ar')->success('The resource was created');
Translation Files
Define your translations in YAML files in the translations/
directory:
# translations/flasher.ar.yaml
success: 'نجاح'
error: 'خطأ'
warning: 'تحذير'
info: 'معلومة'
The resource was created: 'تم إنشاء :resource'
The resource was updated: 'تم تعديل :resource'
The resource was saved: 'تم حفظ :resource'
The resource was deleted: 'تم حذف :resource'
resource: 'الملف'
# translations/flasher.en.yaml
success: 'Success'
error: 'Error'
warning: 'Warning'
info: 'Info'
The resource was created: 'The :resource was created'
The resource was updated: 'The :resource was updated'
The resource was saved: 'The :resource was saved'
The resource was deleted: 'The :resource was deleted'
resource: 'resource'
# translations/flasher.fr.yaml
success: 'Succès'
error: 'Erreur'
warning: 'Avertissement'
info: 'Information'
The resource was created: 'La ressource :resource a été ajoutée'
The resource was updated: 'La ressource :resource a été mise à jour'
The resource was saved: 'La ressource :resource a été enregistrée'
The resource was deleted: 'La ressource :resource a été supprimée'
resource: ''
Right-to-Left (RTL) Support
PHPFlasher automatically handles right-to-left languages like Arabic and Hebrew. The layout adjusts based on the language:
تمت العملية بنجاح.
// Using Arabic language automatically enables RTL
flash()
->translate('ar')
->success('Your request was processed successfully.', 'Congratulations!');
// Or explicitly set RTL mode
flash()
->option('rtl', true)
->success('Your request was processed successfully.', 'Congratulations!');
Benefits of Built-in Translation Support
Reach users worldwide with notifications in their native language.
Works seamlessly with Symfony's translation system.
Automatic right-to-left layout for Arabic, Hebrew, etc.
Translation with Parameters
You can use parameters in your translations:
// In translations/messages.en.yaml:
// welcome.user: 'Welcome, %name%!'
flash()
->info(
$this->translator->trans('welcome.user', ['%name%' => $user->getFirstName()])
);
// Or directly with PHPFlasher (if using presets with placeholders)
flash()->preset('welcome_user', ['name' => $user->getFirstName()]);
Best Practice: Centralize Your Translations
Store all user-facing notification messages in translation files rather than hardcoding them. This makes it much easier to update wording or add new languages later.
Additional Features
Multiple Themes
Choose from 6+ themes including Toastr, SweetAlert, Notyf, Noty and more.
View themesLivewire Support
Seamless integration with Livewire for dynamic notifications without page reload.
Learn moreAJAX Support
Easy integration with AJAX requests using JavaScript API to display notifications after requests.
Learn moreReady to elevate your Symfony UI?
Start using PHPFlasher today and give your users beautiful notifications in minutes!