Laravel初学者です。
オリジナルアプリを作成しているのでその過程を記事にしています。
理解が曖昧なところも多いため、ご指摘等ありましたらご連絡いただければ幸いです。
今回は投稿保存の実装について備忘録のため記録として残します。
前回の記事:【Laravel初心者】一覧表示の実装
環境
Version | |
---|---|
PHP | 7.4.14 |
Laravel | 8.24.0 |
mysql | 8.0.23 |
docker | 20.10.2 |
docker-compose | 1.27.4 |
ルーティング
Route::resource('/game', App\Http\Controllers\GameController::class)->only(['create','store']);
resource
でcreate
とstore
を指定します。
resourceについては以下の記事がとても分かりやすかったです。ありがとうございます!
参考:LaravelでRoute::resourceを使うときに気をつけること
create
とstore
の役割としては
- create→投稿画面の生成とstoreへデータを送信する役割
- store→データを受け取り保存する役割
です。
モデル
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Game extends Model
{
use HasFactory;
protected $table = "games";
protected $fillable = [
"id",
"user_id",
"name",
"describe",
"play_time",
"players_minimum",
"players_max",
"image_path",
"updated_at",
"created_at",
];
public function user()
{
return $this->belongsTo(User::class);
}
}
$fillable
で指定して保存を許可します。指定してないとエラーになります。
$fillable
についてはこちらの記事が分かりやすかったです。
ありがとうございます。
マイグレーションファイル
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateGamesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('games', function (Blueprint $table) {
$table->id();
$table->bigInteger('user_id');
$table->string('name');
$table->text('describe');
$table->integer('play_time');
$table->integer('players_minimum');
$table->integer('players_max');
$table->string('image_path')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('games');
}
}
上記の内容でカラムを作成しました。
コントローラー
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
//以下createアクションでviewを表示する
public function create()
{
return view('game.create');
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
//以下storeアクション
public function store(Request $request)
{
$input = $request->only('user_id', 'name', 'describe', 'play_time', 'players_minimum', 'players_max', 'image_path');
$game = new Game();
$game->user_id = Auth::id();
$game->name = $input["name"];
$game->describe = $input["describe"];
$game->play_time = $input["play_time"];
$game->players_minimum = $input["players_minimum"];
$game->players_max = $input["players_max"];
//以下3行はAWSのS3に保存するための記述
$image = $request->file('image');
$path = Storage::disk('s3')->putFile('bgame', $image, 'public');
$game->image_path = Storage::disk('s3')->url($path);
//saveで保存
$game->save();
return redirect('/')->with('success', '投稿しました');
}
create
はビューを返すだけのアクションです。
store
で保存をしています。
このstoreについてはいろいろな書き方があり勉強になりました。
ビュー
<div class="container mt-4">
<div class="border p-4">
<h1 class="h4 mb-4 font-weight-bold">新規作成</h1>
<form action="{{ route('game.store') }}" enctype="multipart/form-data" method="POST" id="new">
@csrf
<fieldset class="mb-4">
<div class="form-group">
<label for="subject">
ボードゲーム名
</label>
<input
id="name"
type="text"
name="name"
value="{{old('name')}}"
class="form-control"
>
</div>
<div class="form-group">
<label for="subject">
商品説明
</label>
<textarea
id="new"
name="describe"
value="{{old('describe')}}"
class="form-control"
rows="8"
>
</textarea>
</div>
<div class="form-group">
<label for="subject">
プレイ時間
</label>
<input
type="number"
name="play_time"
value="{{old('play_time')}}"
class="form-control"
>
</div>
<div class="form-group">
<label for="subject">
最小プレイ人数
</label>
<input
type="number"
name="players_minimum"
value="{{old('players_minimum')}}"
class="form-control"
>
</div>
<div class="form-group">
<label for="subject">
最大プレイ人数
</label>
<input
type="text"
name="players_max"
value="{{old('players_max')}}"
class="form-control"
>
</div>
<div class="form-group">
<label for="exampleInputFile">
商品画像
</label>
<input
id="image"
type='file'
name="image"
accept="image/png, image/jpeg"
class="form-control-file"
>
</div>
<button type="submit" class="btn btn-primary">
投稿する
</button>
</fieldset>
</form>
</div>
</div>
Bootstrapを活用して作成しています。
以下の記事に作り方をまとめています。
【Laravel初心者】BootstrapでのFormの作り方
<form action="{{ route('game.store') }}" enctype="multipart/form-data" method="POST" id="new">
重要なところは上記の部分でしょうか。
action="{{ route('game.store') }}"
でstoreへデータを送信します。
画像がある場合はenctype="multipart/form-data"
がないとエラーになりました。
method="POST"
でメソッドを指定しています。
以上で実装ができました。