Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Eloquentとクエリビルダを両方使った実装の失敗例 - 第150回 PHP勉強会 #phpstudy

Eloquentとクエリビルダを両方使った実装の失敗例 - 第150回 PHP勉強会 #phpstudy

ことみん / kotomin_m

March 15, 2023
Tweet

More Decks by ことみん / kotomin_m

Other Decks in Programming

Transcript

  1. @kotomin_m #phpstudy
    Eloquentとクエリビルダを
    両方使った実装の失敗例
    ことみん
    第150回 PHP勉強会@東京
    @kotomin_m #phpstudy

    View full-size slide

  2. @kotomin_m #phpstudy
    ことみん @kotomin_m

    所属:
     株式会社ウィルゲート 21卒
    趣味:
     LT会とカンファレンス
    特技:
     懇親会で仲良くなる


    View full-size slide

  3. @kotomin_m #phpstudy
    1. 用語を知ろう

    2. 実装の失敗例

    Eloquentとクエリビルダを

    両方使った実装の失敗例


    View full-size slide

  4. @kotomin_m #phpstudy
    用語を知ろう

    ● Eloquent

    ● アクセサ

    ● ミューテタ

    ● クエリビルダ


    View full-size slide

  5. @kotomin_m #phpstudy
    Eloquent


    View full-size slide

  6. @kotomin_m #phpstudy
    Eloquent

    ● データベース操作を楽しくする、オブジェクトリ
    レーショナルマッパー(ORM)

    ● 各データベーステーブルに対応する「モデル」
    を使用

    ● レコードの取得、挿入、更新、削除が可能

    https://readouble.com/laravel/10.x/ja/eloquent.html

    View full-size slide

  7. @kotomin_m #phpstudy
    アクセサ


    View full-size slide

  8. @kotomin_m #phpstudy
    アクセサ

    Eloquentの属性値にアクセスがあった時に、その
    値を変換するもの

    https://readouble.com/laravel/10.x/ja/eloquent-mutators.html

    View full-size slide

  9. @kotomin_m #phpstudy
    アクセサ(Laravel 5.6)

    アクセスしたいカラム名がFooの場合、
    getFooAttributeメソッドをモデルに作成

    https://readouble.com/laravel/5.6/ja/eloquent-mutators.html

    View full-size slide

  10. @kotomin_m #phpstudy
    アクセサ(Laravel 5.6)

    class User extends Model

    {

    /**

    * @param string $value

    * @return string

    */

    public function getFirstNameAttribute($value)

    {

    // 復号する

    return decrypt($value);

    }

    }


    View full-size slide

  11. @kotomin_m #phpstudy
    アクセサ(Laravel 10.x)

    ● メソッド名はカラム名の「キャメルケース」で
    protectedなメソッドをモデルに作成

    ● 戻り値のタイプヒントは
    Illuminate\Database\Eloquent\Casts\Attribute

    ○ Attributeクラスのコンストラクタにget引数を与えます。

    https://readouble.com/laravel/10.x/ja/eloquent-mutators.html

    View full-size slide

  12. @kotomin_m #phpstudy
    class User extends Model

    {

    /**

    * ユーザの名前取得

    */

    protected function firstName(): Attribute

    {

    return Attribute::make(

    get: fn (string $value) => ucfirst($value),

    );

    }

    }

    アクセサ(Laravel 10.x)


    View full-size slide

  13. @kotomin_m #phpstudy
    ミューテタ


    View full-size slide

  14. @kotomin_m #phpstudy
    ミューテタ

    Eloquentの属性値を設定するときに、その値を変
    換するもの

    https://readouble.com/laravel/10.x/ja/eloquent-mutators.html

    View full-size slide

  15. @kotomin_m #phpstudy
    ミューテタ(Laravel 5.6)

    アクセスしたいカラム名がFooの場合、
    setFooAttributeメソッドをモデルに作成

    https://readouble.com/laravel/5.6/ja/eloquent-mutators.html

    View full-size slide

  16. @kotomin_m #phpstudy
    ミューテタ(Laravel 5.6)

    class User extends Model

    {

    /**

    * @param string $value

    * @return void

    */

    public function setFirstNameAttribute($value)

    {

    // 暗号化する

    $this->attributes['first_name'] = encrypt($value);

    }

    }


    View full-size slide

  17. @kotomin_m #phpstudy
    ミューテタ(Laravel 10.x)

    属性を定義するときに set という引数を指定する

    https://readouble.com/laravel/10.x/ja/eloquent-mutators.html

    View full-size slide

  18. @kotomin_m #phpstudy
    class User extends Model

    {

    protected function firstName(): Attribute

    {

    return Attribute::make(

    get: fn (string $value) => ucfirst($value),

    set: fn (string $value) => strtolower($value),

    );

    }

    }

    ミューテタ(Laravel 10.x)


    View full-size slide

  19. @kotomin_m #phpstudy
    クエリビルダ


    View full-size slide

  20. @kotomin_m #phpstudy
    クエリビルダ

    ● クエリを作成し実行するために使用

    ● アプリケーションで行われるほとんどのデータ
    ベース操作が可能

    ○ select, where ……

    https://readouble.com/laravel/5.6/ja/queries.html

    View full-size slide

  21. @kotomin_m #phpstudy
    クエリビルダ

    $users = DB::table('users')

    ->select('name','email as user_email')

    ->get();


    View full-size slide

  22. @kotomin_m #phpstudy
    Eloquentとクエリビルダ

    組み合わせた実装の失敗例


    View full-size slide

  23. @kotomin_m #phpstudy
    // クエリビルダでデータベースから値を取得

    $users = DB::table('users')

    ->select('id','first_name', 'last_name')

    ->get();


    // EloquentのupdateOrCreate()を利用してDBを更新

    $this->userHistory->updateOrCreate(

    ['user_id' => $users->id],

    [

    'last_name' => $users->last_name,

    'first_name' => $users->first_name,

    ]

    );


    View full-size slide

  24. @kotomin_m #phpstudy
    // クエリビルダでデータベースから値を取得

    $users = DB::table('users')

    ->select('id','first_name', 'last_name')

    ->get();


    // EloquentのupdateOrCreate()を利用してDBを更新

    $this->userHistory->updateOrCreate(

    ['user_id' => $users->id],

    [

    'last_name' => $users->last_name,

    'first_name' => $users->first_name,

    ]

    );


    View full-size slide

  25. @kotomin_m #phpstudy
    // クエリビルダでデータベースから値を取得

    $users = DB::table('users')

    ->select('id','first_name', 'last_name')

    ->get();


    // EloquentのupdateOrCreate()を利用してDBを更新

    $this->userHistory->updateOrCreate(

    ['user_id' => $users->id],

    [

    'last_name' => $users->last_name,

    'first_name' => $users->first_name,

    ]

    );


    View full-size slide

  26. @kotomin_m #phpstudy
    // クエリビルダでデータベースから値を取得

    $users = DB::table('users')

    ->select('id','first_name', 'last_name')

    ->get();


    // EloquentのupdateOrCreate()を利用してDBを更新

    $this->userHistory->updateOrCreate(

    ['user_id' => $users->id],

    [

    'last_name' => $users->last_name,

    'first_name' => $users->first_name,

    ]

    );


    getメソッドは、クエリの結果を含む 

    Illuminate\Support\Collection 

    インスタンスを返す


    View full-size slide

  27. @kotomin_m #phpstudy
    // クエリビルダでデータベースから値を取得

    $users = DB::table('users')

    ->select('id','first_name', 'last_name')

    ->get();


    // EloquentのupdateOrCreate()を利用してDBを更新

    $this->userHistory->updateOrCreate(

    ['user_id' => $users->id],

    [

    'last_name' => $users->last_name,

    'first_name' => $users->first_name,

    ]

    );


    Eloquentで使用するモデル 


    View full-size slide

  28. @kotomin_m #phpstudy
    // クエリビルダでデータベースから値を取得

    $users = DB::table('users')

    ->select('id','first_name', 'last_name')

    ->get();


    // EloquentのupdateOrCreate()を利用してDBを更新

    $this->userHistory->updateOrCreate(

    ['user_id' => $users->id],

    [

    'last_name' => $users->last_name,

    'first_name' => $users->first_name,

    ]

    );


    第一引数に指定したカラムのモデルが
    存在していたら更新、なかったら追加す
    る


    View full-size slide

  29. @kotomin_m #phpstudy
    // クエリビルダでデータベースから値を取得

    $users = DB::table('users')

    ->select('id','first_name', 'last_name')

    ->get();


    // EloquentのupdateOrCreate()を利用してDBを更新

    $this->userHistory->updateOrCreate(

    ['user_id' => $users->id],

    [

    'last_name' => $users->last_name,

    'first_name' => $users->first_name,

    ]

    );


    ユーザ履歴テーブル(user_history)の 

    user_idと$users->idが一致するモデルが
    あれば更新、なかったら追加する 


    View full-size slide

  30. @kotomin_m #phpstudy
    // クエリビルダでデータベースから値を取得

    $users = DB::table('users')

    ->select('id','first_name', 'last_name')

    ->get();


    // EloquentのupdateOrCreate()を利用してDBを更新

    $this->userHistory->updateOrCreate(

    ['user_id' => $users->id],

    [

    'last_name' => $users->last_name,

    'first_name' => $users->first_name,

    ]

    );



    View full-size slide

  31. @kotomin_m #phpstudy
    // クエリビルダでデータベースから値を取得

    $users = DB::table('users')

    ->select('id','first_name', 'last_name')

    ->get();


    // EloquentのupdateOrCreate()を利用してDBを更新

    $this->userHistory->updateOrCreate(

    ['user_id' => $users->id],

    [

    'last_name' => $users->last_name,

    'first_name' => $users->first_name,

    ]

    );


    ミューテタが使われるので、暗号化されて
    保存


    View full-size slide

  32. @kotomin_m #phpstudy
    // クエリビルダでデータベースから値を取得

    $users = DB::table('users')

    ->select('id','first_name', 'last_name')

    ->get();


    // EloquentのupdateOrCreate()を利用してDBを更新

    $this->userHistory->updateOrCreate(

    ['user_id' => $users->id],

    [

    'last_name' => $users->last_name,

    'first_name' => $users->first_name,

    ]

    );


    クエリビルダで取得しているので、アク
    セサが使われない

    →複合されていない名前を取得してい
    る


    View full-size slide

  33. @kotomin_m #phpstudy
    // クエリビルダでデータベースから値を取得

    $users = DB::table('users')

    ->select('id','first_name', 'last_name')

    ->get();


    // EloquentのupdateOrCreate()を利用してDBを更新

    $this->userHistory->updateOrCreate(

    ['user_id' => $users->id],

    [

    'last_name' => $users->last_name,

    'first_name' => $users->first_name,

    ]

    );


    すでに暗号化された状態のデータを
    さらに暗号化して保存 


    View full-size slide

  34. @kotomin_m #phpstudy
    // クエリビルダでデータベースから値を取得

    $users = DB::table('users')

    ->select('id','first_name', 'last_name')

    ->get();


    // EloquentのupdateOrCreate()を利用してDBを更新

    $this->userHistory->updateOrCreate(

    ['user_id' => $users->id],

    [

    'last_name' => $users->last_name,

    'first_name' => $users->first_name,

    ]

    );


    失敗→二重で暗号化されてデータ
    ベースに保存されていた


    View full-size slide

  35. @kotomin_m #phpstudy
    Eloquentとクエリビルダを
    両方使った実装の失敗例
    ことみん
    第150回 PHP勉強会@東京
    @kotomin_m #phpstudy

    View full-size slide