tiger9810 / Laravel-Chirper

0 stars 0 forks source link

Chirpを保存する #7

Open tiger9810 opened 1 year ago

tiger9810 commented 1 year ago

index.blade.phpのフォームのaction属性がchirps.storeに設定されています。 <form method="POST" action="{{ route('chirps.store') }}"> なので、app/Http/Controllers/ChirpController.phpのstoreメソッドを編集していきます。

ChirpController.php

app/Http/Controllers/ChirpController.phpの名前空間が定義されている箇所にuse Illuminate\Http\RedirectResponse;を追加します。参考(Chirpを保存する) 次にstoreメソッドの中身を変更していきます。

    public function store(Request $request): RedirectResponse
    {
        // リクエストから取得したデータを検証します。'message'フィールドは必須で、文字列でなければならず、最大255文字である必要があります。
        $validated = $request->validate([
            'message' => 'required|string|max:255',
        ]);

        // 現在認証されているユーザー($request->user())が所有するchirpsに、バリデーション済みのデータを使って新たなchirpを作成します。
        $request->user()->chirps()->create($validated);

        // 処理が終わったら、ユーザーをchirps.indexルート(つぶやき一覧画面)へリダイレクトします。
        return redirect(route('chirps.index'));
    }

User.php

$request->user()オブジェクトのchirpsメソッドを使用しているので、Models/User.phpを編集して、UserモデルがChirpモデルと一対多のリレーションシップを持つことを定義します。 つまり、各個人のユーザーがそれぞれ複数のChirpsを持つことができるということを定義します。 app/Models/User.php

use Illuminate\Database\Eloquent\Relations\HasMany;

class User extends Authenticatable
{
 ...
    public function chirps(): HasMany
    {
        return $this->hasMany(Chirp::class);
    }
}

Chirp.php(Mass assignmentの保護)

リクエストからモデルにすべてのデータを渡すことは危険です。ユーザーがプロフィールを編集できるページがあると想像してください。もしリクエスト全体をモデルに渡すと、ユーザーはis_adminカラムなど、好きなカラムを編集することができます。これはMass assignmentの脆弱性と呼ばれます。 Chirpモデルに$fillableプロパティを追加して、message属性に対してMass assignmentを有効にしましょう。 app/Models/Chirp.php

class Chirp extends Model
{
    protected $fillable = [
        'message',
    ];
}

マイグレーションの更新

ここまで設定できたら、ChirpとそのUserの関係性とメッセージそのものを格納するためのカラムを追加します。以前に作成したデータベースのマイグレーションを思い出してください。それを開いて、いくつかの追加のカラムを追加する時がきました。 databases/migration/<timestamp>_create_chirps_table.php

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('chirps', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->string('message');
            $table->timestamps();
        });
    }
 ...
};

ここまで設定できたら、./vendor/bin/sail artisan tinkerコマンドをターミナルに入力して、tinkerセッションを開始します。

App\Models\Chirp::all();

を実行すると、

= Illuminate\Database\Eloquent\Collection {#7226
    all: [
      App\Models\Chirp {#7228
        id: 1,
        user_id: 1,
        message: "hjh",
        created_at: "2023-06-04 22:01:50",
        updated_at: "2023-06-04 22:01:50",
      },

のような結果が出力されていれば、成功です。

tiger9810 commented 1 year ago

Route::resource('chirps', ChirpController::class) ルートの定義では、名前付きルートが自動的に生成されます。

具体的には、名前付きルートの命名規則は以下のようになります:

chirps.index: チャープ一覧表示のためのルート chirps.store: チャープ保存のためのルート ですので、上記のルート定義では name メソッドを使用していませんが、名前付きルートが生成されます。

tiger9810 commented 1 year ago

$request->user()->chirps()->create($validated);は、Laravel フレームワークの中でよく使用されるパターンの一つです。特に、認証されたユーザーに関連するデータを保存する際に頻繁に使用されます。

理解するべきポイントは次のとおりです:

$request オブジェクトは、リクエストに関連するデータへのアクセスを提供します。 $request->user() は、認証された現在のユーザーを表します。 chirps() は、ユーザーモデルとチャープモデルの間の関連付けを定義したメソッドです。 create($validated) は、関連付けられたモデルを使用して新しいレコードをデータベースに作成します。 このパターンを覚えておくと、ユーザーが関連するデータを作成、保存、表示する際に便利です。

$request->user()->chirps() の部分で、$requestオブジェクトuser()メソッドの chirps メソッドが呼び出されています。userメソッドは、$request オブジェクトから取得されますが、その詳細な定義は $request オブジェクト自体ではなく、Laravel の認証システムによって提供されます。

Laravel の認証システムでは、ユーザー情報を表すために User モデルを使用します。User モデルは通常、app/Models ディレクトリ内に配置されます。

具体的には、User モデルには chirps メソッドが定義されています。このメソッドは、User モデルが Chirp モデルとの間に定義されたリレーションシップを表現しています。

$request->user()は、現在認証されているユーザーのインスタンスを返します。これは通常、Userモデルのインスタンスであり、Models/User.phpで定義されているクラスのインスタンスになります。

したがって、$request->user()->chirps()で$request->user()はUserオブジェクトになり、そのUserオブジェクトのchirps()メソッドを呼び出すという流れです。

tiger9810 commented 1 year ago

「モデル」とは、

データベースのテーブルと対応するものです。データベースは、たくさんの情報を整理して保存する場所です。例えば、学校の生徒名簿や本の一覧などがデータベースに保存される情報です。

「モデル」は、そのデータベースの情報を取り扱うためのクラスです。クラスは、特定の役割や機能を持つプログラムのかたまりのことです。モデルは、データベースの情報を取得したり、保存したり、関連する情報にアクセスしたりするための便利な機能を提供します。

例えば、「User(ユーザー)」というモデルがあるとします。これは、ユーザーに関連する情報(名前やメールアドレスなど)をデータベースに保存したり、その情報を取得したりするための機能を提供します。

モデルを使うことで、データベースの情報を簡単に取得したり、保存したりできます。

ビジネスロジックとは、アプリケーションで行われる具体的な処理や操作のことを指します。

例えば、新しいユーザーを作成する処理や、特定の条件に合ったデータを検索する処理などがビジネスロジックになります。

モデルは、アプリケーションの中でデータの管理や操作を担当し、ビジネスロジックを実行するための道具です。

データベースの情報を扱う際に便利に利用されます。

tiger9810 commented 1 year ago

$request 引数には、HTTP リクエストに関する情報やデータが含まれています。具体的には、以下のような情報が $request インスタンスに格納されています。

リクエストのメソッド(GET、POST、PUT、DELETE など) リクエストの URL パス(/chirps など) リクエストヘッダー(User-Agent、Content-Type など) リクエストパラメーター(クエリ文字列やフォームデータなど) セッション情報 認証情報(ログインしているユーザーの情報など) アップロードされたファイル(ファイルアップロードが行われた場合) これらの情報は、$request インスタンスのプロパティやメソッドを介してアクセスできます。例えば、$request->input('name') のような形式でリクエストのパラメーターを取得したり、$request->file('avatar') のような形式でアップロードされたファイルを取得したりすることができます。

tiger9810 commented 1 year ago

store アクションにアクセスした場合、一般的には以下のようなリクエストデータが $request 引数として提供されます。

フォームデータ:通常、フォームからの入力データが $request インスタンスに含まれます。例えば、 要素の値や、チェックボックスやラジオボタンの選択状態などが含まれます。 JSON データ:もしリクエストのヘッダーで Content-Type を application/json に指定している場合、リクエストボディ内の JSON データが $request インスタンスに含まれます。 ファイルアップロード:もしフォームにファイルアップロードフィールドが含まれている場合、アップロードされたファイルデータが $request インスタンスに含まれます。ファイルデータは $request->file('fieldName') などのメソッドを使用して取得できます。 認証情報:もし認証が有効になっている場合、$request インスタンスには認証されたユーザーに関連する情報が含まれます。例えば、ログインユーザーの情報は $request->user() で取得できます。 これらのリクエストデータは、$request インスタンスのメソッドやプロパティを使用して取得できます。具体的には、$request->input('fieldName') や $request->all() などのメソッドを使用してデータにアクセスできます。

tiger9810 commented 1 year ago

use Illuminate\Http\RedirectResponse;はLaravelフレームワークにおける名前空間の宣言です。

PHPでは、名前空間(namespace)は主にコードの組織化と衝突を防ぐために使用されます。つまり、同じ名前のクラスや関数が存在する場合でも、それらが異なる名前空間に属していれば、その名前が衝突することなく使用することができます。

useキーワードは、そのファイルで特定のクラス、関数、または定数を簡単に参照するために使用されます。これは特定の名前空間からクラスや関数を"インポート"するようなものです。

そして、Illuminate\Http\RedirectResponseはLaravelフレームワークのクラスの1つで、HTTPリダイレクトレスポンスを生成し、管理するためのメソッドを提供しています。このクラスを使用すると、特定のURLへのリダイレクト、特定のルートやアクションへのリダイレクトなど、さまざまな形式のリダイレクトを簡単に生成できます。

したがって、use Illuminate\Http\RedirectResponse;は、このファイル内でRedirectResponseクラスを簡単に参照できるようにするためのものです。

tiger9810 commented 1 year ago

データベースのフィールドは、オブジェクト指向プログラミングにおけるオブジェクトのプロパティ(または属性)に相当します。オブジェクトは複数のプロパティとメソッド(操作)を持つことができ、これらはオブジェクトの状態と振る舞いを定義します。

データベーステーブルにおけるフィールド(列)は、そのテーブルの各レコードに含まれる特定のデータを表し、この意味でオブジェクトのプロパティと類似しています。

オブジェクト指向プログラミングとデータベース設計の間には、このような対応関係がしばしば見られます。そして、オブジェクトリレーショナルマッピング(ORM)システムの一つであるEloquentは、これら二つの世界をつなぐ役割を果たしています。

tiger9810 commented 1 year ago

./vendor/bin/sail artisan migrate

具体的な操作としては、以下のようなことを行います:

未実行のマイグレーションファイルを特定します。 マイグレーションファイルに記述されたアップメソッドを実行し、データベースに新しいテーブルやカラムを作成します。 マイグレーションテーブル(デフォルトではmigrationsテーブル)に実行済みのマイグレーションを記録します。 実行済みのマイグレーションは、再実行されることなくスキップされます。 マイグレーションの実行順序は、ファイル名のタイムスタンプに基づいて決定されます。