class AdminBaseController extends Controller {
public function store(FormRequest $request)
{
// Your code here
}
}
[L5]how to use Form Validation Request Injection in a subclass
I have a base controller, which like below:
class AdminBaseController extends Controller {
public function store(Request $request)
{
.........
}
}
Then i have a subclass which extend above class and override the store function like below:
class AdminBlogsController extends AdminBaseController {
public function store(StoreBlogPostRequest $request)
{
........
}
}
The function parameter StoreBlogPostRequest is a Form Validation Request class which I used to validate the post form.
but now I got the error lilke ErrorException in AdminBlogsController.php line 12: Declaration of App\Http\Controllers\Admin\AdminBlogsController::store() should be compatible with App\Http\Controllers\Admin\AdminBaseController::store(Illuminate\Http\Request $request)
so i guess the error is because two method have different type of parameter? how to fix that.
Thanks
I tried to change "Request" to "FormRequest " , but still same error.
Declaration of App\Http\Controllers\Admin\AdminBlogsController::store() should be compatible with App\Http\Controllers\Admin\AdminBaseController::store(Illuminate\Foundation\Http\FormRequest $request)
can you show us the content of this class "StoreBlogPostRequest"
<?php namespace App\Http\Requests;
class StoreBlogPostRequest extends Request {
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'title' => 'required',
'body' => 'required',
'thumb'=> 'required',
'published_at'=>'required|date'
];
}
}
i used below command to generate this class.
php artisan make:request StoreBlogPostRequst
Hi, the error told you:
App\Http\Controllers\Admin\AdminBlogsController::store()
Review your AdminBlogsController store method because seems to be that your AdminBlogsController hadn't any parameter when the error was sent.
Hey, I have just view that you extend from AdminBaseSimpleController not AdminBaseController.
Review it.
AdminBlogsController is looks like below:
class AdminBlogsController extends AdminBaseController {
public function store(StoreBlogPostRequest $request)
{
//some code here.
}
}
Try like this :
class AdminBaseController extends Controller {
public function store(FormRequest $request)
{
//
}
}
class AdminBlogsController extends AdminBaseController {
public function store(StoreBlogPostRequest $request)
{
//
}
}
You probably wrote the class name wrong, as @codeatbusiness mentioned.
@RachidLaasri , my code is exactly same as yours. but still got the error.
Declaration of App\Http\Controllers\Admin\AdminBlogsController::store() should be compatible with App\Http\Controllers\Admin\AdminBaseController::store(Illuminate\Foundation\Http\FormRequest $request)
and i have checked the code many time, the class name is correct, it is
class AdminBlogsController extends AdminBaseController {
public function store(StoreBlogPostRequest $request)
{
//
}
}
Hi @lcf8381595 did you use any namespace within your project and imported the AdminBaseController within your AdminBlogsController? You also need to import or use a backslash with your request and request subclass.
@codeatbusiness i am using default APP as the namespace, AdminBaseController and AdminBlogsController are in same folder have same namespace, so do not need imported AdminBaseController to AdminBlogsController.
How did you take the Request and StoreBlogPostRequest? Wich their namespaces are?
StoreBlogPostRequest class
<?php namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreBlogPostRequest extends FormRequest {
//
}
AdminBaseController class
<?php namespace App\Http\Controllers\Admin;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Request;
use Laracasts\Flash\Flash;
use Illuminate\Support\Facades\Redirect;
class AdminBaseController extends Controller {
public function store(FormRequest $request)
{
//
}
}
AdminBlogsController class
<?php namespace App\Http\Controllers\Admin;
use App\Blog;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreBlogPostRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Str;
use Laracasts\Flash\Flash;
class AdminBlogsController extends AdminBaseController {
public function store(StoreBlogPostRequest $request)
{
//
}
}
Does it work with :
class AdminBlogsController extends AdminBaseController {
public function store(StoreBlogPostRequest $request = null)
{
//
}
}
@bestmomo $request = null not work..
any one can help?
Why do you need to have a store method in the AdminBaseController?
@lcf8381595 Unsure what you are trying to do, but I think your problem is you attempting to extend a normal class i.e. AdminBaseController. Controller is abstract class you can extend that, if you want to extend AdminBaseController change it to abstract or just extend Controller.
@nolros Thanks. let me explain what I am trying to do. AdminBaseController extend Controller, which have store method. some any class like AdminBlogController or AdminPostController extend AdminBaseController, so they all have their parent 's store method by default, so these subclass do not need write same store code in each of them.
But for one of the subclass like AdminPostController i do no want use the parent class AdminBaseController 's store method, i want override this method in this subclass. so i redefined the store() method in this subclass. and then cause the error..
I am sure then error means that store() method is sub class and parent class do not have same type of parameter. i am just not sure how to fix that. the parent class store method have one parameter which is Illuminate\Http\Request $request, and the subclass store method have one parameter which is App\Http\Requests\StoreBlogPostRequest ( used make:request to generate this class for validate the form post before store )
Thanks.
Have you tried this setup
// abstract classs
abstract AdminBaseController extend Controller
public function store( StoreBlogPostRequest )
{
// code set 1
}
class AdminBlogController extends AdminBaseController
public function store ( StoreBlogPostRequest )
{
// code overwrite code
}
class AdminPostController extends AdminBaseController
// no store method as it will inherit from AdminBaseController
Hi, this is due to the strict error reporting being enforced by laravel. So, apparently this is not possible. As a hack you can comment this line to make it work.
More info is here: http://stackoverflow.com/questions/3115388/declaration-of-methods-should-be-compatible-with-parent-methods-in-php
Regards :)
@nolros For AdminBaseController class store() method, i can not use StoreBlogPostRequest as the parameter, because all subclass will have different Validate Class. for example
AdminBlogController will have method store ( StoreBlogPostRequest ) AdminMovieController will have method store( StoreMoviePostRequest )
@lcf8381595 i think you are attempting inheritance but not really using it so I would suggest you use the same StoreBlogPostRequest request and build conditional logic logic inside the validation to filter. If that is not an option you could use route filters to direct to the right method and keep them separate. You can also build custom validators and store them in a ServiceProvider or your route file. I personally would not attempt what you are attempting as it flies in the face of inheritance but if you really want it to work you could attempt usman's suggestion.
You could just use a trait for classes that share a store method.
This can't be done ( http://stackoverflow.com/questions/19448742/override-interface-parent-method-that-use-type-hinting )
Child classes methods have to have exactly the same signatures. You have to change your structure.
I've already done this by injecting a FormRequestInterface to the method and binding it to the correct form request implementation according to the url / route.
class AdminBaseController extends Controller {
public function store(FormRequestInterface $request)
{
.........
}
}
class AdminBlogsController extends AdminBaseController {
public function store(FormRequestInterface $request)
{
........
}
}
class AppServiceProvider{
public register(Request $request, Route $route)
{
$route_name = $route->getCurrentRouteName() // Not sure of the syntax, don't remember
if($route_name == 'admin.index') $this->app->bind('App\Http\Requests\FormRequestInterface', function() use($request)
{
return $request;
});
if($route_name == 'admin.blogs.index') $this->app->bind(
'App\Http\Requests\FormRequestInterface',
'App\Http\Requests\StoreBlogPostRequest'
);
}
}
I went to the same issue.
Isn't it possible to make such a thing ?
class AdminBaseController extends Controller {
protected $request;
public function __construct()
{
\App::when( get_class() )
->needs('Requests\FormRequestInterface')
->give($this->request);
}
public function store(Requests\FormRequestInterface $request)
{
.........
}
}
class AdminBlogsController extends AdminBaseController {
protected $request = 'Requests\StoreBlogPostRequest';
}
It cant work like this. The method signature must be the same, here there is FormRequest in the parent class and StoreBlogpostRequest on the child class.
Create an interface for your form request. For example AdminFormRequestInterface. So the signature can be the same for all the admin controllers.
Then, in your AppServiceProvider, you have to detect when the request is for a blog (it can be determined from the request url for example). Then, if the request id for a blog, you can bind the AdminFormRequestInterface to StoreBlogPostRequest, so it is the one which will be injected. You may also use contextual binding to achieve this. The point is, use AppServiceProvider to bind the interface to its correct implementation someway and it is done.
By the way, I don't see the point of extending a parent controller.
Edit i didn't notice I've already answered this above ^^
Really, what is the point of extending a controller ?
Ok, merci @pmall !
When you have to make a CRUD for a lot of Model, extending a controller is really useful because you don't have to re-invent the wheel for every model. You only need to re-use the common resource base controller which already implement the controller's methods, kind of Don't Repeat Yourself if you will. I'd be glad to use the auto-magical Requests but I'll keeps my old Validators instead ;)
When you have to make a CRUD for a lot of Model, extending a controller is really useful because you don't have to re-invent the wheel for every model.
Yes but with model / request injection you don't even need to have many controllers, only one is enough.
Please or to participate in this conversation.