LaravelでやっっとDBにデータ保存まで行けた

やっっとDBにデータ保存する所までは行けたので、忘れないようにメモ。

いやー、Laravel9って初歩的な記事…少なくね?
それとも他のバージョンでの記事が多いから見つけ辛かったのかな?

ログイン機能

./vendor/bin/sail composer require laravel/breeze --dev
./vendor/bin/sail php artisan breeze:install
./vendor/bin/sail npm install
./vendor/bin/sail npm run dev

こんな感じ(あってるか知らん)。
まだ、./vendor/bin/sail npm run devをどうやってバックグラウンドにするか悩み中です。
探しても、終了時にはpsでプロセス番号を確認してkillみたいなのしか無い。
…面倒くない?

あと、これによってvite(だっけ?)とやらが実装されます。
それに不具合が残ってるっぽいです。
一応localhostにアクセスすると動いているのは確認出来ますが、loginとかのページに移動するとCSSが効いて無い状態になります。
これは下記ファイルを手動で修正する以外に対応方法は無さげです。

- http://0.0.0.0:5173
+ http://localhost:5173

うん、なぜかlocalhostじゃなく0.0.0.0で作られるんですよね。
で、色々やっても大元は修正出来なかったので、仕方なく上記ファイルを手動で変更しています。
これ、./vendor/bin/sail npm run devを実行する度に修正する必要があるので面倒だけど…しゃーない。

controllerとかmodelとかrouteとか

分からんなりに頑張った。

./vendor/bin/sail artisan make:model Post
./vendor/bin/saiartisan make:controller PostController --resource --model=Post --requests

こんな雰囲気で作りました。
model 作る時に–allってオプションでコントローラーとかも作ってくれるらしいね!知らね。

あと、URLとコントローラーを紐づけるrouterに登録しないと動かない。
とりあえずRoute::resource()ってヤツで基本的なCRUD系のアクションを指定しなくてもOKになるみたい。

use App\Http\Controllers\PostController;
Route::resource('post', PostController::class);

他にセキュアなやり方とか色々とやり方あるんでしょうが…とりあえず動いたのでいいや。

viewの方は…ログイン関連で生成されたbladeテンプレートを参考にしながら準備。
bladeテンプレートは…そこまで混乱しませんでした。
都度、調べていけば問題ないかもー!

migration

やってみた。
softdeleteとか簡単につけられるらしい。

$table->softDeletes();

関連付けも命名規則に従えば簡単。
よくある投稿したユーザーのユーザーIDを保存したいなら下記のように設定すればOKらしい。

$table->foreignId('user_id')->constrained()->onDelete('cascade');

簡単!
でもこの後、このuser_idのセット方法で苦労しました…。

MySQLさんって今は素で全文検索とか出来るらしく、Laravelでも簡単に利用出来るらしい。
その内試してみたいな。
10年以上前は1000万pv/dayを超えるサイトでも検索にlike使ってたわw

あと、掲示板とか記事コメントのようにユーザーが書き込む系のヤツだとIPアドレスやポート番号も保存したいじゃないですか?
それ用のプラグインとか無いのかな…?
不思議。

Requestのrulesを使ったバリデーションで躓く

Postにtitle,body,user_idを保存する、みたいな?

普通にコントローラーのindexとcreateでviewを指定、そのviewを作成(最低限必要な要素のみ)。
そんでcreateフォームからstoreに飛ばし、投稿処理してindexにリダイレクト。
そんなシンプルな流れでデータベースに保存する所までやりました。

app/Http/Requests/StorePostRequest.phpとか出来てる筈。
ここのrulesにバリデーション書けばいいんだな。
コントローラーで取得した$requestに直接ルール書くのは簡易過ぎるっぽいし。

    public function rules()
    {
        return [
            'title'=> 'required|max:255',
            'body' => 'required|max:2000',
            'user_id' => 'required|exists:users,id',
        ];
    }

この変なコダワリで苦労しました。
user_idはcreateフォームに<input type=”hidden” user_id=”99″>のように埋め込んじゃ駄目だろ。
store()に来た時に$user_id = $request->user()->idって感じでセットしないと駄目だよね。

        $validated = $request->validated();
        $validated->merge(['user_id'=>$request->user()->id]);
        $post= new Post;
        $post->create( $validated );

よし、createのフォームviewも適当に用意して投稿!
エラーになる。
user_idは必須ですよって。
入れてるやん!
謎現象で$request->user()->idの返り値がnullになってるとか?
コントローラーのstore関数の頭でdd($request->user()->id);とするもエラー表示のまま。
ナンデ?

数時間悩んで…「store関数の前にStorePostRequest.phpのrules使ってバリデーションしてね?」となりました。
試しにapp/Http/Requests/StorePostRequest.phpでuser_idからrequiredを外してみると、dd($request->user()->id); の結果が表示される。
やっぱり!!

ならばとvalidationの前にかかるフック(?)を探せばいいだけ。
Http/Requests/StorePostRequest.phpにprepareForValidation()を追加します。

    protected function prepareForValidation()
    {
        $this->merge([ 'user_id' => $this->user()->id ]);
    }

アトはrulesのuser_idにrequiredも再設定して…動きました!

user_idを保存するだけで1日以上かかりましたw
これもapp/Http/Requests/StorePostRequest.phpのrules()でバリデーションを設定させたのが原因。
store()で引数の$requestにバリデーションを設定すればstore()の実行前にバリデーションされる事も無いので簡単です。多分。

public function store(Request $request)
{
    $request->merge(['user_id'=> $request->user()->id]);
    $validated = $request->validate([
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
        'user_id' => 'required|exists:users,id',
    ]);
}

きっとこんな感じでいけるよね。
妄想で書いてみたけどw
でもファットコントローラー害悪論を昔に見た気がするのでコントローラーにバリデーションの設定を書くのは気が引けるんですよね。
「modelに$requestを渡してそっちで書けばよくね?」
うーん…どうなん?
正直、最初はmodelに$requestを渡す形式で書いてましたが、途中で上記のRequestのファイルにrulesって関数があると知ったので、用意されてるのならソッチに書こうとなりました。

あるモデルのバリデーション設定が複数のコントローラーに散らばる可能性があるのは微妙かなーって思います!

でも…今気づいたけど、storeとupdateしかRequestファイル生成されてないけどそれ以外のアクションで更新する時って…どこにバリデーション書けばいいのだろう?

public function store2(Store2PostRequest $request)

こんな感じでコントローラーのメソッドの引数で指定して、Requestファイルを生成したらいいのかな?

コメント

タイトルとURLをコピーしました