驚喜!一個檔案多個【請求類】的另類寫法

zhaiduting發表於2020-01-11

《終於找到了 Laravel-admin 中使用【請求類】驗證表單的方法》一文中介紹過,通過覆寫larave-admin控制其中的store()和update()方法可以呼叫請求類驗證表單。程式碼如下

    public function update($id) {
        app(UserRequest::class);
        return $this->form()->update($id);
    }
    public function store() {
        app(UserRequest::class);
        return $this->form()->store();
    }

但是,建立使用者和修改使用者所需要的驗證規則並非完全一致(例如:新建使用者時必須設定密碼,但是修改使用者時密碼並不是必須的)。為此,我們可能需要使用兩個類來完成這個任務。類似於下面這樣的寫法

    public function update($id) {
        app(UserUpdateRequest::class);
        ...
    }
    public function store() {
        app(UserStoreRequest::class);
        ...
    }

根據一個類對應一個檔案的規則,以上寫法的缺點立即顯現:區區一個【使用者請求相關類】竟然要使用3個檔案(UserRequest.php、UserUpdateRequest.php和UserStoreRequest.php),殺雞用了牛刀的感覺。如果我們強行將這3個相關類寫在一個檔案裡行不行?不行,試一下就知道了。我百度過一些方法,實現方法並不是很優雅。

思索N久,我終於找到了相對優雅的做法,仍然可以將3個請求類強塞進一個檔案裡(無需配置 composer.json 無需使用 require 語句)。UserRequest.php程式碼如下

namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;

//以下是最初的 UserRequest 請求類
class UserRequest extends FormRequest
{
    ...
    public function rules() {...}

    public function update() {
        app(UserUpdateRequest::class);
    }
    public function store() {
        app(UserStoreRequest::class);
    }
}

//以下是新建使用者時用到的請求類
//必須繼承 UserRequest 決不能繼承 FormRequest
class UserStoreRequest extends UserRequest {
    public function rules() {
        return [
            'password'=> 'required|min:3',
        ];
    }
}

//以下是更新使用者時用到的請求類
//這個類暫時沒什麼特別的要求,留空備用
class UserUpdateRequest extends UserRequest { }

新增的兩個類(UserStoreRequest和UserUpdateRequest)對外界來說是不可見的!嘗試一下下面的寫法就會知道了,提示找不到類(並非絕對不可見,必要條件不滿足的情況下才是不可見的)

public function store() {
    //報錯:UserStoreRequest does not exist
    app('App\Http\Requests\UserStoreRequest');
    return $this->form()->store();
}

對外界不可見?那怎麼使用它們?簡單得很:在基類UserRequest中新增兩個訪問器就搞定了!

class UserRequest extends FormRequest
{
    ...
    public function update() {
        app(UserUpdateRequest::class);
    }
    public function store() {
        app(UserStoreRequest::class);
    }
}

如此一來,外界就可以通過UserRequest的兩個訪問器UserRequest::update()及UserRequest::store()分別訪問它們了。例如在laravel-admin中就可以這麼寫

public function update($id) {
    app(UserRequest::class)->update();
    return $this->form()->update($id);
}
public function store() {
    app(UserRequest::class)->store();
    return $this->form()->store();
}

效果如下
Laravel

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章