Vijay
Vijay

Reputation: 41

Using Request, Response in constructor in router class Slim Framework 3

I am using Slim Framework for my application. I am using routes. All is working fine. But now I want to do some pre-process working under my constructor on Request and Response.

So that I should not rework on every function of the class. Like getting host and token in every function. I am using middle-ware for many pre-process. But I also want to do some work in class constructor. When I am trying to access request and response interface in constructor, It is showing the error, Please show me the right way of using Request and Response in a class constructor. Will I have to append $app, or will need to work with container.

If it can be done without help of middleware, It will be great for me.

use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;    
$app->group('/products', function() {
    new \Products($this);
});

And I have a class called Products.

class Products
{
    public function __construct($app)
    {
        $app->map(['GET','POST'], '/createupdate', array($this, 'createupdate'));    
        //I want to use Request and Response here in constructor. But it is showing error. 
        $this->req_data['request_token'] = $request->getAttribute('request_token');
    }
    public function createupdate($request, $response, $args) {      
    //This is working fine.
    $this->req_data['request_token'] = $request->getAttribute('request_token');
    }
}

Upvotes: 0

Views: 1796

Answers (2)

Ron Dadon
Ron Dadon

Reputation: 2706

Ofcourse you will get an error, $request is not defined.

public function __construct($app)
{
    $app->map(['GET','POST'], '/createupdate', array($this, 'createupdate'));    
    // Where does $request comes from?!
    $this->req_data['request_token'] = $request->getAttribute('request_token');
}

Slim way of doing pre-processing is by using middlewares.

When a route is called, it is automatically injected with the Request and Response objects (and the request route params if any), but when a class is created for the route, it is not automatically injects those instances to the constructor, so they are not available "out of the blue".

If you have pre-processing, I would stick to middlewares, it is much cleaner code (although this is my opinion).

Upvotes: 0

jmattheis
jmattheis

Reputation: 11115

When you really want to do this, then you could get the request/response object from the container.

class Products
{
    public function __construct($app)
    {
        $app->map(['GET','POST'], '/createupdate', array($this, 'createupdate'));

        $request = $app->getContainer()->get('request');
        $this->req_data['request_token'] = $request->getAttribute('request_token');     
    }
// [..]
}

But, also this will not make much difference $this->req_data['request_token'] is nearly as long as $request->getAttribute('request_token'); so you should use this inside the code.

Note: I expect you to set this attribute already inside middleware, so it may not be available here, because first the container will create a new request object and second cause the middleware is not run when php executes your constructor code.

When you now still want to use $this->req_data['request_token'] inside your class then you should do this:

$products = new \Products();

$app->group('/products', function() use ($products) {
    $products->addRoutes($this);
})->add($products); // add the class as middleware as well to set there the class attributes (__invoke function)

class Products
{
    public function addRoutes($app)
    {
        $app->map(['GET','POST'], '/createupdate', array($this, 'createupdate'));
    }

    public function __invoke($request, $response, $next) // this is middleware function
    {
        $this->req_data['request_token'] = $request->getAttribute('request_token');

        return $next($request, $response); // next in this example would be your route function like createupdate()
    }
}

Upvotes: 0

Related Questions