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