Laravel ‐ Chapter 18‐19 - pierre-akhrass/Lavarel-Docs GitHub Wiki

Chapter 18: Relationships in Laravel

Laravel Eloquent provides an expressive and convenient way to interact with your database using relationships. In this chapter, we cover:

  • One-to-One Relationships
  • One-to-Many Relationships
  • Many-to-Many Relationships
  • Polymorphic Relationships

One-to-One Relationships

A one-to-one relationship is used when a record in one table is associated with exactly one record in another table (e.g., a User has one Profile).

Example:

Profile Model:

class Profile extends Model
{
    public function user() {
        return $this->belongsTo(User::class);
    }
}

This indicates the profile table contains the foreign key (user_id).

Migration:

php artisan make:migration create_profiles_table

Inside the Migration:

Schema::create('profiles', function (Blueprint $table) {
    $table->id();
    $table->unsignedBigInteger('user_id');
    $table->string('avatar');
    $table->string('address')->nullable();
    $table->timestamps();

    $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
    // Alternative modern syntax:
    // $table->foreignId('user_id')->constrained()->onDelete('cascade');
});

User Model:

class User extends Model
{
    public function profile() {
        return $this->hasOne(Profile::class);
    }
}

Usage:

$user = User::find(1);
$profile = $user->profile;

$profile = Profile::find(1);
$user = $profile->user;

One-to-Many Relationships

In a one-to-many relationship, one record is associated with many records in another table. For example, a Category has many Posts.

Example:

Category Model:

class Category extends Model
{
    public function posts() {
        return $this->hasMany(Post::class);
    }
}

Post Model:

class Post extends Model
{
    public function category() {
        return $this->belongsTo(Category::class);
    }
}

Usage:

$category = Category::find(1);
$posts = $category->posts;

$post = Post::find(1);
$category = $post->category;

Many-to-Many Relationships

In a many-to-many relationship, multiple records in one table can be related to multiple records in another table (e.g., Posts and Tags).

Migration:

php artisan make:migration create_post_tag_table
php artisan make:model Tag

Migration file:

Schema::create('tags', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->timestamps();
});

Schema::create('post_tag', function (Blueprint $table) {
    $table->id();
    $table->unsignedBigInteger('post_id');
    $table->unsignedBigInteger('tag_id');
    $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
    $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
});

Post Model:

class Post extends Model
{
    public function tags() {
        return $this->belongsToMany(Tag::class);
    }
}

Tag Model:

class Tag extends Model
{
    public function posts() {
        return $this->belongsToMany(Post::class);
    }
}

Usage:

$post = Post::find(1);
$tags = $post->tags;

$tag = Tag::find(1);
$posts = $tag->posts;

Managing Relationships:

$post->tags()->attach(1);               // attach tag with id 1
$tag->posts()->detach(790);            // remove relationship with post id 790
$tag->posts()->sync([79, 80]);         // sync relationships

Why parentheses in method call?

  • $tag->posts returns a Collection
  • $tag->posts() returns a Relationship instance for performing DB operations

Polymorphic Relationships

Polymorphic relationships allow a model to belong to more than one type of model on a single association (e.g., Images attached to either Posts or Users).

Example: One-to-One Polymorphic

Database Structure:

images table:
- id
- url
- imageable_id
- imageable_type

Models:

Image Model:

class Image extends Model
{
    public function imageable(): MorphTo {
        return $this->morphTo();
    }
}

Post/User Model:

public function image(): MorphOne {
    return $this->morphOne(Image::class, 'imageable');
}

Example: Many-to-Many Polymorphic

Migration:

php artisan make:migration create_taggables_table
Schema::create('taggables', function (Blueprint $table) {
    $table->id();
    $table->unsignedBigInteger('tag_id');
    $table->unsignedBigInteger('taggable_id');
    $table->string('taggable_type');
    $table->timestamps();
});

Models:

Tag Model:

public function posts() {
    return $this->morphedByMany(Post::class, 'taggable');
}

public function videos() {
    return $this->morphedByMany(Video::class, 'taggable');
}

Post Model:

public function tags() {
    return $this->morphToMany(Tag::class, 'taggable');
}

Summary of Methods:

  • morphOne() – one-to-one polymorphic
  • morphMany() – one-to-many polymorphic
  • morphToMany() – many-to-many polymorphic
  • morphedByMany() – inverse many-to-many polymorphic

Conclusion

Laravel’s Eloquent ORM provides robust support for relationships, making it easy to:

  • Retrieve related data
  • Perform DB operations through model methods
  • Avoid writing complex SQL joins
  • Reuse structures like tags or images across multiple models using polymorphism

Chapter 19: General Features

This chapter explores a variety of important features in Laravel that are commonly used across different types of web applications. It covers configuration, logging, pagination, mail handling, helper functions, collections, loading strategies (lazy vs eager), mutators/accessors, localization, queues, error handling, and more.


Environment Variables & Custom Configuration

Laravel uses a .env file to store environment variables that help configure the application per environment (development, production, etc.).

Custom Config Files

You can create your own configuration files in the config/ directory:

  1. Create a PHP file (e.g. myconfig.php)
  2. Return an array with your configuration keys:
    return [
        'example' => 'value'
    ];
    
  3. Access it using config('myconfig.example')

Logging

Laravel provides extensive logging options via the config/logging.php file.

Channels

  • Stack: Default; logs to multiple channels.
  • Single: Logs to a single file.
  • Daily: Rotates logs daily.

Configuration

'channels' => [
    'daily' => [
        'driver' => 'daily',
        'path' => storage_path('logs/laravel.log'),
        'level' => 'debug',
        'days' => 14,
    ],
],

Log Levels

From lowest to highest priority: debug, info, notice, warning, error, critical, alert, emergency

Log Formatters

You can customize how logs are formatted using a formatter.


Custom Pagination

Laravel provides two main pagination types:

  1. Paginator – used for simple next/prev navigation.
  2. LengthAwarePaginator – provides total pages info.

Usage:

Post::paginate(10); // LengthAwarePaginator
Post::simplePaginate(10); // Paginator

Mail System

Laravel uses the Mailable class to send emails.

Steps:

  1. Create a mailable:

    php artisan make:mail WelcomeUser
    
  2. Define the email logic in the class:

    public function build() {
        return $this->view('emails.welcome');
    }
    
  3. Send it:

    Mail::to('[email protected]')->send(new WelcomeUser());
    

Features:

  • Support for cc, bcc, and mass mailing
  • Parameterized templates
  • Markdown mail components

Helper Functions

Laravel allows creating global helper functions.

Steps:

  1. Create a file like app/helpers.php
  2. Add functions:
    function greet($name) {
        return "Hello, $name!";
    }
    
  3. Add to composer.json:
    "autoload": {
        "files": ["app/helpers.php"]
    }
    
  4. Run composer dump-autoload

Collections

Collections are Laravel’s wrapper over PHP arrays and include many useful methods like:

  • map()
  • filter()
  • pluck()
  • groupBy()

Example:

collect([1, 2, 3])->map(fn($v) => $v * 2);

Lazy vs Eager Loading

Lazy Loading (Default)

$posts = Post::all(); // multiple queries

Eager Loading (Recommended for performance)

$posts = Post::with('comments')->get(); // single optimized query

Mutators and Accessors

Mutators and accessors allow automatic data transformation when saving or retrieving model attributes.

Mutator:

public function setNameAttribute($value) {
    $this->attributes['name'] = strtolower($value);
}

Accessor:

public function getNameAttribute($value) {
    return ucfirst($value);
}

Localization & Translations

Laravel supports multilingual applications using translation strings and language files in resources/lang.

Steps:

  1. Publish language files:

    php artisan lang:publish
    
  2. Add translations:

    __('messages.welcome') // e.g., returns “Welcome” in the user’s language
    
  3. Middleware can prefix routes with language codes (e.g. /en/posts, /fr/posts).


Custom @vite Attributes

You can modify how Laravel includes assets with Vite, including custom attributes or tags.


Remove /public or /index.php from URLs

To avoid /public in your URLs:

  • Set your web server's root to public/
  • Use .htaccess or Nginx rewrite rules

Queues & Jobs

Jobs allow background processing (e.g., emails, image processing).

Example:

  1. Create a Job:

    php artisan make:job SendEmailJob
    
  2. Dispatch the job:

    dispatch(new SendEmailJob($user));
    
  3. Configure queue driver in .env (e.g. database, redis)


Other Useful Features

Failed Jobs

Laravel records failed jobs and allows retrying them.

Custom Exceptions

You can create custom exception classes and handle them in the Handler.php file.

Throttling

Control API request limits via middleware:

Route::middleware('throttle:60,1')->group(...);

Conclusion

This chapter introduces general Laravel features that go beyond basic CRUD. It equips you to:

  • Manage config, logs, and mail
  • Optimize performance with eager loading
  • Improve code with accessors/mutators
  • Handle multilingual sites
  • Build scalable systems using queues
  • Customize your project structure and helper functions