Masoniteで登録フォーム（Laravelとの比較）

今回Masoniteで、よくありそうな登録フォームを作成してみました。
Laravelと比較しながら少しだけ見ていきたいと思います。
※controllerとviewだけ。

今回はアイテム(item)を登録・編集するイメージのものになります。
また、登録も編集も同一のviewを使用するようにしています。

[Laravel Documentation](https://laravel.com/docs/9.x)
[Laravel ReaDouble](https://readouble.com/laravel/9.x/ja/)
[Masonite Documentation](https://docs.masoniteproject.com/)

# Controller
### Laravel
```php:app/Http/Controllers/ItemController.php
use App\Http\Controllers\Controller;
use App\Http\Requests\ItemRequest;
use App\Models\Item;

class ItemController extends Controller
    public function create()
    {
        return view('item.create');
    }

    public function store(ItemRequest $request)
    {
        $item = new Item();
        $item->fill($request->all())->save();

        return redirect()->route('item.index');
    }

    public function edit(int $item_id)
    {
        return view('item.create', [
            'item' => Item::findOrFail($item_id)
        ]);
    }

    public function update(int $item_id, ItemRequest $request)
    {
        $item = Item::findOrFail($item_id);
        $item->fill($request->all())->save();

        return redirect()->route('item.show', $item_id);
    }
```

### Masonite
```python:app/controllers/ItemController.py
from app.models.Item import Item
from app.validation.ItemValidation import ItemValidation
from masonite.controllers import Controller
from masonite.views import View
from masonite.request import Request
from masonite.response import Response


class ItemController(Controller):
    def create(self, view: View):
        return view.render("item.create")

    def store(self, request: Request, response: Response):
        errors = request.validate(ItemValidation)

        if errors:
            return response.redirect('', 'item.create') \
                .with_errors(errors).with_input()

        Item.create(request.all())

        return response.redirect('', 'item.index')

    def edit(self, view: View, request: Request):
        return view.render("item.create", {
            "item": Item.find_or_404(request.param("id"))
        })

    def update(self, view: View, request: Request, response: Response):
        item_id = request.param("id")

        errors = request.validate(UserValidation)

        if errors:
            return response.redirect('', 'item.edit', [item_id]) \
                .with_errors(errors).with_input()

        item = User.find_or_404(item_id)
        item.fill(request.all()).save()

        return response.redirect('', 'item.show', {
            'id', item.id
        })
```

### 見た感じ
Laravelはcontroller内で、登録ぐらいですが、Masonite側はvalidationのチェックとリダイレクト処理もあります。

しかもリダイレクトは```response.back().with_errors(errors)```とドキュメントにはありますが、前の画面に戻ってしまいます。
どうやったらフォームの画面に戻るか不明だったので、普通？にリダイレクトしています。

また、```redirect```ですが、第２引数がnameになるようで、ちょっと辛い書き方になっています。
※何かいい書き方があるとは思うのですが…

# View
### Laravel
```php:resources/views/item/create.blade.php
@extends('layouts.app')

@section('content')
@if ($item)
  <form method="POST" action="{{ route('item.update', $item->id) }}">
    @method('PUT')
@else
  <form method="POST" action="{{ route('item.store') }}">
@endif
  @csrf

  <div>
    <label for="name">名前</label>
    <input type="text" name="name" value="{{ old('name', item->name ?? '') }}" />
  </div>

  <button type="submit">登録</button>
</form>
@endsection
```

### Masonite
```python:templates/item/create.html
@extends 'base.html'

@block content
<main>
  @if item
    <form method="POST" action="{{ route('item.update', [item.id]) }}">
      {{ method('PUT') }}
  @else
    <form method="POST" action="{{ route('item.store') }}">
  @endif
    {{ csrf_field }}

    <div>
      <label for="name">名前</label>
      @if session().has('name')
        <input type="text" name="name" value="{{ session().get('name') }}" />
      @elif item
        <input type="text" name="name" value="{{ item.name }}" />
      @else
        <input type="text" name="name" />
      @endif
    </div>

    <button type="submit">登録</button>
  </form>
</main>
@endblock

```

### 見た感じ
両方ともですが、登録と編集を同じファイルで実現する為に```method```を条件分けで作っているのですが、もっと素敵な書き方ないだろうかと思ってしまう。

Masonite側でいうと、Laravelの様に```old()```が見当たらないので、頑張ってしまっています。
htmlの属性エリア？に```@if```も書けなさそう。
pythonの書き方とかでもう少し綺麗になる部分があるようには思えます。

# 感想
Laravelの方がいい感じなんだろうなぁと最初から思っていましたが、その通りな雰囲気でした。
また、普段あまりPythonを使用しないのもあってか、Masoniteは苦戦しました。

なんだかMasoniteをいじっていると、初めてLaravelをいじった時の事をちょっぴり思い出して、辛い涙が出そうでした。