Sorry if this question has been asked several times before and this is simply not possible in Laravel/PHP.
In my Laravel application, I have a PostController
that uses Laravel's rich naming convention. I also have a CommentController
that mostly copies PostController
in various ways, so I decided CommentController
should extend PostController代码>.
The only difference so far is that the store()
method needs to accept a different FormRequest
object since they have different validation rules. Therefore, I overridden the store()
method to expect CommentFormRequest
instead of PostFormRequest
(both extend FormRequest
) .
This will raise an error that the overridden method parameters need to match the base method.
Is this expected? Is there a reasonable solution for what I want to do?
Edit from here
I just started designing this project where users can create posts, questions, polls, ads, etc. and comment on any of them.
All of these are Post
types. Some have relationships with other models, for example Poll
may have a relationship with the PredefinedAnswer
model, while the generic Post
may have no relationship.
Some may require different validation logic, for example a user may decide whether to allow comments on a generic Post
, but may never allow comments on an Advert
.
In my database, I think these could all be stored in the post
table, but with different postable_type
.
In my controller, I think most of the CRUD logic is the same between these different types. In some cases, differences may exist and methods may need to be overridden.
So, in my PostController
I currently have a very simple store()
method:
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'); } }
Let's say my AdvertController
has the same logic but different validation rules I think:
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'); }
Instead of implying the specific implementation, you will get more benefits by implying the interface, for example:
This way you:
can be called in situations where some special handling is required, such as type/sanity checks, but the rest of the method remains the same.
ControllerInterface
,
RedirectInterface, etc.] and further simplify your code.