Лаб. работа 3 "Создание моделей, миграций и сидеров"
Цель: Научиться проектировать сложные связи между моделями, использовать фабрики и сидеры для заполнения данных.
Задачи:
- Создать несколько взаимосвязанных моделей:
Post,Category,Comment,Tag. - Реализовать связи: один-ко-многим, многие-ко-многим.
- Настроить каскадное удаление данных.
Методическая часть
1. Создание моделей и миграций
Выполните команды для создания моделей и миграций:
1php artisan make:model Post -m
2php artisan make:model Category -m
3php artisan make:model Comment -m
4php artisan make:model Tag -m
2. Настройка миграций
a. Таблица categories (database/migrations/xxxx_create_categories_table.php):
1Schema::create('categories', function (Blueprint $table) {
2 $table->id();
3 $table->string('name');
4 $table->string('slug')->unique();
5 $table->timestamps();
6});
b. Таблица posts (добавить внешние ключи):
1Schema::create('posts', function (Blueprint $table) {
2 $table->id();
3 $table->string('title');
4 $table->text('content');
5 $table->string('image')->nullable();
6 $table->foreignId('user_id')->constrained()->cascadeOnDelete();
7 $table->foreignId('category_id')->constrained()->cascadeOnDelete();
8 $table->timestamps();
9});
c. Таблица comments:
1Schema::create('comments', function (Blueprint $table) {
2 $table->id();
3 $table->text('text');
4 $table->foreignId('user_id')->constrained()->cascadeOnDelete();
5 $table->foreignId('post_id')->constrained()->cascadeOnDelete();
6 $table->timestamps();
7});
d. Таблица tags и связь многие-ко-многим с posts:
1// Таблица tags
2Schema::create('tags', function (Blueprint $table) {
3 $table->id();
4 $table->string('name');
5 $table->string('slug')->unique();
6 $table->timestamps();
7});
8
9// Промежуточная таблица post_tag
10Schema::create('post_tag', function (Blueprint $table) {
11 $table->foreignId('post_id')->constrained()->cascadeOnDelete();
12 $table->foreignId('tag_id')->constrained()->cascadeOnDelete();
13 $table->primary(['post_id', 'tag_id']);
14});
3. Определение связей в моделях
a. Модель Post (app/Models/Post.php):
1public function user() {
2 return $this->belongsTo(User::class);
3}
4
5public function category() {
6 return $this->belongsTo(Category::class);
7}
8
9public function comments() {
10 return $this->hasMany(Comment::class);
11}
12
13public function tags() {
14 return $this->belongsToMany(Tag::class);
15}
b. Модель Comment:
1public function user() {
2 return $this->belongsTo(User::class);
3}
4
5public function post() {
6 return $this->belongsTo(Post::class);
7}
c. Модель Category:
1public function posts() {
2 return $this->hasMany(Post::class);
3}
d. Модель Tag:
1public function posts() {
2 return $this->belongsToMany(Post::class);
3}
4. Создание фабрик
Создайте фабрики для всех моделей:
1php artisan make:factory PostFactory
2php artisan make:factory CategoryFactory
3php artisan make:factory CommentFactory
4php artisan make:factory TagFactory
Пример фабрики PostFactory:
1public function definition(): array {
2 return [
3 'title' => fake()->sentence(),
4 'content' => fake()->paragraphs(3, true),
5 'user_id' => User::factory(),
6 'category_id' => Category::factory(),
7 'image' => fake()->optional()->imageUrl(),
8 ];
9}
5. Заполнение сидеров
Измените database/seeders/DatabaseSeeder.php:
1public function run(): void {
2 // Создать 5 категорий
3 Category::factory(5)->create();
4
5 // Создать 10 тегов
6 Tag::factory(10)->create();
7
8 // Создать 20 постов
9 Post::factory(20)
10 ->has(Comment::factory(3)) // 3 комментария к каждому посту
11 ->create()
12 ->each(function ($post) {
13 // Привязать случайные теги к постам
14 $tags = Tag::inRandomOrder()->take(3)->pluck('id');
15 $post->tags()->attach($tags);
16 });
17}
Индивидуальные задания
1. Добавление модели Like
- Создайте модель
Likeс полями:user_id,likeable_type(полиморфная связь),likeable_id. - Реализуйте полиморфное отношение, чтобы лайки можно было ставить как постам, так и комментариям.
2. Мягкое удаление (Soft Delete)
- Добавьте в модели
PostиCommentподдержку мягкого удаления. - Измените миграции, добавив
$table->softDeletes();. - Проверьте, что при удалении поста комментарии остаются в базе (если не использовать каскадное удаление).
3. Валидация slug
- В модели
Categoryдобавьте валидацию slug через observer:1// Создайте observer 2php artisan make:observer CategoryObserver --model=Category - В
CategoryObserver:1public function creating(Category $category) { 2 $category->slug = Str::slug($category->name); 3}
4. Теги через строку
Модифицируйте форму создания поста:
- Добавьте поле
tags(строка с тегами через запятую). - В контроллере обработайте ввод:
1$tags = explode(',', $request->tags); 2foreach ($tags as $tagName) { 3 $tag = Tag::firstOrCreate(['name' => trim($tagName)]); 4 $post->tags()->attach($tag); 5}
Проверка работы
- Выполните миграции и сидеры:
1php artisan migrate:fresh --seed - Проверьте связи через Tinker:
1php artisan tinker 2$post = Post::first(); 3$post->comments; // Должен вывести комментарии 4$post->tags; // Должен вывести теги
Примечания
- Каскадное удаление: При удалении категории все связанные посты будут удалены автоматически.
- Полиморфные связи: Используются для гибкой привязки моделей (например, лайки к разным сущностям).