How to make request type dynamic (validation) in Laravel 5.1

I am trying to create a crud controller base from where I extend it and set the base model then I have some basic crud methods. I work dynamically. But I cannot create a dynamic request type to check it, I have a ChannelRequest, its working fine, but I want it to be dynamic:

this is my CrudController class (which I will extend and set the model):

    public function store(ChannelRequest $request)
    {
        $this->save($request); // this method get the model instantiated in parent class and save the inputs

        return redirect('admin/' . $this->plural);
    }

      

in this example above I have hardcoded the request type on dependency injection, then it checks, but I want to dynamically change the request type like:

    // i know it not being work
    public function store($this->model .'Request' $request)
    {
        $this->save($request);

        return redirect('admin/' . $this->plural);
    }

      

I've tried this:

    public function store()
    {
        $request = new ChannelRequest();
        $request->validate(); //hopping it runs like when dependency injection

        $this->save($request);

        return redirect('admin/' . $this->plural);
    }

      

this results in an error:

FatalErrorException in FormRequest.php line 75:
Call to a member function make() on null
in FormRequest.php line 75
at FatalErrorException->__construct() in HandleExceptions.php line 133
at HandleExceptions->fatalExceptionFromError() in HandleExceptions.php line 118
at HandleExceptions->handleShutdown() in HandleExceptions.php line 0
at FormRequest->getValidatorInstance() in ValidatesWhenResolvedTrait.php line 20
at FormRequest->validate() in CrudController.php line 67

      

+3


source to share


1 answer


First of all, I want to emphasize that having separate controllers for each resource (model) is good practice and prevents overly mixed problems. Using the dynamic Request class defeats the purpose of explicitly defining the request class in the first place.

However, in the interest of answering the question, I can best give you an idea of ​​how to solve this. This code is untested, but the concept should be robust.

What I've done here is extending the standard Request class with the SmartRequest class and overriding __construct

to allow me to run a preloader on the appropriate request class for a given request type.

This will allow you to define individual request classes and then load them into a property SmartRequest::$subRequest

based on the request parameter resourceType

(this can be part of the POST, GET, or URL parameters if you want to change the code for the latter).

Code: App\Http\Requests\SmartRequest



<?php 

use App\Http\Requests\Request;

class SmartRequest extends Request {

    /**
     * Holds sub request class
     * @var Request
     */
    protected $subRequest;

    /**
     * Default constructor
     * @param array             $query      
     * @param array             $request    
     * @param array             $attributes 
     * @param array             $cookies    
     * @param array             $files      
     * @param array             $server     
     * @param string|resource   $content    
     */
    public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
    {
        // make sure standard constructor fires
        parent::__construct($query, $request, $attributes, $cookies, $files, $server, $content);

        // instantiate the sub request object, we must also pass through all the data for the base
        // request since the sub class requires this data.
        $this->loadSubRequest($query, $request, $attributes, $cookies, $files, $server, $content);
    }

    /**
     * Default constructor
     * @param array             $query      
     * @param array             $request    
     * @param array             $attributes 
     * @param array             $cookies    
     * @param array             $files      
     * @param array             $server     
     * @param string|resource   $content    
     */
    public function loadSubRequest($query, $request, $attributes, $cookies, $files, $server, $content)
    {   
        // get resource type off the request data to generate the class string
        $class = $this->getRequestClassName();

        $this->subRequest = new $class($query, $request, $attributes, $cookies, $files, $server, $content);
    }

    /**
     * Get the sub class name with namespace
     * @return string
     */
    public function getRequestClass()
    {
        return '\<path>\<to\<namespace>\\' . studly_case($this->resourceType) . 'Request';
    }

    /**
     * Returns rules based on subclass, otherwise returns default rules
     * @return array
     */
    public function rules()
    {
        // return the default rules if we have no sub class
        if (empty($this->subRequest)) return [];

        // return the rules given by the sub class
        return $this->subRequest()->rules();
    }
}

      

Again, this is not real code (since I haven't tested it), but it might be a way to fulfill your request. It also depends on having some identifier sent on request (in this case, a parameter requestType

), since you don't know anything about the other's request, then where it was sent to and with what parameters.

However, I think this is completely against the intent of this functionality. It is much better to have explicit requests and use them explicitly in the methods that require them. What for? Self-documenting code. People will know what you are using just by reading things like ChannelRequest $request

in action. If something like above ( SmartRequest

) will result in some kind of magic that any other developer won't understand until the class breaks SmartRequest

.

Let me know if this was unclear, or if you have any other questions about why I believe this approach is a step in the wrong direction.

+3


source







All Articles