🐘

PHP / Laravel

Laravel framework, Eloquent ORM, queues, testing, and modern PHP practices.

Laravel Service Container

The **Service Container** is Laravel's powerful tool for managing class dependencies and performing dependency injection. **Key Concepts:** - **Binding** - Register how to resolve a class - **Resolving** - Get instance from container - **Autowiring** - Automatic resolution of type-hinted dependencies - **Contextual Binding** - Different implementations based on context
// Service Provider binding
class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        // Simple binding
        $this->app->bind(PaymentInterface::class, StripePayment::class);

        // Singleton
        $this->app->singleton(CacheService::class, function ($app) {
            return new CacheService($app->make('redis'));
        });

        // Contextual binding
        $this->app->when(OrderController::class)
            ->needs(PaymentInterface::class)
            ->give(StripePayment::class);
    }
}

Eloquent Relationships

**Eloquent ORM** provides expressive relationships: - **hasOne / belongsTo** - One-to-one - **hasMany / belongsTo** - One-to-many - **belongsToMany** - Many-to-many (pivot table) - **hasOneThrough / hasManyThrough** - Distant relations - **morphOne / morphMany** - Polymorphic relations **Performance Tips:** - Use eager loading (with()) to avoid N+1 queries - Use withCount() for counting relations - Use lazy loading judiciously
// Eager loading example
class Post extends Model
{
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }

    public function author()
    {
        return $this->belongsTo(User::class, 'user_id');
    }
}

// Bad: N+1 queries
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->author->name; // Query per post!
}

// Good: Eager loading
$posts = Post::with(['author', 'comments'])->get();
foreach ($posts as $post) {
    echo $post->author->name; // No extra queries
}

// With counts
$posts = Post::withCount('comments')
    ->having('comments_count', '>', 10)
    ->get();

Laravel Queues

**Queues** allow deferring time-consuming tasks like sending emails. **Drivers:** Database, Redis, SQS, Beanstalkd **Key Concepts:** - **Jobs** - Define the task to be queued - **Dispatching** - Send job to queue - **Workers** - Process queued jobs - **Failed Jobs** - Handle job failures - **Batching** - Process multiple jobs together
// Job class
class ProcessPodcast implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $tries = 3;
    public $backoff = [60, 300, 600]; // Exponential backoff

    public function __construct(
        public Podcast $podcast
    ) {}

    public function handle(AudioProcessor $processor)
    {
        $processor->process($this->podcast);
    }

    public function failed(Throwable $exception)
    {
        // Handle failure
        Log::error('Podcast processing failed', [
            'podcast_id' => $this->podcast->id,
            'error' => $exception->getMessage(),
        ]);
    }
}

// Dispatching
ProcessPodcast::dispatch($podcast)
    ->onQueue('podcasts')
    ->delay(now()->addMinutes(10));

// Chaining jobs
Bus::chain([
    new ProcessPodcast($podcast),
    new NotifySubscribers($podcast),
    new UpdateStatistics($podcast),
])->dispatch();

Query Optimization

**Database Performance Tips:** 1. **Indexes** - Add indexes on frequently queried columns 2. **Select only needed columns** - Avoid SELECT * 3. **Chunk large datasets** - Process in batches 4. **Use raw queries** for complex operations 5. **Cache repeated queries** - Use remember()
// Chunking for large datasets
User::chunk(1000, function ($users) {
    foreach ($users as $user) {
        $user->processData();
    }
});

// Lazy collection for memory efficiency
User::lazy()->each(function ($user) {
    $user->processData();
});

// Query caching
$users = Cache::remember('active_users', 3600, function () {
    return User::where('active', true)
        ->select(['id', 'name', 'email'])
        ->get();
});

// Raw queries for complex operations
$results = DB::select("
    SELECT users.name, COUNT(orders.id) as order_count
    FROM users
    LEFT JOIN orders ON users.id = orders.user_id
    WHERE orders.created_at > ?
    GROUP BY users.id
    HAVING order_count > 5
", [now()->subMonth()]);

📝 More Laravel content coming soon - Middleware, Testing, API Resources...