Hey Laravel developers! π
After years of building Laravel applications (from corporate projects to indie SaaS solutions), I've learned some hard lessons that could save you serious debugging time. Here are 5 practical tips that have made my development workflow much smoother.
1. Always Use Database Transactions for Multi-Step Operations
// β Without transaction - risky
$user = User::create($userData);
$profile = Profile::create(['user_id' => $user->id]);
$subscription = Subscription::create(['user_id' => $user->id]);
// β
With transaction - safe
DB::transaction(function () use ($userData) {
$user = User::create($userData);
$profile = Profile::create(['user_id' => $user->id]);
$subscription = Subscription::create(['user_id' => $user->id]);
});
Why this matters: I once spent 3 hours debugging why some users had accounts but no profiles. One database operation was failing silently, leaving data in an inconsistent state.
2. Use Laravel's Query Builder Log for Performance Issues
// Add this to your route or controller for debugging
DB::listen(function ($query) {
Log::info($query->sql, $query->bindings);
});
// Or get all queries for a specific request
DB::enableQueryLog();
// Your code here
dd(DB::getQueryLog());
Pro tip: This saved me when a simple-looking Eloquent query was generating 50+ SQL queries due to N+1 problems.
3. Create Custom Validation Rules for Business Logic
Instead of cluttering your controllers:
// Create: php artisan make:rule ValidPhoneNumber
class ValidPhoneNumber implements Rule
{
public function passes($attribute, $value)
{
// Your Indian phone number validation logic
return preg_match('/^[6-9]\d{9}$/', $value);
}
public function message()
{
return 'Please enter a valid Indian mobile number.';
}
}
// Usage in your request
'phone' => ['required', new ValidPhoneNumber],
Why this rocks: Reusable, testable, and keeps your controllers clean. Perfect for region-specific validations!
4. Use Laravel's Built-in Cache for Expensive Operations
// β Hits database every time
$popularPosts = Post::where('views', '>', 1000)->get();
// β
Cache for 1 hour
$popularPosts = Cache::remember('popular_posts', 3600, function () {
return Post::where('views', '>', 1000)->get();
});
// β
Even better - cache with tags for easy clearing
$popularPosts = Cache::tags(['posts'])->remember('popular_posts', 3600, function () {
return Post::where('views', '>', 1000)->get();
});
// Clear when posts are updated
Cache::tags(['posts'])->flush();
Real impact: Reduced my hospital management SaaS dashboard load time from 3 seconds to 200ms.
5. Create Seeders for Different Environments
// DatabaseSeeder.php
public function run()
{
if (App::environment('local')) {
$this->call([
UserSeeder::class,
TestDataSeeder::class, // Lots of fake data
]);
}
if (App::environment(['local', 'staging'])) {
$this->call([
DemoDataSeeder::class, // Clean demo data
]);
}
// Always run these
$this->call([
RoleSeeder::class,
PermissionSeeder::class,
]);
}
Game changer: No more accidentally seeding production with test data, and my local environment always has realistic data to work with.
Bonus Tip: Use Laravel Telescope in Development
If you're not using Telescope yet, you're missing out:
composer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate
It's like having X-ray vision for your Laravel app - see every query, request, job, and cache operation in real-time.
Your Turn!
What's your favorite Laravel tip that saved you hours of debugging? Drop it in the comments below!
And if you found this helpful, follow me for more Laravel insights from my journey building SaaS solutions and CodeCanyon plugins from rural Gujarat! π
Happy coding! β¨
Building Laravel solutions from Jam Kalyanpur, Gujarat. Connect with me at hardikkanajariya.in
Top comments (0)