## Pour éviter les erreurs de clé étrangère lors de la création des tables
Ordre d’exécution des migrations

  1. roles
  2. users
  3. uploads
  4. pages
  5. exercises
  6. plans
  7. workouts
  8. swim_sets
  9. myliste
  10. workout_exercises
  11. workout_swim_sets
  12. plan_workouts
  13. myliste_items

-- Migrations & Modèles

Poisson Rouge « Cours »: — Eloquent ORM (Object-Relational Mapping) est le système de gestion de base de données intégré à Laravel. Il permet d’interagir avec la base de données en utilisant des objets PHP plutôt que des requêtes SQL brutes

  • ## chaque table de la base de données est représentée par un modèle PHP, ce qui facilite les manipulations de données

Création des Modèles et Relations (Eloquent ORM)

Modèles et Migrations

php artisan make:model Exercise -m
php artisan make:model Page -m
php artisan make:model Plan -m
php artisan make:model PlanWorkout -m
php artisan make:model Role -m
php artisan make:model SwimSet -m
php artisan make:model Upload -m
php artisan make:model User -m
php artisan make:model Workout -m
php artisan make:model WorkoutExercise -m
php artisan make:model WorkoutSwimSet -m
php artisan make:model MyList -m
php artisan make:model MyListItem -m

Poisson Rouge  : – Astuce / Exemple : #php artisan make:model Exercise -m –>> genere les modeles et les migrations; #php artisan make:model Exercise -mf –>> genere les modeles et les factories et #php artisan make:model Exercise -mc –>> genere les modeles et les controlleurs


Définir les Relations « One to Many »

Poisson Rouge : — Exemple : Un utilisateur peut avoir plusieurs posts

// App/Models/User.php
public function posts() {
 return $this->hasMany(Post::class, 'post_author');
}
// App/Models/Post.php
public function author() {
 return $this->belongsTo(User::class, 'post_author');
}

Exemple : Une catégorie a plusieurs posts

// App/Models/Category.php
public function posts() {
 return $this->hasMany(Post::class, 'category_id');
}
// App/Models/Post.php
public function category() {
 return $this->belongsTo(Category::class, 'category_id');
}

 

 

 

-- Role "M + M"

Role

Migration



use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('roles', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name')->unique(); // Added unique constraint
            $table->timestamps(); // Use Laravel's default timestamps
        });

        // Add foreign key constraint to users table AFTER roles table creation
        Schema::table('users', function (Blueprint $table) {
            $table->foreignId('role_id')->nullable()->constrained('roles')->onDelete('set null');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        // Drop foreign key constraint before dropping the roles table
        Schema::table('users', function (Blueprint $table) {
            $table->dropForeign(['role_id']);
        });

        Schema::dropIfExists('roles');
    }
};

 


Modèle



namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
    use HasFactory;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = [
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    /**
     * Get the users for the role.
     */
    public function users()
    {
        return $this->hasMany(User::class);
    }
}



 

-- User "M + M"

User

Migration





// ...

public function up(): void
{
    Schema::table('users', function (Blueprint $table) {
        // Si role_id n'existe pas, l'ajouter
        if (!Schema::hasColumn('users', 'role_id')) {
            $table->foreignId('role_id')->nullable()->constrained('roles')->onDelete('set null');
        }
    });
}

public function down(): void
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropForeign(['role_id']); // Supprimer la contrainte
    });
}

 


Modèle




namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable; // Important pour l'authentification
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'username',
        'email',
        'password',
        'first_name',
        'last_name',
        'role_id', // Assurez-vous que role_id est dans fillable
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
        'password' => 'hashed', // Hashage du mot de passe
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    /**
     * Get the role associated with the user.
     */
    public function role()
    {
        return $this->belongsTo(Role::class);
    }

    // ... autres relations (exercises, pages, plans, workouts, mylistes)
    public function exercises()
    {
        return $this->hasMany(Exercise::class);
    }

    public function pages()
    {
        return $this->hasMany(Page::class);
    }

    public function plans()
    {
        return $this->hasMany(Plan::class);
    }

    public function workouts()
    {
        return $this->hasMany(Workout::class);
    }

    public function mylistes()
    {
        return $this->hasMany(Myliste::class);
    }
}

 

-- Upload "M + M"

Upload

Migration



public function up(): void
{
    Schema::create('uploads', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('filename');
        $table->string('path');
        $table->string('type')->nullable();
        $table->foreignId('user_id')->nullable()->constrained('users')->onDelete('set null'); // Clé étrangère
        $table->timestamps();
    });

    // Dans les migrations des tables exercises et pages, ajouter les clés étrangères vers uploads
    Schema::table('exercises', function (Blueprint $table) {
        $table->foreignId('upload_id')->nullable()->constrained('uploads')->onDelete('set null');
    });

    Schema::table('pages', function (Blueprint $table) {
        $table->foreignId('upload_id')->nullable()->constrained('uploads')->onDelete('set null');
    });

}

public function down(): void
{
    // Supprimer les clés étrangères dans les tables exercises et pages
    Schema::table('exercises', function (Blueprint $table) {
        $table->dropForeign(['upload_id']);
    });

    Schema::table('pages', function (Blueprint $table) {
        $table->dropForeign(['upload_id']);
    });

    Schema::dropIfExists('uploads');
}

 


Modèle



namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Upload extends Model
{
    use HasFactory;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'filename',
        'path',
        'type',
        'user_id',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = [
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    /**
     * Get the user that uploaded the file.
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }

    // ... autres relations (exercises, pages)

    public function exercises()
    {
        return $this->hasMany(Exercise::class);
    }

    public function pages()
    {
        return $this->hasMany(Page::class);
    }
}

 

-- Page "M + M"

Page

Migration



public function up(): void
{
    Schema::create('pages', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('title');
        $table->longText('content');
        $table->string('page_category')->nullable();
        $table->foreignId('upload_id')->nullable()->constrained('uploads')->onDelete('set null'); // Clé étrangère vers uploads
        $table->foreignId('user_id')->constrained('users')->onDelete('cascade'); // Clé étrangère vers users
        $table->timestamps();
    });
}

public function down(): void
{
    Schema::dropIfExists('pages');
}

 


Modèle



namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Page extends Model
{
    use HasFactory;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'title',
        'content',
        'page_category',
        'upload_id',
        'user_id',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = [
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    /**
     * Get the user that created the page.
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }

    /**
     * Get the upload associated with the page.
     */
    public function upload()
    {
        return $this->belongsTo(Upload::class);
    }
}

 

-- Exercise "M + M"

Exercise

Migration




public function up(): void
{
    Schema::create('exercises', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('title');
        $table->text('description')->nullable();
        $table->string('exercise_level')->nullable();
        $table->string('exercise_category')->nullable();
        $table->foreignId('upload_id')->nullable()->constrained('uploads')->onDelete('set null'); // Clé étrangère vers uploads
        $table->foreignId('user_id')->constrained('users')->onDelete('cascade'); // Clé étrangère vers users
        $table->timestamps();
    });
}

public function down(): void
{
    Schema::dropIfExists('exercises');
}

 


Modèle


namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Exercise extends Model
{
    use HasFactory;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'title',
        'description',
        'exercise_level',
        'exercise_category',
        'upload_id',
        'user_id',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = [
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    /**
     * Get the user that created the exercise.
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }

    /**
     * Get the upload associated with the exercise.
     */
    public function upload()
    {
        return $this->belongsTo(Upload::class);
    }

    /**
     * Get the swim sets for the exercise.
     */
    public function swimSets()
    {
        return $this->hasMany(SwimSet::class);
    }

    /**
     * The workouts that belong to the exercise.
     */
    public function workouts()
    {
        return $this->belongsToMany(Workout::class, 'workout_exercises');
    }
}

 

-- Plan "M + M"

Plan

Migration


public function up(): void
{
    Schema::create('plans', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('title');
        $table->text('description')->nullable();
        $table->string('plan_category')->nullable();
        $table->foreignId('user_id')->constrained('users')->onDelete('cascade'); // Clé étrangère vers users
        $table->timestamps();
    });
}

public function down(): void
{
    Schema::dropIfExists('plans');
}

 


Modèle



namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Plan extends Model
{
    use HasFactory;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'title',
        'description',
        'plan_category',
        'user_id',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = [
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    /**
     * Get the user that created the plan.
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }

    /**
     * The workouts that belong to the plan.
     */
    public function workouts()
    {
        return $this->belongsToMany(Workout::class, 'plan_workouts');
    }
}

 

-- PlanWorkout "M + M"

PlanWorkout

Migration

public function up(): void
{
    Schema::create('plan_workouts', function (Blueprint $table) {
        $table->foreignId('plan_id')->constrained('plans')->onDelete('cascade');
        $table->foreignId('workout_id')->constrained('workouts')->onDelete('cascade');
        $table->primary(['plan_id', 'workout_id']); // Clé primaire composite
        $table->timestamps(); // Ajout des timestamps pour suivre la création et la modification des associations.
    });
}

public function down(): void
{
    Schema::dropIfExists('plan_workouts');
}

 


Modèle

Pas de modèle
Relations dans les modèles Plan et Workout Many-to-Many à définir dans les modèles Plan et Workout :


// Dans Plan
public function workouts()
{
    return $this->belongsToMany(Workout::class, 'plan_workouts');
}
 
//Dans Workout

public function plans()
{
    return $this->belongsToMany(Plan::class, 'plan_workouts');
}

 

-- SwimSet "M + M"

SwimSet

Migration


public function up(): void
{
    Schema::create('swim_sets', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->foreignId('workout_id')->nullable()->constrained('workouts')->onDelete('cascade'); // Clé étrangère vers workouts
        $table->foreignId('exercise_id')->nullable()->constrained('exercises')->onDelete('set null'); // Clé étrangère vers exercises
        $table->integer('set_distance')->nullable();
        $table->integer('set_repetition')->nullable();
        $table->integer('rest_time')->nullable();
        $table->timestamps();
    });
}

public function down(): void
{
    Schema::dropIfExists('swim_sets');
}

 


Modèle



namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class SwimSet extends Model
{
    use HasFactory;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'workout_id',
        'exercise_id',
        'set_distance',
        'set_repetition',
        'rest_time',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = [
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    /**
     * Get the workout that the swim set belongs to.
     */
    public function workout()
    {
        return $this->belongsTo(Workout::class);
    }

    /**
     * Get the exercise that the swim set uses.
     */
    public function exercise()
    {
        return $this->belongsTo(Exercise::class);
    }
}

 

-- Workout "M + M"

Workout

Migration


public function up(): void
{
    Schema::create('workouts', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('title');
        $table->text('description')->nullable();
        $table->string('workout_category')->nullable();
        $table->foreignId('user_id')->constrained('users')->onDelete('cascade'); // Clé étrangère vers users
        $table->timestamps();
    });
}

public function down(): void
{
    Schema::dropIfExists('workouts');
}

 


Modèle


namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Workout extends Model
{
    use HasFactory;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'title',
        'description',
        'workout_category',
        'user_id',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = [
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    /**
     * Get the user that created the workout.
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }

    /**
     * The exercises that belong to the workout.
     */
    public function exercises()
    {
        return $this->belongsToMany(Exercise::class, 'workout_exercises');
    }

    /**
     * The plans that the workout is included in.
     */
    public function plans()
    {
        return $this->belongsToMany(Plan::class, 'plan_workouts');
    }

    /**
     * Get the swim sets for the workout.
     */
    public function swimSets()
    {
        return $this->hasMany(SwimSet::class);
    }
}

 

-- WorkoutExercises "M + M"

workout_exercises

Migration


public function up(): void
{
    Schema::create('workout_exercises', function (Blueprint $table) {
        $table->foreignId('workout_id')->constrained('workouts')->onDelete('cascade');
        $table->foreignId('exercise_id')->constrained('exercises')->onDelete('cascade');
        $table->primary(['workout_id', 'exercise_id']); // Clé primaire composite
        $table->timestamps(); // Ajout des timestamps pour suivre la création et la modification des associations.
    });
}

public function down(): void
{
    Schema::dropIfExists('workout_exercises');
}

 


Modèle

Pas de modèle
Relations Workout et Exercise Many-to-Many dans modèles Workout et Exercise



//Dans Workout.php 

public function exercises()
{
    return $this->belongsToMany(Exercise::class, 'workout_exercises');
}
 // Dans Exercise.php

public function workouts()
{
    return $this->belongsToMany(Workout::class, 'workout_exercises');
}

 

-- WorkoutSwimSets "M + M"

workout_swim_sets

Migration


public function up(): void
{
    Schema::create('workout_swim_sets', function (Blueprint $table) {
        $table->foreignId('workout_id')->constrained('workouts')->onDelete('cascade');
        $table->foreignId('swim_set_id')->constrained('swim_sets')->onDelete('cascade');
        $table->primary(['workout_id', 'swim_set_id']); // Clé primaire composite
        $table->timestamps(); // Ajout des timestamps pour suivre la création et la modification des associations.
    });
}

public function down(): void
{
    Schema::dropIfExists('workout_swim_sets');
}

 


Modèle

Pas de modèle Relations Many-to-Many définies Workout et SwimSet


//Dans Workout.php :

public function swimSets()
{
    return $this->belongsToMany(SwimSet::class, 'workout_swim_sets');
}
 // Dans SwimSet.php

public function workouts()
{
    return $this->belongsToMany(Workout::class, 'workout_swim_sets');
}

 

-- Myliste "M + M"

myliste

Migration



public function up(): void
{
    Schema::create('myliste', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->foreignId('user_id')->constrained('users')->onDelete('cascade'); // Clé étrangère vers users
        $table->string('title');
        $table->text('description')->nullable();
        $table->timestamps();
    });
}

public function down(): void
{
    Schema::dropIfExists('myliste');
}

 


Modèle

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Myliste extends Model
{
    use HasFactory;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string="">
     */
    protected $fillable = [
        'user_id',
        'title',
        'description',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string="">
     */
    protected $casts = [
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    /**
     * Get the user that owns the myliste.
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }

    /**
     * Get the items in the myliste.
     */
    public function mylisteItems()
    {
        return $this->hasMany(MylisteItem::class); // Relation avec MylisteItem
    }
}

 

-- MylisteItems "M + M"

Role

Migration



public function up(): void
{
    Schema::create('myliste_items', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->foreignId('myliste_id')->constrained('myliste')->onDelete('cascade'); // Clé étrangère vers myliste
        $table->bigInteger('item_id'); // ID de l'élément (polymorphique)
        $table->string('item_type'); // Type de l'élément (polymorphique)
        $table->timestamps();
    });
}

public function down(): void
{
    Schema::dropIfExists('myliste_items');
}

 


Modèle


namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class MylisteItem extends Model
{
    use HasFactory;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'myliste_id',
        'item_id',
        'item_type',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = [
        'created_at' => 'datetime',
    ];

    /**
     * Get the myliste that the item belongs to.
     */
    public function myliste()
    {
        return $this->belongsTo(Myliste::class);
    }

    // Les relations polymorphiques seront définies ici (voir explication plus bas)
}

// La table myliste_items utilise une relation pour lier (exercices, séances, plans) ===>> item_id peut référencer l’ID d’un exercice, d’une séance ou d’un plan, et item_type indique le type de modèle.


//Dans le modèle MylisteItem :

/**
 * Get the item (exercise, workout, or plan).
 */
public function item()
{
    return $this->morphTo();
}
//dans les modèles Exercise, Workout et Plan :

public function mylisteItems()
{
    return $this->morphMany(MylisteItem::class, 'item');
}

-- Exécuter Les Migrations Créer Les Tables

Création des tables



php artisan migrate --path=/database/migrations/01_create_roles_table.php
php artisan migrate --path=/database/migrations/02_create_users_table.php
php artisan migrate --path=/database/migrations/03_create_uploads_table.php
php artisan migrate --path=/database/migrations/04_create_pages_table.php
php artisan migrate --path=/database/migrations/05_create_exercises_table.php
php artisan migrate --path=/database/migrations/05_create_plans_table.php
php artisan migrate --path=/database/migrations/07_create_workouts_table.php
php artisan migrate --path=/database/migrations/08_create_swim_sets_table.php
php artisan migrate --path=/database/migrations/09_create_my_lists_table.php
php artisan migrate --path=/database/migrations/10_create_workout_exercises_table.php
php artisan migrate --path=/database/migrations/11_create_workout_swim_sets_table.php
php artisan migrate --path=/database/migrations/12_create_plan_workouts_table.php
php artisan migrate --path=/database/migrations/13_create_my_list_items_table.php


Poisson Rouge  : Une par une pour maitriser les erreurs ?????