Laravelの勉強の備忘録です
Laravelの勉強のためにこのサイトの**【Laravel】掲示板を作成する(1)~(7)**をなぞりながら掲示板を作りました。
記事を書かれた方にこの場を借りてお礼申し上げます。
そしてLaravel技術力アップのため、この掲示板に機能を追加していきます(本記事の内容)
環境
前提条件:【Laravel】掲示板を作成する(1)~(7)をLaravel 8で作り終えていること。
Windows 10
Laravel 8(※掲示板を作成された方の環境はLaravel 5.8のようですが、8で作っています)
Docker
目標
- Userデータを作成し、UserとPostやCommentのリレーションを設定する
- Fakerを使いUserのダミーデータを作成
- PostとCommentテーブルのnameカラム名削除をし、user_idカラムを作成
- Userとのリレーションの設定を行う
- viewの変更
- 検索の修正
## Fakerを使いUserのダミーデータを作成
Userのダミーデータを作成します。
UserモデルとUserFactoryは仕様で作成されているので、Seederを作成します。
$ php artisan make:seeder UsersTableSeeder
ダミーデータをとりあえず5つ作成
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
class UsersTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
User::factory(5)->create();
}
}
パスワードの記述の変更
public function definition()
{
return [
'name' => $this->faker->name(),
'email' => $this->faker->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
}
↓ 変更 ↓
public function definition()
{
return [
'name' => $this->faker->name(),
'email' => $this->faker->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => bcrypt('password'),
'remember_token' => Str::random(10),
];
}
ダミーユーザーを5つ作ったので、PostsとCommentsテーブルのuser_id(後ほど作成)に1~5の数字をランダムに流し込むために内容を変更します。
public function definition()
{
return [
(略)
// 'name' => $this->faker->name, // 氏名
↓↓ 変更
'user_id' => $this->faker->numberBetween(1,5),
(略)
];
}
seederを流し込むための記述を追記します。
public function run()
{
$this->call(UsersTableSeeder::class); // ← リレーションの関係でPostsTableSeederより上に追記
$this->call(PostsTableSeeder::class);
}
PostとCommentテーブルの内容を変更
nameカラムを削除し、user_idを追加します。
Laravelはデフォルトではカラム名の変更はできないらしいので、Doctrine DBALをインストールします。
(カラム名を変更していないので、Doctrine DBALはインストールしなくてもいいかもしれません)
$ composer require doctrine/dbal
postsとcommentsテーブルのnameカラムを削除し、user_idカラムを作成するためのマイグレーションファイルの作成を行います。
(1)nameカラム削除用のmigrationファイルの作成
とりあえずわかりやすいかなと思う名前で作成。
$ php artisan make:migration drop_name_column_from_posts_table --table=posts
$ php artisan make:migration drop_name_column_from_comments_table --table=comments
最初はdrop_column_name_columnにしようとしました。
しかし、posts作成後にcomments分を作成しようとしたところ、既にファイルが存在しているとエラーがでたため、上記のような書き方にしました。
(2)nameカラム削除用のmigrationファイルへの記述
public function up()
{
Schema::table('comments', function (Blueprint $table) {
$table->dropColumn('name'); //カラムの削除
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('comments', function (Blueprint $table) {
$table->string('name'); //カラム追加
});
}
(3)nameカラム削除用のmigrationファイルの反映
$ php artisan migrate
down処理の検証をしたい場合は、 php artisan migrate:rollback --step=2 とやって、カラムが巻き戻っているかを確認すればいいと思います。というか、した方がいいです。
(4)user_idカラム追加用のmigrationファイルの作成
$ php artisan make:migration add_user_id_to_posts_table --table=posts
$ php artisan make:migration add_user_id_to_comments_table --table=comments
(5)user_idカラム追加用のmigrationファイルへの記述
Usersテーブルのidを確認したところ、タイプがbigint、属性がunsignedだったのでunsignedBingIntegerで作成します。
public function up()
{
Schema::table('posts', function (Blueprint $table) {
$table->unsignedBigInteger('user_id'); //カラム追加
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('posts', function (Blueprint $table) {
$table->dropForeign('posts_user_id_foreign');
$table->dropColumn('user_id');
});
}
public function up()
{
Schema::table('comments', function (Blueprint $table) {
$table->unsignedBigInteger('user_id'); //カラム追加
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('comments', function (Blueprint $table) {
$table->dropForeign('comments_user_id_foreign');
$table->dropColumn('user_id');
});
}
リレーション設定のために内容に変更や追記をします。
public function posts()
{
return $this->hasMany('App\Models\Post');
}
public function comments()
{
return $this->hasMany('App\Models\Comment');
}
protected $fillable = [
'post_id',
'user_id', // 'name'から変更
'comment',
];
public function user() // 追記
{
return $this->belongsTo('App\Models\User');
}
protected $fillable = [
'user_id', // 'name'から変更
'subject',
'message',
'category_id'
];
public function user() // 追記
{
return $this->belongsTo('App\Models\User');
}
これでseederとリレーションが出来たので、ダミーデータを流し込みます。
$ php artisan migrate:refresh --seed
viewの編集
今まではpostsテーブルのnameカラムを参照していました。
しかし、nameカラムを削除し、user_idを参照するようになったので、内容を変更します。
<td>{{ $post->name }}</td>
↓ 変更 ↓
<td>{{ $post->user->name }}</td>
value="{{ old('name') ?: $post->name }}"
↓ 変更 ↓
value="{{ old('name') ?: $post->user->name }}"
上記の記述にするとちゃんと名前が表示されるようになりました。
検索の修正
テーブルの構造を変えたので、検索をしても名前がひっかからなくなりました。
ですので、検索対象のカラムを変更します。
postsテーブルのmessegeカラム
postsテーブルのnameカラム
↓
postsテーブルのmessegeカラム
usersテーブルのnameカラム
public function scopeFuzzyNameMessage($query, $searchword)
{
(略)
return $query->where(function ($query) use($searchword) {
$query->orWhere('name', 'like', "%{$searchword}%")
->orWhere('message', 'like', "%{$searchword}%");
});
}
↓ 変更 ↓
public function scopeFuzzyNameMessage($query, $searchword)
{
(略)
$user_ids = User::where('name', 'like', "%{$searchword}%")->pluck("id");
$query->whereIn('user_id', $user_ids)
->orWhere('message', 'like', "%{$searchword}%");
return $query;
}
まずuser_idsに検索ワードと一致したusersテーブルのnameカラムと一致するidをぶち込みます。
whereInを使っている理由は、user_idsはpluckメソッドを使っていて配列が入っています。そのためwhereIn()を使うのが適しているらしいからです。
この修正を行った後に検索をすると、名前とメッセージに一致している記事を拾ってきてくれるようになります。
続きは、Laravelで作られた掲示板に機能を追加する②にて!