Reputation: 495
I'm writing my own project and want to use some of Symfony components. I'm implementing Sf Router to my project and I don't understand how to call controller in router.
For ex I have a class:
<?php
namespace App;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Routing\Loader\YamlFileLoader;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\HttpFoundation as Http;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
class AppRouter
{
public function match() {
$context = new RequestContext();
$request = Http\Request::createFromGlobals();
$context->fromRequest($request);
$matcher = new UrlMatcher($this->getRoutes(), $context);
return $matcher->matchRequest($request);
}
private function getRoutes() {
$fileLocator = new FileLocator([__DIR__ . '/../config']);
$loader = new YamlFileLoader($fileLocator);
$routes = $loader->load('routes.yml');
return $routes;
}
}
and I have some defined routes in my routes.yml
so if I trying to go to registred route match()
method returns to me an array like below:
[
"_controller" => "Controller\\MyController::testAction"
"_route" => "test"
]
So, how now can I call the controller for matched URL? I'm read a documentation but can't understand how should I do this.
Upvotes: 0
Views: 3468
Reputation: 1010
The HTTP Kernel handles the Route to Controller invokation. You can find the full documentation here
The Controller Resolver and argument resolver will help you to match pretty easily a route to a controller method. This is the easy and robust way in order to get the router up and running on a legacy project without having to invoke the fully-fledge framework.
Think about it once more: our framework is more robust and more flexible than ever and it still has less than 50 lines of code.
require_once __DIR__.'/../vendor/autoload.php';
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing;
use Symfony\Component\HttpKernel;
function render_template(Request $request)
{
extract($request->attributes->all(), EXTR_SKIP);
ob_start();
include sprintf(__DIR__.'/../src/pages/%s.php', $_route);
return new Response(ob_get_clean());
}
$request = Request::createFromGlobals();
$routes = include __DIR__.'/../src/app.php';
$context = new Routing\RequestContext();
$context->fromRequest($request);
$matcher = new Routing\Matcher\UrlMatcher($routes, $context);
$controllerResolver = new HttpKernel\Controller\ControllerResolver();
$argumentResolver = new HttpKernel\Controller\ArgumentResolver();
try {
$request->attributes->add($matcher->match($request->getPathInfo()));
$controller = $controllerResolver->getController($request);
$arguments = $argumentResolver->getArguments($request, $controller);
$response = call_user_func_array($controller, $arguments);
} catch (Routing\Exception\ResourceNotFoundException $exception) {
$response = new Response('Not Found', 404);
} catch (Exception $exception) {
$response = new Response('An error occurred', 500);
}
$response->send();
`
Upvotes: 1
Reputation: 495
My solution for are next:
call_user_func_array($this->controller, $this->parameters)
Upvotes: 0
Reputation: 48865
This is a much more involved question then it might look.
The easiest approach is to simply explode the _controller string, new the controller and call the action.
// Untested but I think the syntax is correct
$matched = $router->match();
$parts = explode(':',$matched['_controller']);
$controller = new $parts[0]();
$controller->$parts[2]();
Of course there is a great deal of error checking to be added.
The reason I say it can be more complicated is that there is actually a lot you more you can do. Take a look at the HTTP Component. HttpKernel::handle($request) which uses a ControllerResolver class to create a controller as well as an ArgumentResolver to handle many of the controller's arguments. Fun stuff.
Create Your Own Framework is an excellent resource.
And the fairly new Symfony Flex approach gives you a bare bones framework which is worth studying as well.
Upvotes: 5