BNBのプログラミング勉強記録

ガチのプログラミング初心者が駆け上がっていくブログ

Laravel俺用逆引きリファレンス

前提

  • 「Laravelの教科書」という超初心者向けサイトを参考
  • MVCはPostで統一(belongstoとhasmany用にUserも出てくるけど)
  • sail導入前提なのでphp 〇〇のコマンドは全てsail 〇〇 と記述
  • Railsを4ヶ月ほど使ったので、それとの比較も書く
  • シンタックスハイライトのために、phpコードの行頭は統一

コマンドライン

アプリ作る

curl -s "https://laravel.build/アプリ名" | bash

sail立ち上げ

./vendor/bin/sail up

sail 〇〇 が使えるようにする

alias sail='[ -f sail ] && sh sail || sh vendor/bin/sail'

breez(全部のっけ的なスターターキット)

sail composer require laravel/breeze --dev
sail artisan breeze:install 
sail artisan migrate
sail npm install
sail npm run dev

日本語化

sail composer require askdkc/breezejp --dev
sail artisan breezejp

モデル作成(マイグレーション付き)

sail artisan make:model Post -m

マイグレートする

sail artisan migrate

マイグレートしたやつを戻す

sail artisan migrate:rollback

マイグレーションファイル追加(カラム追加)

sail artisan make:migration add_column_user_id_to_posts_table --table=posts

コントローラー作成(resource付き)

sail artisan make:controller PostController --resource --model=Post

コンポーネント作成

sail artisan make:component Message

tinker

起動

rails cみたいなやつ。データベースをいごいごできる。phpmyadminが素人くさすぎて抵抗があって調べたらこれが良さそうだった。

sail artisan tinker

モデル全件取得

$posts = \App\Models\Post::all();

モデル1件取得

$post = \App\Models\Post::find(1);

モデルに何のカラムが入ってるか見る

\Illuminate\Support\Facades\Schema::getColumnListing('posts');

モデル

belongsTo

<?php
    public function user() {
        return $this->belongsTo(User::class);
    } 

hasMany

<?php
    public function posts() {
        return $this->hasMany(Post::class);
    }

submitで受け付けるパラメーターを設定

railsのpermit的なやつか。モデルに書くんだねえ

<?php
    protected $fillable = [
        'title',
        'body',
        'user_id',
        'image',
    ];    

コントローラー

ビューを指定

この場合だと「postフォルダのcreate.blade.php」を指す

<?php
return view('post.create');

インスタンスを作る

<?php
$post=new Post();

インスタンスに代入

上の続き

<?php
$post->title=$request->title;
$post->body=$request->body;

インスタンスに代入(自動で、認証ユーザーのIDを取得)

この辺勉強中だが、Laravelってこのあたりのユーザー認証系が、標準で組み込まれてるみたい。この辺はRailsよりもかなりとっつきやすいのでは。

<?php
$post->user_id=auth()->user()->id;

インスタンスをデータベースに保存

<?php
$post->save();

リダイレクト

<?php
return redirect()->route('post.create');

メッセージ表示

Railsflash的なやつか?

<?php
return redirect()->route('post.create')->with('message', '投稿を作成しました');

バリデーション

<?php
        $inputs=$request->validate([
            'title'=>'required|max:255',
            'body'=>'required|max:1000',
            'image'=>'image|max:1024'
        ]);
        
        $post=new Post();
        $post->title=$inputs['title'];
        $post->body=$inputs['body'];
         //以下略。ちなみに、インスタンス作成時にわざわざinputsに置き換える必要もない

ビュー

共通のビュー

app.blade.phpの下記の部分が、他のビューの中身になる。言い換えると、それ以外は共通。Railsと一緒。

<?php
{{ $slot }}

中身にするには

上記の続き。各ビューは、下記タグで囲む。

<?php
<x-app-layout>
</x-app-layout>

フォーム

  • このケースは、postコントローラーのstoreアクションを使う
  • @csrfを入れることで、クロスサイトリクエストフォージェリ(Webアプリケーションのユーザーが意図しないリクエストを偽造し、ユーザーが意図しない処理を実行させる攻撃)を防ぐ
<?php
<form method="post" action="{{route('post.store')}}" enctype="multipart/form-data">
@csrf

コンポーネントを使う(breez標準付属のprimary-button)

<?php
<x-primary-button class="mt-4">
送信する
</x-primary-button>

コンポーネントコンストラクター設定

Messageというコンポーネントの場合。下記はMessage.phpに書く。オブジェクト指向コンストラクターですな。あ、「コンポーネントコンストラクター」って「長久命の長助さん」っぽいな

<?php
    public $message;

    public function __construct($message)
    {
        $this->message = $message;
    }

コンポーネント本体

上記の続き(上記とセットでコンポーネントを作るのが基本のやり方)。下記はmessage.blade.phpに書く。issetは、変数が存在するかの真偽値を返すphpの組み込み関数。Railsだとこんなの付けなくても変数だけ書いたんでよかったような・・。exist?か。いかん、この辺の理解が浅いな。戻り値をどうするかで使い分けるんだっけ。trueではなかったときにnilかfalseかというところで。

<?php
@if(isset($message))
<div>
    {{$message}}
</div>
@endif

コンポーネントを使用する

<?php
// <x-ファイル名> </ファイル名>
// <x-ファイル名 :データ名=データの定義> </ファイル名>
// <x-ファイル名 :データ名=データの定義 />

<x-message :message="session('message')" />

匿名コンポーネント

上記の例でいくと、コンストラクター用のMessage.phpを作らず、message.blade.phpだけを作ること。使用の仕方は上記と同じ。

<?php
@props(['message'])

@if(isset($message))
<div>
    {{$message}}
</div>
@endif

標準コンポーネント(バリデーションエラー)

<?php
<x-input-error class="mb-4" :messages="$errors->all()"/>

バリデーションエラー後、入力したものを自動入力してくれる

これもRailsのform_withだと標準ではあるけど、こっちの方が明示的で好感が持てるなあ。ほんまform_with嫌い。書き方が柔軟すぎて。

<?php
value="{{old('title')}}" 

コンポーネント(カスタマイズしたバリデーションエラー)

Laravel教科書では、画像を再添付させるためにカスタムコンポーネントを使用している。注意書きレベルのものをエラーと同じ文字装飾で表示するのってどうなんだろう。なんか引っかかるなあ。

<?php
@props(['errors'])

@if ($errors->any())
    <div {{ $attributes }}>
        <div class="font-medium text-red-600">
            エラーの内容を確認してください。
        </div>

        <ul class="mt-3 list-disc list-inside text-sm text-red-600">
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach

            @if(empty($errors->first('image')))
                <li>画像ファイルがあれば、再度、選択してください。</li>
            @endif
        </ul>
    </div>
@endif

ルーティング

resource

<?php
Route::resource('post', PostController::class);

上記を分解

<?php
Route::get('post', [PostController::class, 'index'])->name('post.index');
Route::get('post/create', [PostController::class, 'create'])->name('post.create');
Route::post('post', [PostController::class, 'store'])->name('post.store');
Route::get('post/{post}', [PostController::class, 'show'])->name('post.show');
Route::get('post/{post}/edit', [PostController::class, 'edit'])->name('post.edit');
Route::patch('post/{post}', [PostController::class, 'update'])->name('post.update');
Route::delete('post/{post}', [PostController::class, 'destroy'])->name('post.destroy');

マイグレーションファイル

モデル新規作成時にカラムを設定

nullableとすると、必須ではなくなる。これ、もしかしてバリデーション的なものなのか?この辺は勉強。

<?php
$table->string('title');
$table->text('image')->nullable();

foreignId

ここもよく分からん。integerではないのは、他のモデルのidを使うからか?それともbelongsしてるからか?

<?php
$table->foreignId('user_id');

特定のカラムの後に追加

一発目のマイグレート以降のカラム追加時に使う。

<?php
$table->foreignId('user_id')->after('image');

カラム削除

どうも、LaravelはRailsと違って、マイグレーションファイルは常にupとdownを書かないといけないようだ。(ほんと?)

<?php
$table->dropColumn('user_id');