MVCでカート機能1 - Model編 for Laravel


考え方

ModelはDBからの読み書きと(それに付随する処理)を担当します。
ViewはUI。
ControllerはModelとViewの架け橋。

データベース

DBカラム
items : id | name | content | price | quantity | created_at | updated_at | deleted_at
carts : id | user_id | item_id | quantity | created_at | updated_at | deleted_at

ソース

app/Cart.php
<?php
namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\facades\Auth;

class Cart extends Model
{
    use SoftDeletes; //ソフトデリート準備
    protected $fillable = ['user_id', 'item_id', 'quantity'];
    protected $table = 'carts';

    public function item() {
        //リレーション
        return $this->belongsTo('App\Item', 'item_id');
    }

    public function insert($item_id, $add_qty) {
        $item = (new item)->findOrFail($item_id);
        $qty = $item->quantity;
        //在庫なしバリデーション
        if ($qty <= 0) {
            return false;
        }
        $cart = $this->firstOrCreate(['user_id' => Auth::id(), 'item_id' => $item_id], ['quantity' => 0]);
        DB::beginTransaction();
        try {
            $cart->increment('quantity', $add_qty);
            $item->decrement('quantity', $add_qty);
            DB::commit();
            return true;
        } catch (Exception) {
            DB::rollback();
            return false;
        }
    }
    public function delete($cart_id) {
        $cart = $this->findOrCreate($cart_id);
        if ($cart->user_id == Auth::id()) {
            DB::beginTransaction();
            try {
                $item_id = $cart->item_id;
                $qty = $cart->quantity;
                $cart->delete();
                $item = (new Item)->find($item_id);
                $item->increment('quantity', $qty);
                DB::commit();
                return true;
           } catch (Exception $e) {
                DB::rollback();
           }
        }
        return false;
    }
    public function subtotal() {
        $result = $this->item->price * $this->quantity;
        return $result;
    }
}

解説

以下は等価
(new Item)->all();
Item::all();
//static呼出しも裏ではインスタンス発行する
softDelete設定
use Illuminate\Database\Eloquent\SoftDeletes;

class Cart extends Model
{
        use SoftDeletes;
//$this->delete(); がソフトデリート
リレーション
public function item() {
    return $this->belongsTo('App\Item', 'item_id');
}
//主:id <- 従:item_id ( 1 : 1 ) hasOneの逆
//例: $item_name = $this->item->name; 
クエリビルダーで抽出
    $carts = $this->where('user_id', $auth_id)->get();
}
//user_id == $auth_id だけ抽出してDBから読み込み
DB操作->検索->なかったら新規作成
$cart = $this->firstOrCreate(['user_id' => Auth::id(), 'item_id' => $item_id], ['quantity' => 0]);
//$cart->user_id == Auth::id() && $cart->item_id == $item_id
//なかったときのパラメータ 第1引数 + 第2引数
eloquant/インクリメント・デクリメント
$cart->increment('quantity', $add_qty);
$item->decrement('quantity', $add_qty);
//第2引数を増減
モデル内で計算
public function subtotal() {
    $result = $this->item->price * $this->quantity;
    return $result;
}
//コントローラーから使用

モデルの重要性

コントローラーの可読性はモデルの出来による。
わかりやすいモデルのメソッド名と機能の両立が大事。

LTGMよろしくお願いします!
励みになります!