1

Is there any sample/tutorial working with both Aura router and dispatcher? I found a sample code on the documentation page:

// dispatch the request to the route handler.
// (consider using https://github.com/auraphp/Aura.Dispatcher
// in place of the one callable below.)
$callable = $route->handler;
$response = $callable($request);

// emit the response
foreach ($response->getHeaders() as $name => $values) {
    foreach ($values as $value) {
        header(sprintf('%s: %s', $name, $value), false);
    }
}
http_response_code($response->getStatusCode());
echo $response->getBody();

and I wanna know how can I integrate the Aura dispatcher with this sample code.

The second question is when we want to retrieve a GET request using Aura router, we use something like this:

// add a route to the map, and a handler for it
$map->get('blog.read', '/blog/{id}', function ($request) {
    $id = (int) $request->getAttribute('id');
    $response = new Zend\Diactoros\Response();
    $response->getBody()->write("You asked for blog entry {$id}.");
    return $response;
});

How about the POST method? I tried the following code, but it cannot retrieve the firstname in a similar way:

$map->post('profile', '/profile', function ($request) {
    $firstname = $request->getAttribute('firstname');

    $response = new Zend\Diactoros\Response();
    $response->getBody()->write("first name is {$firstname}");
    return $response;
});

The output is missing the $firstname value:

first name is 
Belkin
  • 199
  • 15
  • 2
    Looks like instead of $request->getAttribute(), I should use $request->getParsedBody() for POST method. This way, I can have an associative array holding all POST methods. Is this the best way of retrieving POST variables in Aura router? – Belkin Dec 26 '19 at 06:05

1 Answers1

2

There are multiple ways you can use Aura.Dispatcher. The example provided below is one way.

$route = $matcher->match($request);

So once you match the request, there can be a route or null.

If there is a route, you can get the $route->handler;. This can be either a callable or string.

It is your implementation that tells how the Dispatcher can be invoked. From https://gist.github.com/harikt/8671136

    <?php
require dirname(__DIR__) . '/vendor/autoload.php';

use Aura\Dispatcher\Dispatcher;
use Aura\Router\RouterContainer;
use Zend\Diactoros\Response;
use Zend\Diactoros\ServerRequest;

class Blog
{   
    public function browse(ServerRequest $request)
    {
        $response = new Response();
        $response->getBody()->write("Browse all posts!");

        return $response;
    }

    public function read(ServerRequest $request, $id)
    {
        $id = (int) $request->getAttribute('id');
        $response = new Response();
        $response->getBody()->write("Read blog entry $id");

        return $response;
    }

    public function edit(ServerRequest $request, $id)
    {
        $response = new Response();
        $response->getBody()->write("Edit blog entry $id");

        return $response;
    }
}

$dispatcher = new Dispatcher;
$dispatcher->setObjectParam('controller');
$dispatcher->setMethodParam('action');
$dispatcher->setObject('blog', new Blog());

$routerContainer = new RouterContainer();
$map = $routerContainer->getMap();

// NB : You can use @ sign as in Laravel. So blog@browse
$map->get('blog.browse', '/blog', 'blog::browse');
$map->get('blog.read', '/blog/{id}', 'blog::read');

$request = Zend\Diactoros\ServerRequestFactory::fromGlobals(
    $_SERVER,
    $_GET,
    $_POST,
    $_COOKIE,
    $_FILES
);
$matcher = $routerContainer->getMatcher();
$route = $matcher->match($request);

if ($route) {
    foreach ($route->attributes as $key => $val) {
        $request = $request->withAttribute($key, $val);
    }
    // Take special attention, how I am using the handler.
    // Do what you want with the handler
    list($controller, $action) = explode('::', $route->handler);

    $params = [
        'controller' => $controller,
        'action' => $action,
        'request' => $request,
        // This is not needed, just showing for demo purpose
        'id' => $request->getAttribute('id'),
    ];

    $response = $dispatcher($params);

    // emit the response
    foreach ($response->getHeaders() as $name => $values) {
        foreach ($values as $value) {
            header(sprintf('%s: %s', $name, $value), false);
        }
    }
    http_response_code($response->getStatusCode());
    echo $response->getBody();
} else {
    echo "No route found";
}

I repeat this is not the only way. There are other better ways, read https://github.com/auraphp/Aura.Web_Kernel if you are really interested to learn more.

Regarding your question about getting value from POST. No there is no other way. The router is not handling the POST values. I think probably PSR-7 could have improved a bit in those areas :-) .

Hari K T
  • 4,174
  • 3
  • 32
  • 51
  • 1
    Thank you Hari. I think Aura dispatcher belongs to 2.x versions, am I right? If so, is it fine to combine it with Router version 3.x? – Belkin Dec 27 '19 at 07:26
  • 1
    Yes, it is totally fine. – Hari K T Dec 27 '19 at 11:13
  • 1
    One more thing. I saw you instantiated the Blog class by $dispatcher->setObject('blog', new Blog()); Is there a way to make this dynamic? I mean, if I have another controller to be used by a different path, it does not make sense to instantiate Blog for that path. Besides, the controller class is in another namespace (so it should be loaded by use statement). – Belkin Dec 27 '19 at 21:07
  • 1
    Yes, you can use a DI container. – Hari K T Dec 30 '19 at 06:04