Блог на Laravel 7, часть 1. Создание таблиц БД, наполнение тестовыми данными
02.12.2020
Теги: Laravel • MySQL • PHP • Web-разработка • БазаДанных • Блог • Класс • Практика • Фреймворк
Функционал будет не слишком богатый — просмотр списка всех постов, просмотр постов выбанной категории, просмотр постов выбранного тега, просмотр отдельного поста, регистрация и аутентификация пользователей. В панели управления можно создать, отредактировать и удалить категорию, пост или тег.
Создание проекта
Создаем новый проект Laravel:
> composer create-project --prefer-dist laravel/laravel blog
Пакет для подсказок PhpStorm:
> composer require barryvdh/laravel-ide-helper --dev > php artisan clear-compiled > php artisan ide-helper:generate
Таблицы БД
Модель Category
и миграция:
> php artisan make:model Category -m Model created successfully. Created Migration: 2020_12_02_074609_create_categories_table
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateCategoriesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('categories', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('parent_id')->nullable(false)->default(0); $table->string('name', 100); $table->string('slug', 100)->unique(); $table->string('image', 50)->nullable(); $table->string('content', 500)->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('categories'); } }
Модель Post
и миграция:
> php artisan make:model Post -m Model created successfully. Created Migration: 2020_12_02_074631_create_posts_table
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreatePostsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('posts', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('user_id')->nullable(); $table->unsignedBigInteger('published_by')->nullable(); $table->unsignedBigInteger('category_id')->nullable(); $table->string('name', 100); $table->string('slug', 100)->unique(); $table->string('image', 50)->nullable(); $table->string('excerpt', 500)->nullable(false); $table->text('content')->nullable(false); $table->timestamps(); // внешний ключ, ссылается на поле id таблицы users $table->foreign('user_id') ->references('id') ->on('brands') ->nullOnDelete(); // внешний ключ, ссылается на поле id таблицы users $table->foreign('published_by') ->references('id') ->on('users') ->nullOnDelete(); // внешний ключ, ссылается на поле id таблицы categories $table->foreign('category_id') ->references('id') ->on('categories') ->nullOnDelete(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('posts'); } }
Модель Comment
и миграция:
> php artisan make:model Comment -m Model created successfully. Created Migration: 2020_12_02_074651_create_comments_table
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateCommentsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('comments', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('post_id')->nullable(false); $table->unsignedBigInteger('user_id')->nullable(); $table->unsignedBigInteger('published_by')->nullable(); $table->string('content', 500)->nullable(false); $table->timestamps(); // внешний ключ, ссылается на поле id таблицы posts $table->foreign('post_id') ->references('id') ->on('posts') ->onDelete('cascade'); // внешний ключ, ссылается на поле id таблицы users $table->foreign('user_id') ->references('id') ->on('users') ->nullOnDelete(); // внешний ключ, ссылается на поле id таблицы users $table->foreign('published_by') ->references('id') ->on('users') ->nullOnDelete(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('comments'); } }
Модель Tag
и миграция:
> php artisan make:model Tag -m Model created successfully. Created Migration: 2020_12_02_074715_create_tags_table
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateTagsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('tags', function (Blueprint $table) { $table->id(); $table->string('name', 50)->nullable(false); $table->string('slug', 50)->nullable(false)->unique(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('tags'); } }
Миграция для создания таблицы связи пост-тег:
> php artisan make:migration create_post_tag_table Created Migration: 2020_12_02_074853_create_post_tag_table
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreatePostTagTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('post_tag', function (Blueprint $table) { $table->unsignedBigInteger('post_id'); $table->unsignedBigInteger('tag_id'); $table->timestamps(); // внешний ключ, ссылается на поле id таблицы posts $table->foreign('post_id') ->references('id') ->on('posts') ->onDelete('cascade'); // внешний ключ, ссылается на поле id таблицы tags $table->foreign('tag_id') ->references('id') ->on('tags') ->onDelete('cascade'); // составной первичный ключ $table->primary(['post_id', 'tag_id']); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('post_tag'); } }
Seeders
Класс для заполнения таблицы categories
:
> php artisan make:seeder CategoryTableSeeder Seeder created successfully.
use Illuminate\Database\Seeder; class CategoryTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { // создать 12 категорий factory(App\Category::class, 12)->create(); } }
Класс для заполнения таблицы posts
:
> php artisan make:seeder PostTableSeeder Seeder created successfully.
use Illuminate\Database\Seeder; class PostTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { // создать 50 постов блога factory(App\Post::class, 50)->create(); } }
Класс для заполнения таблицы tags
:
> php artisan make:seeder TagTableSeeder Seeder created successfully.
use Illuminate\Database\Seeder; class TagTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { // создать 100 тегов блога factory(App\Tag::class, 100)->create(); } }
Класс для заполнения таблицы comments
:
> php artisan make:seeder CommentTableSeeder Seeder created successfully.
use Illuminate\Database\Seeder; class CommentTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { // создать 200 комментариев factory(App\Comment::class, 200)->create(); } }
Класс для заполнения таблицы post_tag
:
> php artisan make:seeder PostTagTableSeeder Seeder created successfully.
use Illuminate\Database\Seeder; class PostTagTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { // создать связи между постами и тегами foreach(App\Post::all() as $post) { foreach(App\Tag::all() as $tag) { if (rand(1, 20) == 10) { $post->tags()->attach($tag->id); } } } } }
Поскольку в классе PostTagTableSeeder
мы используем связи, надо их сразу установить:
namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model { public function tags() { return $this->belongsToMany(Tag::class)->withTimestamps(); } }
namespace App; use Illuminate\Database\Eloquent\Model; class Tag extends Model { public function posts() { return $this->belongsToMany(Post::class)->withTimestamps();; } }
Класс для заполнения таблицы users
:
> php artisan make:seeder UserTableSeeder Seeder created successfully.
use Illuminate\Database\Seeder; class UserTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { // создать 10 пользователей factory(App\User::class, 10)->create(); } }
Фабрики
Фабрика для модели Category
:
> php artisan make:factory CategoryFactory --model=Category Factory created successfully.
/** @var \Illuminate\Database\Eloquent\Factory $factory */ use App\Category; use Faker\Generator as Faker; use Illuminate\Support\Str; $factory->define(Category::class, function (Faker $faker) { $name = $faker->realText(rand(40, 50)); return [ 'name' => $name, 'content' => $faker->realText(rand(200, 500)), 'slug' => Str::slug($name), ]; });
Фабрика для модели Post
:
> php artisan make:factory PostFactory --model=Post Factory created successfully.
/** @var \Illuminate\Database\Eloquent\Factory $factory */ use App\Post; use Faker\Generator as Faker; use Illuminate\Support\Str; $factory->define(Post::class, function (Faker $faker) { $name = $faker->realText(rand(70, 100)); return [ 'user_id' => rand(1, 10), 'category_id' => rand(1, 12), 'name' => $name, 'excerpt' => $faker->realText(rand(300, 400)), 'content' => $faker->realText(rand(400, 500)), 'slug' => Str::slug($name), 'published_by' => rand(1, 10), ]; });
Фабрика для модели Tag
:
> php artisan make:factory TagFactory --model=Tag Factory created successfully.
/** @var \Illuminate\Database\Eloquent\Factory $factory */ use App\Tag; use Faker\Generator as Faker; $factory->define(Tag::class, function (Faker $faker) { $name = $faker->realText(rand(20, 30)); return [ 'name' => $name, 'slug' => Str::slug($name), ]; });
Фабрика для модели Comment
:
> php artisan make:factory CommentFactory --model=Comment Factory created successfully.
/** @var \Illuminate\Database\Eloquent\Factory $factory */ use App\Comment; use Faker\Generator as Faker; $factory->define(Comment::class, function (Faker $faker) { return [ 'post_id' => rand(1, 50), 'user_id' => rand(1, 10), 'content' => $faker->realText(rand(200, 500)), 'created_at' => $faker->dateTimeBetween('-200 days', '-50 days'), 'updated_at' => $faker->dateTimeBetween('-40 days', '-1 days'), 'published_by' => rand(1, 3), // супер-админ или просто админ ]; });
Фабрика для модели User
:
/** @var \Illuminate\Database\Eloquent\Factory $factory */ use App\User; use Faker\Generator as Faker; use Illuminate\Support\Str; /* |-------------------------------------------------------------------------- | Model Factories |-------------------------------------------------------------------------- | | This directory should contain each of the model factory definitions for | your application. Factories provide a convenient way to generate new | model instances for testing / seeding your application's database. | */ $factory->define(User::class, function (Faker $faker) { return [ 'name' => $faker->name, 'email' => $faker->unique()->safeEmail, 'password' => Hash::make('qwerty'), 'email_verified_at' => now(), 'remember_token' => Str::random(10), ]; });
Наполнение БД
Редактируем класс DatabaseSeeder
:
use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { /** * Seed the application's database. * * @return void */ public function run() { $this->call(UserTableSeeder::class); $this->command->info('Таблица пользователей загружена данными!'); $this->call(CategoryTableSeeder::class); $this->command->info('Таблица категорий загружена данными!'); $this->call(TagTableSeeder::class); $this->command->info('Таблица тегов загружена данными!'); $this->call(PostTableSeeder::class); $this->command->info('Таблица постов загружена данными!'); $this->call(PostTagTableSeeder::class); $this->command->info('Таблица пост-тег загружена данными!'); $this->call(CommentTableSeeder::class); $this->command->info('Таблица комментариев загружена данными!'); } }
Все готово, запускаем миграцию:
> php artisan migrate:fresh --seed Dropped all tables successfully. Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.03 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.03 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.02 seconds) Migrating: 2020_12_02_074609_create_categories_table Migrated: 2020_12_02_074609_create_categories_table (0.03 seconds) Migrating: 2020_12_02_074631_create_posts_table Migrated: 2020_12_02_074631_create_posts_table (0.03 seconds) Migrating: 2020_12_02_074651_create_comments_table Migrated: 2020_12_02_074651_create_comments_table (0.02 seconds) Migrating: 2020_12_02_074715_create_tags_table Migrated: 2020_12_02_074715_create_tags_table (0.02 seconds) Migrating: 2020_12_02_074853_create_post_tag_table Migrated: 2020_12_02_074853_create_post_tag_table (0.02 seconds) Seeding: UserTableSeeder Seeded: UserTableSeeder (0.91 seconds) Таблица пользователей загружена данными! Seeding: CategoryTableSeeder Seeded: CategoryTableSeeder (0.13 seconds) Таблица категорий загружена данными! Seeding: TagTableSeeder Seeded: TagTableSeeder (0.61 seconds) Таблица тегов загружена данными! Seeding: PostTableSeeder Seeded: PostTableSeeder (0.56 seconds) Таблица постов загружена данными! Seeding: PostTagTableSeeder Seeded: PostTagTableSeeder (7.32 seconds) Таблица пост-тег загружена данными! Seeding: CommentTableSeeder Seeded: CommentTableSeeder (1.67 seconds) Таблица комментариев загружена данными! Database seeding completed successfully.
- Мини-блог на Laravel, часть 4. Создание нового поста, загрузка и обрезка изображения
- Мини-блог на Laravel, часть 3. Постраничная навигация, layout-шаблон и поиск по блогу
- Мини-блог на Laravel, часть 2. Создание контроллера, представления и маршрута
- Мини-блог на Laravel, часть 1. Создание таблиц БД, наполнение тестовыми данными
- Блог на Laravel 7, часть 17. Временная зона для пользователей, деплой на хостинг TimeWeb
- Блог на Laravel 7, часть 16. Роль нового пользователя, сообщение админу о новом посте
- Блог на Laravel 7, часть 13. Загрузка и ресайз изображений для категорий и постов блога
Поиск: Laravel • MySQL • PHP • Web-разработка • База данных • Блог • Класс • Практика • Фреймворк