Sign In Create Account
Key Principles

Laravel Key Principles

The foundational principles that guide all Laravel development decisions.

Follow Laravel's Intended Approach

“First and foremost, Laravel provides the most value when you write things the way Laravel intended.” This principle should guide every development decision.

  • • Use Laravel's built-in features before reaching for third-party packages
  • • Follow Laravel's naming conventions and directory structure
  • • Leverage Laravel's service container and dependency injection
  • • Use Eloquent relationships as designed
  • • Always have a strong justification for deviating from Laravel's defaults

Example

// ✅ Use Laravel's intended approach
class UserController extends Controller
{
    public function store(StoreUserRequest $request)
    {
        $user = User::create($request->validated());
        
        return redirect()->route('users.show', $user);
    }
}

// ❌ Fighting against Laravel's conventions  
class UserController extends Controller
{
    public function store(Request $request)
    {
        // Manual validation instead of Form Request
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users',
        ]);
        
        if ($validator->fails()) {
            return back()->withErrors($validator);
        }
        
        // Direct database calls instead of Eloquent
        DB::table('users')->insert([
            'name' => $request->name,
            'email' => $request->email,
        ]);
        
        return back();
    }
}

Write Expressive, Self-Documenting Code

Code should clearly communicate its intent without requiring extensive comments or documentation.

  • • Use descriptive method and variable names
  • • Break complex operations into smaller, named methods
  • • Prefer explicit over implicit behavior
  • • Use type hints and return types
  • • Structure code to tell a story

Example

// ✅ Expressive and self-documenting
class SubscriptionService
{
    public function renewSubscription(User $user): Subscription
    {
        $this->ensureUserCanRenew($user);
        $this->cancelPendingRenewal($user);
        
        return $this->createRenewalSubscription($user);
    }
    
    private function ensureUserCanRenew(User $user): void
    {
        if (! $user->hasActiveSubscription()) {
            throw new InvalidSubscriptionState('User must have active subscription to renew');
        }
    }
    
    private function cancelPendingRenewal(User $user): void
    {
        $user->subscriptions()
            ->where('status', 'pending_renewal')
            ->update(['status' => 'cancelled']);
    }
    
    private function createRenewalSubscription(User $user): Subscription
    {
        return $user->subscriptions()->create([
            'plan_id' => $user->currentSubscription()->plan_id,
            'starts_at' => $user->currentSubscription()->ends_at,
            'ends_at' => $user->currentSubscription()->ends_at->addMonth(),
            'status' => 'active',
        ]);
    }
}

// ❌ Unclear intent, requires comments
class SubscriptionService  
{
    public function renew($u)  // Renew what? For who?
    {
        // Check if user can renew
        if (! $u->sub || $u->sub->status !== 'active') {
            throw new Exception('Cannot renew');
        }
        
        // Cancel existing pending renewals
        DB::table('subscriptions')
            ->where('user_id', $u->id)
            ->where('status', 'pending')
            ->update(['status' => 'cancelled']);
        
        // Create new subscription
        return DB::table('subscriptions')->insertGetId([
            'user_id' => $u->id,
            'plan_id' => $u->sub->plan_id,
            'starts_at' => $u->sub->ends_at,
            'ends_at' => Carbon::parse($u->sub->ends_at)->addMonth(),
            'status' => 'active',
        ]);
    }
}

Justify Deviations from Defaults

When you need to deviate from Laravel's defaults, always have a clear, documented reason.

  • • Document why the deviation is necessary
  • • Consider performance, security, or business requirements
  • • Evaluate if the deviation could be temporary
  • • Ensure the team understands the reasoning
  • • Regularly review deviations to see if they're still needed

Example

// ✅ Justified deviation with clear documentation
class ReportController extends Controller
{
    /**
     * Generate large reports using raw SQL for performance.
     *
     * We deviate from Eloquent here because:
     * - Reports involve complex joins across 5+ tables
     * - Dataset can exceed 100k records
     * - Eloquent ORM adds 2-3x memory overhead
     * - Report generation time reduced from 45s to 8s
     *
     * Review: Consider moving to dedicated reporting service
     * if this pattern spreads to other controllers.
     */
    public function generateAnnualReport(): Response
    {
        \$sql = "
            SELECT u.name, COUNT(o.id) as order_count, SUM(o.total) as revenue
            FROM users u
            JOIN orders o ON u.id = o.user_id
            WHERE o.created_at >= ? AND o.status = 'completed'
            GROUP BY u.id
            HAVING order_count > 10
            ORDER BY revenue DESC
        ";

        \$data = DB::select(\$sql, [now()->subYear()]);

        return response()->json(\$data);
    }
}

// ❌ Unexplained deviation
class ReportController extends Controller
{
    public function generateReport()
    {
        // Just using raw SQL because it's faster
        \$data = DB::select("SELECT * FROM users JOIN orders...");
        return response()->json(\$data);
    }
}