Table of contents
- Laravel Best Practices
- Laravel Naming Conventions
Laravel Best Practices
1. Database & Eloquent Best Practices
1.1 Optimize Database Queries
// ❌ Bad: N+1 Query Problem
@foreach (Post::all() as $post)
{{ $post->category->name }}
@endforeach
// ✅ Good: Eager Loading
$posts = Post::with('category')->get();
@foreach ($posts as $post)
{{ $post->category->name }}
@endforeach
// ✅ Even Better: Use Laravel's Lazy Loading when needed
Model::withoutLazy()->get(); // Disable lazy loading in production
1.2 Use Query Builder for Complex Queries
// ✅ Good: Use Query Builder for complex queries
User::query()
->select(['name', 'email'])
->whereHas('posts', function ($query) {
$query->where('published', true);
})
->paginate();
2. Modern Controller Practices
2.1 Use Invokable Controllers for Single-Action Controllers
// ✅ Good: Single Action Controller
class ShowDashboardController extends Controller
{
public function __invoke()
{
return view('dashboard', [
'metrics' => $this->getMetrics(),
]);
}
}
2.2 Use Form Requests for Validation
// ❌ Bad: Validation in Controller
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|max:255',
'body' => 'required',
]);
}
// ✅ Good: Dedicated Form Request
class StoreArticleRequest extends FormRequest
{
public function rules(): array
{
return [
'title' => ['required', 'string', 'max:255'],
'body' => ['required', 'string'],
'category_id' => ['required', 'exists:categories,id'],
];
}
}
public function store(StoreArticleRequest $request)
{
$article = Article::create($request->validated());
}
3. Modern Architecture Patterns
3.1 Use Actions Classes for Business Logic
// ✅ Good: Single-Purpose Action Class
class PublishArticleAction
{
public function execute(Article $article): void
{
$article->published_at = now();
$article->status = ArticleStatus::Published;
$article->save();
event(new ArticlePublished($article));
}
}
3.2 Use Data Transfer Objects (DTOs)
// ✅ Good: Use DTOs for complex data structures
class ArticleData
{
public function __construct(
public readonly string $title,
public readonly string $content,
public readonly ?Carbon $publishDate = null,
) {}
public static function fromRequest(StoreArticleRequest $request): self
{
return new self(
title: $request->validated('title'),
content: $request->validated('content'),
publishDate: $request->validated('publish_date'),
);
}
}
4. Modern View & Frontend Practices
4.1 Use Blade Components
// ✅ Good: Reusable Blade Components
// alert.blade.php
<x-alert type="{{ $type }}" :dismissible="$dismissible">
{{ $slot }}
</x-alert>
// Usage
<x-alert type="success" :dismissible="true">
Profile updated successfully!
</x-alert>
4.2 Use Laravel Vite for Asset Management
// ✅ Good: Modern Asset Management
// vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
],
});
// In Blade
@vite(['resources/css/app.css', 'resources/js/app.js'])
5. Modern Testing Practices
5.1 Use Pest for Testing
// ✅ Good: Modern Testing with Pest
it('creates a new article', function () {
$response = post('/articles', [
'title' => 'My Article',
'content' => 'Content here',
]);
$response->assertCreated();
expect(Article::count())->toBe(1);
});
5.2 Use Factories Effectively
// ✅ Good: Modern Factory Usage
class ArticleFactory extends Factory
{
public function published(): self
{
return $this->state(fn (array $attributes) => [
'published_at' => now(),
'status' => ArticleStatus::Published,
]);
}
}
// Usage
Article::factory()->published()->create();
6. API Development
6.1 Use API Resources
// ✅ Good: Use API Resources for Response Transformation
class ArticleResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'content' => $this->when($request->user()?->isAdmin(), $this->content),
'created_at' => $this->created_at->toISOString(),
];
}
}
6.2 Use Sanctum for API Authentication
// ✅ Good: Modern API Authentication
Route::middleware(['auth:sanctum'])->group(function () {
Route::apiResource('articles', ArticleController::class);
});
7. Performance Best Practices
7.1 Use Cache Effectively
// ✅ Good: Smart Caching
public function show(Article $article)
{
return Cache::remember("articles.{$article->id}", now()->addHour(), fn () =>
ArticleResource::make($article)
);
}
7.2 Use Queue for Heavy Tasks
// ✅ Good: Queue Heavy Operations
class ProcessPodcast implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function handle(): void
{
// Heavy processing here
}
}
8. Security Best Practices
8.1 Use Policy Classes
// ✅ Good: Use Policies for Authorization
class ArticlePolicy
{
public function update(User $user, Article $article): bool
{
return $user->id === $article->user_id || $user->isAdmin();
}
}
8.2 Secure Configuration
// ❌ Bad: Direct Environment Variable Usage
$apiKey = env('API_KEY');
// ✅ Good: Use Configuration Files
// config/services.php
'api' => [
'key' => env('API_KEY'),
],
// Usage
$apiKey = config('services.api.key');
9. Code Organization
9.1 Use Laravel's Directory Structure
app/
├── Actions/ # Single-purpose action classes
├── Data/ # DTOs and other data objects
├── Events/ # Event classes
├── Listeners/ # Event listeners
├── Services/ # Complex business logic
├── Http/
│ ├── Controllers/
│ ├── Middleware/
│ └── Requests/ # Form requests
└── Models/ # Eloquent models
9.2 Use Service Providers for Bootstrap Code
// ✅ Good: Register Bindings in Service Provider
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->singleton(PaymentGateway::class, StripeGateway::class);
}
}
10. Development Workflow
10.1 Use Laravel Sail for Development
# ✅ Good: Use Laravel Sail for consistent development environment
sail up
sail artisan migrate
sail test
10.2 Use GitHub Actions for CI/CD
# ✅ Good: Automated Testing and Deployment
name: Laravel
on:
push:
branches: [ main ]
jobs:
laravel-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
- name: Run Tests
run: |
composer install
php artisan test
Laravel Naming Conventions
The following table outlines the standard naming conventions for Laravel applications in 2024:
Component | Convention | ✅ Good Example | ❌ Bad Example | Notes |
Controller | singular | PostController | PostsController | Use singular form for resource controllers |
Route | plural | posts/1 | post/1 | Use plural for resource routes |
Named route | snake_case with dots | users.show _active | show-active-users | Consistent with Laravel's internal naming |
Model | singular | User | Users | Always use singular for model names |
hasOne/belongsTo relationship | singular | postComment | postComments | Reflects one-to-one nature |
Other relationships | plural | postComments | postComment | Reflects one-to-many nature |
Database table | plural | post_comments | post_comment | Use snake_case, plural form |
Pivot table | alphabetical singular models | post_user | users_posts | Join singular model names with underscore |
Model property | snake_case | $model->created_at | $model->createdAt | Follow Laravel's convention |
Foreign key | singular with _id | post_id | PostId , posts_id | Always use snake_case |
Primary key | 'id' | id | custom_id | Stick to Laravel defaults |
Migration | datetime_action | 2024_01_16_000000_create_posts_table | 2024_01_16_posts | Include full timestamp |
Method | camelCase | getAll() | get_all() | Follow PSR-12 |
Resource controller method | table | store() | savePost() | Use standard resource names |
Variable | camelCase | $postsWithAuthor | $posts_with_creator | Clear and descriptive |
Collection | plural, descriptive | $activeUsers | $active | Clearly indicate content |
Object | singular, descriptive | $activeUser | $users | Reflect single instance |
Config index | snake_case | articles_enabled | ArticlesEnabled | Consistent with Laravel |
View | kebab-case | show-filtered.blade.php | showFiltered.blade.php | Use hyphens for views |
Config file | snake_case | google_calendar.php | googleCalendar.php | Use underscores |
Interface | adjective/noun | AuthenticationInterface | IAuthentication | Follow PSR standards |
Important Notes on Naming Conventions:
Consistency is Key
Stick to these conventions across your entire application
Use automated tools like PHP CS Fixer to enforce standards
Documentation
// ✅ Good: Clear, consistent naming class PostController { public function show(Post $post) { return view('posts.show', compact('post')); } }
File Structure
app/ ├── Http/ │ └── Controllers/ │ └── PostController.php ├── Models/ │ └── Post.php └── Views/ └── posts/ └── show-details.blade.php
Database Conventions
// ✅ Good: Migration naming class CreatePostCommentsTable extends Migration { public function up() { Schema::create('post_comments', function (Blueprint $table) { $table->id(); $table->foreignId('post_id')->constrained(); $table->timestamps(); }); } }
Relationship Naming
// ✅ Good: Clear relationship naming class Post extends Model { public function comments() { return $this->hasMany(Comment::class); } public function author() { return $this->belongsTo(User::class, 'user_id'); } }
Following these naming conventions helps maintain consistency across your Laravel application and makes it easier for other developers to understand and work with your code. It also aligns with Laravel's built-in conventions, ensuring better integration with the framework's features and functionality.
Remember to:
Use PHP 8.2+ features where appropriate
Keep dependencies updated
Follow PSR-12 coding standards
Use static analysis tools like PHPStan
Implement proper logging and monitoring
Use Laravel Horizon for queue monitoring
Implement proper error handling and logging
Use Laravel Telescope for debugging in development
These practices reflect modern Laravel development as of 2024, incorporating new features and best practices from recent Laravel versions.