ポートフォリオ作成にあたり、laravel8でログインユーザーとそのユーザーが登録した在庫データを紐付けしたく、調べて実装したのでこちらでご紹介したいと思います!
是非参考になれば幸いです!
また、人によっては設定の仕方が変わってくる場合もあるかと思いますので、細かい点については僕が参考にさせてもらったこちらのサイトをご覧になってみてください!
https://www.webopixel.net/php/1670.html
user_idカラムを追加
先ずは、在庫を登録しているテーブルにuser_idカラムを追加します。
ここのuser_idカラムにオートインクリメントで登録されるuserのIDが入ります。
// database/migrations/xxxx_xx_xx_xxxxxx_create_stocks_table.php
class CreateStocksTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('stocks', function (Blueprint $table) {
$table->increments('id');
$table->string('shop');
$table->date('purchase_date');
$table->date('deadline');
$table->string('name');
$table->integer('price');
$table->integer('number');
$table->foreignId('user_id')->constrained(); //追加
$table->timestamps();
});
}
}
ファクトリーファイルにも同じく追加します。
// database/factories/StockFactory.php
class StockFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Stock::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'shop' => $this->faker->word,
'purchase_date' => $this->faker->dateTimeBetween('-20 days', now()),
'deadline' => $this->faker->dateTimeBetween(now(), '+1 week'),
'name' => $this->faker->word,
'price' => $this->faker->numberBetween(10,100),
'number' => $this->faker->numberBetween(10,100),
'user_id' => $this->faker->numberBetween(1,3),
'created_at' => $this->faker->datetime($max = 'now', $timezone = date_default_timezone_get()),
'updated_at' => $this->faker->datetime($max = 'now', $timezone = date_default_timezone_get())
];
}
}
下記コマンドでデータベースを再構築します!
※こちらを実行すると再構築するため、今まで登録してあったデータは削除されてしまうのでお気をつけて!
また、docker環境で開発されている方はコンテナに移動してから実行してください。
$ php artisan migrate:refresh --seed
モデルの設定
リレーションの設定をモデルで行います。
// app/Models/Stock.php
class Stock extends Model
{
use HasFactory;
protected $fillable = ['shop','purchase_date','deadline','name','price','number'];
//1対多のリレーション追加
public function user() {
return $this->belongsTo(User::class);
}
}
savingイベントでuser_idを保存するよう設定
保存時にログインユーザーのidをuser_idに保存する処理をします。
この処理はコントローラーに書いてもいいのですが、Laravelにはさまざまなイベントの間に処理を挟むことができるので、今回はイベントで!
データの登録と更新時に同じ処理を行うようsaving
というイベントに処理を追加。
先ほど追加したリレーション設定の下に追加します。
// app/Models/Stock.php
class Stock extends Model
{
use HasFactory;
protected $fillable = ['shop','purchase_date','deadline','name','price','number'];
//1対nのリレーション追加
public function user() {
return $this->belongsTo(User::class);
}
protected static function boot()
{
parent::boot();
// 保存時user_idをログインユーザーに設定
self::saving(function($stock) {
$stock->user_id = \Auth::id();
});
}
}
紐付けたデータを更新もしくは新規追加して、user_idにログインユーザーのIDが登録されるか確認してみてください!
seederを修正
先程のsavingイベントでログイン情報を読み込むような処理をすると、seederのコマンド実行時にもイベントが実行されてしまいエラーが出てしまうようです。(コマンド実行時はログイン情報が取れないので)
Event::fakeForでイベントを実行しないようにすることができるので修正します!
// database/seeders/StocksTableSeeder.php
class StocksTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
// seederのコマンド実行時はイベントを実行しない
\Event::fakeFor(function () {
Stock::factory()->count(20)->create();
});
}
}
これで1対多でユーザー(User)と在庫(stock)の紐付けをすることができました!
ログインユーザーと紐ついた在庫のみ表示させる
参考までに、コントローラで下記のようにするとログインユーザーと紐ついたデータを表示させることができるので試してみてください!
これで、ログイン者ごとに表示されるデータが変わり、複数人で使用できるアプリに変わりました!
<?php
namespace App\Http\Controllers;
use App\Models\Stock; //在庫データを扱えるように
use App\Models\User; //ユーザーデータを扱えるように
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; //ログインユーザーのデータを扱えるように
class StockController extends Controller
{
public function index(Request $request)
{
$user_id = Auth::id(); //ログインユーザーのID取得
$stocks = Stock::with('user')->where('user_id', '=', $user_id)->simplePaginate(8); //ログインユーザーのIDに紐ついた在庫のみ取得
return view('stock.list', ['stocks' => $stocks]); // views/stock/list.blade.phpに取得データを渡す
}
}
// views/stock/list.blade.php
<table>
<thead>
<tr>
<th>期限</th><th>商品</th><th>数量</th>
</tr>
</thead>
<tbody>
@foreach ($stocks as $stock)
<tr>
<td><p>{{$stock->deadline}}</p></td> //取得した在庫データを表示
<td><p>{{$stock->name}}</p></td>
<td><p>{{$stock->number}}</p></td>
</tr>
@endforeach
</tbody>
</table>
<div>
{{ $stocks->links() }} //ペジネーションのリンク
</div>