Filament Admin Panel Introduction
Objective:
- Install and configure Filament in the Laravel project.
- Create a basic CRUD interface using Filament.
- Customize Filament resources (forms, tables) for a specific model.
- Apply role-based access control for the admin panel.
Step 1: Install Filament in Laravel
Filament is a lightweight admin panel generator that allows you to create and manage resources easily. It is designed specifically for Laravel and integrates well with the Eloquent ORM.
Step 1.1: Install Filament In the terminal, run the following command to install Filament via Composer:
composer require filament/filament
Step 1.2: Publish Filament Assets Once installed, publish the Filament configuration and assets:
php artisan filament:install
This command will create necessary configuration files and assets for Filament.
Step 1.3: Run Migrations Filament also requires some database migrations for user roles and permissions. Run the migrations to set up these tables:
php artisan migrate
Step 1.4: Access the Admin Panel Now, start the Laravel development server:
php artisan serve
Visit http://127.0.0.1:8000/admin
to access the Filament admin panel. You should see the Filament login page. Create a user by registering or logging in with an existing user.
Step 2: Creating a Filament Resource for a Model
We’ll now create a Filament resource to manage a model, like Post
.
Step 2.1: Create the Post Model and Migration
If you don’t already have the Post
model from Day 2, you can create it using Artisan:
php artisan make:model Post -m
Edit the migration file in database/migrations
to add the necessary fields for the posts
table:
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->timestamps();
});
Run the migration:
php artisan migrate
Step 2.2: Generate a Filament Resource
Use the following command to generate a Filament resource for the Post
model:
php artisan make:filament-resource Post
This will generate a resource file located at app/Filament/Resources/PostResource.php
along with default views for listing, creating, and editing posts.
Step 2.3: Customize the Post Resource
Open app/Filament/Resources/PostResource.php
. You will see predefined configurations for fields and forms. Customize the table and form based on your needs.
-
Defining Table Columns: Modify the
table()
method to define how the table should display the posts in the admin panel:public static function table(Table $table): Table { return $table ->columns([ TextColumn::make('title')->sortable(), TextColumn::make('created_at')->dateTime()->label('Created'), ]) ->filters([ // ]); }
-
Defining Form Fields: Modify the
form()
method to define the fields users will fill out when creating or editing posts:public static function form(Form $form): Form { return $form ->schema([ TextInput::make('title')->required(), Textarea::make('content')->required(), ]); }
Step 3: Customize Filament Features (Forms, Tables)
Filament provides a range of tools to customize the admin panel’s look and feel. Here’s how you can extend the functionality of your admin panel.
Step 3.1: Adding Filters to the Table
You can add filters to the table to allow admins to quickly find posts based on certain criteria:
public static function table(Table $table): Table
{
return $table
->columns([
TextColumn::make('title')->sortable(),
TextColumn::make('created_at')->dateTime(),
])
->filters([
SelectFilter::make('created_at')
->label('Filter by Date')
->options([
'today' => 'Today',
'this_week' => 'This Week',
'this_month' => 'This Month',
]),
]);
}
Step 3.2: Adding Validation to Forms
To ensure data integrity, add validation to the form fields. For example:
public static function form(Form $form): Form
{
return $form
->schema([
TextInput::make('title')
->required()
->maxLength(255)
->label('Post Title'),
Textarea::make('content')
->required()
->label('Post Content'),
]);
}
Step 4: Implement Role-Based Access Control for the Admin Panel
You can restrict access to certain parts of the admin panel based on user roles.
Step 4.1: Add a Role Column to Users
If you haven’t already done so in Day 3, add a role
column to the users
table via migration:
php artisan make:migration add_role_to_users_table --table=users
Edit the migration to add the role
column:
Schema::table('users', function (Blueprint $table) {
$table->string('role')->default('user');
});
Run the migration:
php artisan migrate
Step 4.2: Assign Roles to Users
Manually update the role
field in the database for users. You can use phpMyAdmin
or any database management tool to assign the role of admin
or user
to each user.
Step 4.3: Restrict Access to the Admin Panel
To restrict access to the admin panel based on roles, open app/Providers/FilamentServiceProvider.php
and modify the gate()
method:
use Illuminate\Support\Facades\Gate;
public function boot()
{
Filament::serving(function () {
Gate::define('access-filament', function ($user) {
return $user->role === 'admin'; // Only admins can access the admin panel
});
});
}
Now, only users with the admin
role will have access to the Filament admin panel.
Step 5: Testing the Admin Panel
-
Visit the Admin Panel: Visit
http://127.0.0.1:8000/admin
in your browser. If you are logged in as an admin, you should see thePost
resource listed in the sidebar. -
Create, Edit, and Delete Posts:
- Use the admin panel to create a new post.
- Edit existing posts by clicking the “Edit” button.
- Delete posts using the “Delete” button.
-
Test Role-Based Access:
- Log in as a user with the
user
role and try accessing the/admin
route. You should be denied access.
- Log in as a user with the
Step 6: Additional Customizations (Optional)
Step 6.1: Customizing Admin Navigation
You can customize the navigation in the admin panel by modifying the PostResource.php
file:
public static function getNavigationLabel(): string
{
return 'Blog Posts';
}
Step 6.2: Creating Custom Pages or Widgets
Filament allows you to create custom pages and widgets within the admin panel. For example, you can create a dashboard with statistics about the posts or users.
-
Generate a Dashboard Widget:
php artisan make:filament-widget PostStatsWidget
-
Customize the Widget: Edit the newly created widget in
app/Filament/Widgets/PostStatsWidget.php
to display statistics like total posts, recent posts, etc.
Outcome:
- A fully functioning Filament admin panel.
- CRUD operations implemented for the
Post
model using Filament. - Role-based access control applied to the admin panel.
- Customized forms, tables, and navigation in the admin panel.
6: APIs in Laravel
Objective:
- Understand the basics of RESTful APIs.
- Build a REST API using Laravel for a resource (e.g.,
Post
). - Implement API authentication using Laravel Sanctum.
- Test the API endpoints with Postman or CURL.
Step 1: Introduction to RESTful APIs
What are RESTful APIs?
- REST (Representational State Transfer) APIs follow a stateless, client-server architecture and use HTTP methods like
GET
,POST
,PUT
, andDELETE
to interact with resources (such as models in Laravel). - Each resource is represented as a URL (endpoint) that the client interacts with.
Common HTTP Methods in REST APIs:
- GET: Retrieve data from the server.
- POST: Send data to the server to create a resource.
- PUT/PATCH: Update an existing resource.
- DELETE: Remove a resource from the server.
Step 2: Creating the API Routes and Controller
Step 2.1: Define API Routes
-
Open
routes/api.php
: Theapi.php
file is where you define all your API routes. By default, these routes are prefixed with/api
. -
Define the Basic API Routes for the
Post
Model: Add the following routes to theapi.php
file for managing thePost
resource:use App\Http\Controllers\API\PostController; Route::middleware('auth:sanctum')->group(function () { Route::get('/posts', [PostController::class, 'index']); Route::post('/posts', [PostController::class, 'store']); Route::get('/posts/{id}', [PostController::class, 'show']); Route::put('/posts/{id}', [PostController::class, 'update']); Route::delete('/posts/{id}', [PostController::class, 'destroy']); });
These routes allow authenticated users to interact with the
Post
model via the API.
Step 2.2: Generate an API Controller
-
Create the API Controller: Use Artisan to generate an API controller for the
Post
model:php artisan make:controller API/PostController --api
This creates a controller in
app/Http/Controllers/API/PostController.php
. -
Implement CRUD Logic in the Controller: Open
PostController.php
and add the following logic:-
Index Method (Retrieve all posts):
public function index() { $posts = Post::all(); return response()->json($posts); }
-
Store Method (Create a new post):
public function store(Request $request) { $validated = $request->validate([ 'title' => 'required|string|max:255', 'content' => 'required|string', ]); $post = Post::create($validated); return response()->json($post, 201); // 201: Resource created }
-
Show Method (Retrieve a single post by ID):
public function show($id) { $post = Post::findOrFail($id); return response()->json($post); }
-
Update Method (Update an existing post):
public function update(Request $request, $id) { $validated = $request->validate([ 'title' => 'required|string|max:255', 'content' => 'required|string', ]); $post = Post::findOrFail($id); $post->update($validated); return response()->json($post); }
-
Destroy Method (Delete a post):
public function destroy($id) { $post = Post::findOrFail($id); $post->delete(); return response()->json(['message' => 'Post deleted successfully'], 200); }
-
Step 3: Setting Up Authentication with Laravel Sanctum
To secure your API, we will use Laravel Sanctum for token-based authentication. Sanctum is a lightweight package that provides API token management and allows authenticated access to API routes.
Step 3.1: Install Laravel Sanctum
-
Install Sanctum: Run the following command to install Laravel Sanctum:
composer require laravel/sanctum
-
Publish Sanctum Configuration: After installation, publish the Sanctum configuration file:
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
-
Run Sanctum Migrations: Run the migrations to create the necessary tables for API tokens:
php artisan migrate
-
Add Sanctum Middleware: To ensure Sanctum handles API authentication, add the
Sanctum
middleware toapi
middleware group inapp/Http/Kernel.php
:'api' => [ \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ],
Step 3.2: Issue API Tokens
-
Create a Route for User Login: Add a route in
routes/api.php
to handle user login and issue an API token:Route::post('/login', function (Request $request) { $credentials = $request->only('email', 'password'); if (Auth::attempt($credentials)) { $user = Auth::user(); $token = $user->createToken('API Token')->plainTextToken; return response()->json(['token' => $token], 200); } return response()->json(['error' => 'Unauthorized'], 401); });
-
Login and Retrieve Token: Use Postman or CURL to send a
POST
request to/api/login
with valid credentials. If successful, you’ll receive an API token that can be used to authenticate subsequent requests.
Step 4: Testing API Endpoints
Step 4.1: Test API Endpoints with Postman or CURL
You can now test your API endpoints using Postman or CURL.
-
Login to Get an API Token: Send a
POST
request tohttp://127.0.0.1:8000/api/login
with the following JSON payload:{ "email": "[email protected]", "password": "password" }
If successful, you will receive a token in the response. Copy this token for use in subsequent requests.
-
Use the Token to Access Protected Routes: In Postman or CURL, send requests to the protected API routes (
/api/posts
,/api/posts/{id}
, etc.) with the token in theAuthorization
header.-
Example CURL Request:
curl -X GET http://127.0.0.1:8000/api/posts \ -H "Authorization: Bearer YOUR_API_TOKEN"
-
Example Postman Request:
- Set the
Authorization
type to "Bearer Token". - Paste the token you received from the login request.
- Send a request to
http://127.0.0.1:8000/api/posts
to get the list of posts.
- Set the
-
Step 4.2: Test Other API Endpoints
Test the following endpoints by sending corresponding requests:
-
Get All Posts (
GET
):curl -X GET http://127.0.0.1:8000/api/posts -H "Authorization: Bearer YOUR_API_TOKEN"
-
Create a New Post (
POST
):curl -X POST http://127.0.0.1:8000/api/posts -H "Authorization: Bearer YOUR_API_TOKEN" \ -d '{"title": "New Post", "content": "This is the content of the new post."}'
-
Update an Existing Post (
PUT
):curl -X PUT http://127.0.0.1:8000/api/posts/1 -H "Authorization: Bearer YOUR_API_TOKEN" \ -d '{"title": "Updated Title", "content": "Updated content."}'
-
Delete a Post (
DELETE
):curl -X DELETE http://127.0.0.1:8000/api/posts/1 -H "Authorization: Bearer YOUR_API_TOKEN"
Step 5: Testing and Error Handling
-
Test Authentication Failures:
- Try accessing protected routes without a token to ensure that they return a
401 Unauthorized
response.
- Try accessing protected routes without a token to ensure that they return a
-
Handle Validation Errors:
- Ensure that invalid data (e.g., missing
title
- Ensure that invalid data (e.g., missing
or content
) triggers validation errors in the API response.
Outcome:
- A fully functioning RESTful API for the
Post
model with CRUD operations. - API token-based authentication implemented using Laravel Sanctum.
- Successful testing of API endpoints using Postman or CURL.
7: Advanced Features - Queues, Jobs, and Task Scheduling
Objective:
- Understand and implement Laravel’s queue system to handle background tasks.
- Create and dispatch jobs to perform tasks asynchronously.
- Set up Laravel's task scheduler to automate recurring tasks.
- Use workers to process queues efficiently.
Step 1: Introduction to Queues and Jobs in Laravel
What are Queues and Jobs?
- Queues allow you to defer the processing of time-consuming tasks, such as sending emails, processing file uploads, or generating reports.
- Jobs are the units of work that you want to run asynchronously. They are placed in a queue and processed by workers.
- Laravel supports various queue drivers, including database, Redis, and Amazon SQS.
When to Use Queues:
- For tasks that take a significant amount of time and would block the HTTP request-response cycle.
- For tasks that need to be processed asynchronously, like sending notifications, file processing, or API calls.
Step 2: Setting Up the Queue System
Laravel has built-in support for queues and can use different backends (drivers) to manage them. For this guide, we'll use the database driver to store the jobs in the database.
Step 2.1: Configure Queue Driver
-
Open the
.env
File: Set the queue driver todatabase
in the.env
file:QUEUE_CONNECTION=database
-
Run the Queue Migration: Laravel provides a migration to create the
jobs
table. Run the migration to set up the table where queued jobs will be stored:php artisan queue:table php artisan migrate
Step 3: Creating and Dispatching Jobs
Step 3.1: Create a Job
-
Generate a Job Class: Use the Artisan command to create a new job:
php artisan make:job SendEmailJob
This will create a job class located in
app/Jobs/SendEmailJob.php
. -
Define Job Logic: Open
app/Jobs/SendEmailJob.php
and define the task to be executed. For example, sending an email:<?php namespace App\Jobs; use App\Mail\NotifyUser; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Mail; class SendEmailJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; protected $user; public function __construct($user) { $this->user = $user; } public function handle() { // Send email Mail::to($this->user->email)->send(new NotifyUser($this->user)); } }
Step 3.2: Dispatch the Job
-
Trigger the Job in a Controller: You can dispatch the job from a controller or anywhere else in your application. For example, in a controller method:
use App\Jobs\SendEmailJob; use App\Models\User; public function sendEmailToUser($userId) { $user = User::find($userId); // Dispatch the job SendEmailJob::dispatch($user); return response()->json(['message' => 'Email queued successfully']); }
This will place the
SendEmailJob
in the queue, and it will be processed asynchronously.
Step 4: Processing the Queue
Step 4.1: Start a Queue Worker
To process queued jobs, you need to run a queue worker that will monitor the queue and execute jobs.
-
Run the Queue Worker: In a separate terminal window, run the following command to start the worker:
php artisan queue:work
This will start processing jobs in the queue. The worker listens for jobs placed in the queue and executes them as they arrive.
-
Test the Queue:
- Trigger the
sendEmailToUser()
method to dispatch a job. - Check that the queue worker processes the job and sends the email (or performs the intended task).
- Trigger the
Step 4.2: Run the Queue Worker in Daemon Mode
For production, it’s common to run the queue worker as a daemon:
php artisan queue:work --daemon
This will keep the worker running indefinitely, processing jobs as they are added to the queue.
Step 5: Task Scheduling in Laravel
Laravel’s task scheduler allows you to schedule recurring tasks like sending out reports, cleaning up old data, or performing backups.
Step 5.1: Setting Up the Task Scheduler
-
Open the
app/Console/Kernel.php
File: Theschedule()
method inside theKernel.php
file defines scheduled tasks. -
Define a Scheduled Task: For example, if you want to clean up old posts daily:
protected function schedule(Schedule $schedule) { $schedule->call(function () { \App\Models\Post::where('created_at', '<', now()->subDays(30))->delete(); })->daily(); }
This will delete posts older than 30 days, every day.
Step 5.2: Running the Scheduler
-
Set Up a Cron Job: To run the Laravel scheduler, you need to set up a cron job on your server. Open your server’s crontab file:
crontab -e
Add the following cron job to run the Laravel scheduler every minute:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
This command runs the Laravel scheduler every minute, allowing it to execute any tasks that are scheduled to run at that time.
Step 6: Handling Failed Jobs
It’s important to handle job failures gracefully. Laravel provides a built-in system to handle failed jobs and retry them.
Step 6.1: Configure Failed Job Handling
-
Run the Failed Job Migration: Laravel provides a migration to create a table for storing failed jobs. Run the migration:
php artisan queue:failed-table php artisan migrate
-
Retry Failed Jobs: If a job fails, you can retry it using the following command:
php artisan queue:retry all
-
Manually View Failed Jobs: You can also view and manage failed jobs using the following commands:
php artisan queue:failed // View failed jobs php artisan queue:forget {job_id} // Forget a failed job
Step 7: Testing and Debugging Jobs and Scheduled Tasks
Step 7.1: Test Queued Jobs
-
Dispatch Jobs and Verify: Dispatch multiple jobs to the queue and verify that the queue worker processes them successfully.
SendEmailJob::dispatch($user);
-
Simulate Job Failures: Introduce a deliberate error in the
SendEmailJob
to simulate a job failure and check that the failed job is recorded.
Step 7.2: Test Scheduled Tasks
-
Test Task Scheduling Locally: Use the
schedule:run
command to manually run the scheduler and verify that your scheduled tasks execute correctly.php artisan schedule:run
-
Check the Cron Job: On production, ensure the cron job runs the scheduler every minute and your tasks are being executed at the defined intervals.
Outcome:
- Queued jobs implemented using Laravel's queue system.
- A working queue worker processing jobs in the background.
- Task scheduling set up for automating recurring tasks.
- Proper handling of failed jobs and job retries.
8: Performance Optimization
Objective:
- Implement caching strategies to reduce load times and database queries.
- Optimize database queries and relationships for better performance.
- Apply general Laravel performance tips to enhance application speed.
Step 1: Caching in Laravel
What is Caching? Caching stores frequently accessed data in memory or disk to reduce repeated queries to the database or calculations, improving the speed of your application.
Laravel supports several caching drivers, such as file
, database
, Memcached
, and Redis
. For this guide, we will focus on file
and Redis
caching.
Step 1.1: Configure Cache Driver
-
Set Cache Driver: Open your
.env
file and set the cache driver. You can usefile
for a basic setup orredis
for a more advanced setup.CACHE_DRIVER=file // For local development, use file caching or CACHE_DRIVER=redis // For advanced caching, use Redis
-
Install Redis (If Using Redis): If you are using Redis for caching, ensure that Redis is installed locally or on your server. You can install it with:
sudo apt install redis-server
-
Install PHP Redis Extension: If Redis is not already installed, use Composer to install the Redis package:
composer require predis/predis
Step 1.2: Cache Data in Your Application
-
Caching Database Queries: Instead of hitting the database every time for common queries, you can cache the results. Use the
cache()
helper in Laravel to store and retrieve cached data.For example, cache a list of posts:
use Illuminate\Support\Facades\Cache; public function getAllPosts() { $posts = Cache::remember('posts', 60, function () { return Post::all(); // Query is only executed if cache is empty }); return $posts; }
This will store the result of the
Post::all()
query in the cache for 60 seconds. Subsequent calls within this time will return the cached result, avoiding additional database queries. -
Remove Cache when Data Changes: When the data changes (like when a post is added, updated, or deleted), you should clear the relevant cache:
Cache::forget('posts');
Step 1.3: Cache API Responses
For heavy API responses, you can cache the response to reduce processing time:
-
Cache API Response:
use Illuminate\Support\Facades\Cache; public function index() { $response = Cache::remember('api.posts', 3600, function () { return response()->json(Post::all()); }); return $response; }
This will cache the API response for an hour (3600 seconds).
Step 2: Database Query Optimization
Step 2.1: Use Eager Loading to Prevent N+1 Query Problem
The N+1 query problem happens when you fetch a model with related models, and each related model triggers a separate query. Eager loading helps to avoid this by loading related models in a single query.
-
Eager Load Relationships: In your controller or query, use
with()
to eager load relationships:$posts = Post::with('comments')->get(); // This will load posts and their comments in one query
Without eager loading, if you loop over the posts and access
comments
, it will trigger a query for each post.
Step 2.2: Use Select Statements to Limit Columns
If you don't need all columns from a table, retrieve only the necessary ones to reduce the size of the query result.
-
Limit Columns in a Query: Instead of retrieving all fields with
*
, specify the columns you need:$posts = Post::select('id', 'title', 'created_at')->get();
This reduces the load on the database and speeds up the query.
Step 2.3: Paginate Results
For large datasets, paginate the results to avoid loading too much data at once.
-
Paginate Queries: Instead of fetching all records, use pagination to limit the number of records retrieved at once:
$posts = Post::paginate(10); // Fetches 10 posts at a time
Pagination not only improves performance but also enhances user experience by loading data in chunks.
Step 3: Optimize Laravel Code
Step 3.1: Minimize Middleware Use
Middleware can add unnecessary overhead if used too often. Ensure middleware is only applied where absolutely necessary.
- Use Middleware Groups:
Laravel allows you to group middleware, reducing the overhead:
Route::middleware(['web', 'auth'])->group(function () { Route::get('/dashboard', [DashboardController::class, 'index']); });
Step 3.2: Use Chunk()
for Processing Large Data Sets
When working with large datasets, processing them in chunks can significantly reduce memory usage.
-
Process Data in Chunks: Instead of retrieving all records at once, process them in smaller chunks:
Post::chunk(100, function ($posts) { foreach ($posts as $post) { // Process each post } });
This reduces memory consumption and improves performance.
Step 4: Use Laravel Optimization Commands
Laravel provides a number of Artisan commands to optimize the application.
Step 4.1: Config and Route Caching
Caching configurations and routes can improve the performance of your application by reducing the need to parse the config and route files repeatedly.
-
Cache Configuration Files: Run the following command to cache your configuration files:
php artisan config:cache
-
Cache Routes: To speed up routing, cache your routes:
php artisan route:cache
Step 4.2: Optimize Class Autoloading
You can optimize the class autoloader for faster application loading using:
composer dump-autoload --optimize
Step 5: Use OPcache for PHP Optimization
OPcache improves PHP performance by storing precompiled script bytecode in memory, thus eliminating the need for PHP to load and parse scripts on each request.
Step 5.1: Enable OPcache
-
Install and Enable OPcache: On most systems, you can install OPcache via PHP extensions. On Ubuntu, for example:
sudo apt-get install php-opcache
-
Configure OPcache in
php.ini
: Ensure OPcache is enabled in your PHP configuration:opcache.enable=1 opcache.memory_consumption=128 opcache.max_accelerated_files=10000 opcache.revalidate_freq=2
Step 6: Testing and Profiling Performance
Step 6.1: Use Laravel Telescope (Optional)
Laravel Telescope is a debugging assistant that provides insights into your application’s performance, including queries, requests, and jobs.
-
Install Laravel Telescope:
composer require laravel/telescope php artisan telescope:install php artisan migrate
-
Use Telescope to Monitor Performance: Visit
/telescope
to view performance metrics for requests, queries, and jobs.
Step 6.2: Use Blackfire or Xdebug for Profiling
Tools like Blackfire or Xdebug can help profile your application and identify bottlenecks.
-
Install Blackfire: You can install Blackfire (a paid service) for profiling PHP applications: https://blackfire.io/docs
-
Use Xdebug for Local Profiling: Set up Xdebug to profile your Laravel application and identify performance bottlenecks.
Step 7: Testing Performance Optimizations
After implementing each performance optimization, test the results to ensure they have a positive impact.
-
Test Before and After:
- Measure the load times and response times before applying optimizations.
- Apply the optimizations incrementally and measure the impact after each change.
-
Test with Large Datasets: Use large datasets in your application to ensure that your queries, caching, and chunking strategies work effectively under high load.
Outcome:
- Caching strategies implemented for common queries and API responses.
- Database queries optimized using eager loading, pagination, and chunking.
- Laravel's Artisan optimization commands applied to speed up the application.
- OPcache enabled to optimize PHP performance.
Day 9: Filament Deep Dive and Custom Widgets
Objective:
- Understand how to create custom widgets in Filament.
- Build a custom dashboard with widgets displaying important metrics.
- Customize the Filament admin panel's appearance and behavior.
- Implement role-based access to specific widgets.
Step 1: Introduction to Filament Customization
Filament is a highly customizable admin panel for Laravel, allowing you to create your own widgets and dashboards. Today, we’ll focus on creating custom widgets and using them on the admin dashboard to display useful data such as recent posts, user statistics, or other business-specific metrics.
What are Widgets in Filament? Widgets in Filament allow you to present information or metrics in a visually organized manner. You can place widgets on dashboards or custom pages.
Step 2: Create a Custom Widget in Filament
Let’s create a custom widget that displays statistics about the posts in the system.
Step 2.1: Generate a Widget Class
-
Use Artisan to Create a New Widget: Run the following command to generate a widget:
php artisan make:filament-widget PostStatsWidget
This will create a widget class located at
app/Filament/Widgets/PostStatsWidget.php
. -
Define Widget Content: Open
PostStatsWidget.php
and customize the widget’srender()
method. This widget will display the total number of posts:<?php namespace App\Filament\Widgets; use App\Models\Post; use Filament\Widgets\Widget; class PostStatsWidget extends Widget { protected static string $view = 'filament.widgets.post-stats-widget'; public function getData(): array { return [ 'postCount' => Post::count(), ]; } }
-
Create the Widget Blade View: Create a view for the widget in the
resources/views/filament/widgets
directory and name itpost-stats-widget.blade.php
:<x-filament::widget> <x-filament::card> <h2 class="text-xl font-bold">Total Posts: {{ $postCount }}</h2> </x-filament::card> </x-filament::widget>
Step 2.2: Display Widget on the Dashboard
To display this widget on the dashboard, open app/Filament/Resources/DashboardResource.php
(or wherever your main dashboard is defined) and register the widget:
-
Modify the Dashboard to Include the Widget: In the
app/Filament/Pages/Dashboard.php
file (or similar file if the dashboard is elsewhere), add the widget:use App\Filament\Widgets\PostStatsWidget; public static function getWidgets(): array { return [ PostStatsWidget::class, ]; }
-
Test the Widget: Visit the admin dashboard at
http://127.0.0.1:8000/admin
. You should see the custom widget showing the total number of posts.
Step 3: Adding Multiple Widgets to the Dashboard
Widgets can display various types of information, such as user statistics, recent activities, or other metrics.
Step 3.1: Create More Widgets
-
User Stats Widget: Create another widget for displaying the total number of users:
php artisan make:filament-widget UserStatsWidget
-
Define Widget Logic: Open
UserStatsWidget.php
and define the logic to get the number of users:<?php namespace App\Filament\Widgets; use App\Models\User; use Filament\Widgets\Widget; class UserStatsWidget extends Widget { protected static string $view = 'filament.widgets.user-stats-widget'; public function getData(): array { return [ 'userCount' => User::count(), ]; } }
-
Create the View for User Stats: Create a new view for the
UserStatsWidget
atresources/views/filament/widgets/user-stats-widget.blade.php
:<x-filament::widget> <x-filament::card> <h2 class="text-xl font-bold">Total Users: {{ $userCount }}</h2> </x-filament::card> </x-filament::widget>
-
Add the Widget to the Dashboard: Add this widget to the dashboard as well:
use App\Filament\Widgets\UserStatsWidget; public static function getWidgets(): array { return [ PostStatsWidget::class, UserStatsWidget::class, ]; }
-
Test Multiple Widgets: Visit the dashboard to see both the post and user stats widgets displayed.
Step 4: Customizing the Widget Layout
You can further customize how the widgets are displayed, including changing the layout and adding CSS or JavaScript for more interactive elements.
Step 4.1: Organize Widgets in a Grid Layout
-
Define Grid Layout in Dashboard View: You can customize the layout of the dashboard by organizing the widgets in a grid. Open the
Dashboard.php
file and define a grid layout:public static function getWidgets(): array { return [ PostStatsWidget::class => [ 'columnSpan' => 'full', ], UserStatsWidget::class => [ 'columnSpan' => 2, // Span two columns ], ]; }
-
Customize Widget Blade Files: Adjust the Blade files to fit the grid layout, applying CSS for better alignment. You can use Tailwind CSS classes since Filament uses Tailwind for styling.
Step 5: Role-Based Access to Widgets
Filament allows you to control access to specific widgets based on user roles.
Step 5.1: Restrict Widget Access Based on Role
-
Modify the Widget Class: In the
PostStatsWidget.php
andUserStatsWidget.php
files, you can restrict access to the widgets based on the user’s role:public static function canView(): bool { return auth()->user()->role === 'admin'; // Only admins can see this widget }
-
Test Role-Based Access:
- Log in as an admin user and check that both widgets are visible.
- Log in as a regular user and verify that the widgets are not displayed.
Step 6: Adding Custom Actions to Widgets
Widgets can also have custom actions, such as buttons that perform specific tasks (e.g., sending reports or clearing cache).
Step 6.1: Add a Button to the Post Stats Widget
-
Modify the Widget to Include a Button: Open the
PostStatsWidget
and modify it to include a button that clears the post cache:public function clearPostCache() { Cache::forget('posts'); $this->notify('success', 'Post cache cleared!'); }
-
Update the Widget View: In
post-stats-widget.blade.php
, add a button that triggers the cache clearing action:<x-filament::widget> <x-filament::card> <h2 class="text-xl font-bold">Total Posts: {{ $postCount }}</h2> <x-filament::button wire:click="clearPostCache">Clear Cache</x-filament::button> </x-filament::card> </x-filament::widget>
-
Test Custom Actions: Visit the admin panel and click the "Clear Cache" button. Check that the post cache is cleared and the user is notified of the success.
Step 7: Testing and Debugging Custom Widgets
-
Test Widget Functionality:
- Test all widgets to ensure they display correct data.
- Verify that any custom actions work as expected.
-
Test Role-Based Access: Ensure that the widgets are only visible to users with the appropriate roles.
-
Debugging: Use Laravel’s
telescope
orlog
functionality to debug any issues with data retrieval, widget rendering, or custom actions.
Step 8: Further Customization (Optional)
-
Custom Widget Styles: Customize the look and feel of widgets by adding CSS to the Blade views or using Tailwind classes.
-
Dynamic Widgets: Implement more dynamic widgets, such as charts or graphs, using JavaScript libraries like Chart.js or D3.js.
-
Create Custom Pages: Beyond widgets, Filament allows you to create fully custom pages for more complex use cases. Use the
make:filament-page
Artisan command to generate a new page.
Oucome:
- Custom widgets for the admin dashboard displaying key statistics (e.g., post and user stats).
- Custom actions integrated into widgets (e.g., clearing the cache).
- Role-based access control applied to specific widgets.
- A customized and more user-friendly Filament dashboard.
Final task that we have to create https://gist.github.com/YugalXD/b60238777651d298e3f17b795b70e6c1