首頁  >  問答  >  主體

使用不同參數的 Laravel PHP 重寫方法

如果之前已經多次詢問過這個問題,而這在 Laravel/PHP 中根本不可行,那麼我們深表歉意。

在我的 Laravel 應用程式中,我有一個 PostController,它使用 Laravel 豐富的命名約定。我還有一個 CommentController,它主要以各種方式複製 PostController,因此我決定 CommentController 應該擴展 PostController.

到目前為止唯一的區別是 store() 方法需要接受不同的 FormRequest 對象,因為它們有不同的驗證規則。因此,我重寫了store() 方法以期望CommentFormRequest 而不是PostFormRequest (兩者都擴展了FormRequest) .

這會引發一個錯誤,即重寫方法參數需要與基本方法相符。

這是預期的嗎?對於我想做的事情有一個合理的解決方案嗎?

從此處編輯

#我剛開始設計這個項目,用戶可以在其中建立貼文、問題、投票、廣告等,並且可以對其中任何內容發表評論。

所有這些都是Post類型。有些與其他模型有關係,例如Poll 可能與 PredefinedAnswer 模型有關係,而通用 Post 可能沒有關係。

有些可能需要不同的驗證邏輯,例如使用者可以決定是否允許對通用 Post 發表評論,但可能永遠不允許對 Advert 發表評論。

在我的資料庫中,我認為這些都可以儲存在 post 表中,但具有不同的 postable_type

在我的控制器中,我認為這些不同類型之間的大多數 CRUD 邏輯是相同的。在某些情況下,可能存在差異,可能需要重寫方法。

因此,在我的 PostController 中,我目前有一個非常簡單的 store() 方法:

class PostController extends Controller
{

    protected $postableType;


    public function __construct()
    {
        $this->postableType = PostType::GENERIC;
    }

    public function store(PostStoreRequest $request): RedirectResponse
    {
        $validated = $request->validated();

        $post = new Post();
        $post->message = $validated['message'];
        $post->user_id = $request->user()->id;

        $post->postable_type = $this->postableType;

        $post->save();

        return Redirect::route('feed');
    }
}

假設我的 AdvertController 有相同的邏輯,但有我所想的不同的驗證規則:

class AdvertController extends PostController
{

    protected $postableType;

    public function __construct()
    {
        $this->postableType = PostType::ADVERT;
    }

    public function store(AdvertStoreRequest $request): RedirectResponse
    {
        $validated = $request->validated();

        $advert= new Advert();
        $advert->message = $validated['message'];
        $advert->user_id = $request->user()->id;

        $advert->postable_type = $this->postableType;
        $advert->save();

        return Redirect::route('feed');
    }

P粉863295057P粉863295057300 天前450

全部回覆(1)我來回復

  • P粉807471604

    P粉8074716042024-01-17 16:43:49

    與其暗示具體的實現,不如暗示介面,你會得到更多的收益,例如:

    interface StoreRequestInterface {
      public function validated(): RedirectResponse;
      public function user();
      // etc
    }
    
    class PostStoreRequest implements StoreRequestInterface {/* ... */}
    class AdvertStoreRequest  implements StoreRequestInterface {/* ... */}
    
    abstract class Controller {
        protected $postableType;
    
        public function store(StoreRequestInterface $request): RedirectResponse
        {
            // ...
        }
    }
    
    class PostController extends Controller
    {
        public function __construct()
        {
            $this->postableType = PostType::GENERIC;
        }
    }
    
    class AdvertController extends PostController
    {
        public function __construct()
        {
            $this->postableType = PostType::ADVERT;
        }
    }
    

    這樣你:

    • 不必使用略有不同的參數提示來重新定義相同的方法體。
    • 在需要一些特殊處理的情況下可以呼叫 parent::store($request),例如:類型/健全性檢查,但該方法的其餘部分仍然相同。
    • 可以避免定義「上帝」類別的陷阱,大量應用程式類別必須追蹤其血統。您可以透過簡單地實現預期的介面來定義獨立的直接替換。

    您可以進一步連接此處引用的其他類別[例如:ControllerInterfaceRedirectInterface等],並進一步簡化您的程式碼。

    回覆
    0
  • 取消回覆