0
votes

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.

3
You need to get in the habit of accepting answers which help you to solve your issues. You'll earn points and others will be encouraged to help you. - Jay Blanchard
BTW - don't be rude to others here just as you were in the question you deleted unless you want to earn a trip to banned camp. - Jay Blanchard
"if you what just to spam in comments just f*ck off pls" - I really didn't deserve that, you were totally out of line there man. This from your now deleted post. You can put those words in the outhouse. You think that "pls" makes it "being polite"? wow. - Funk Forty Niner
and stop soaking everyone and be a good member of the community. You come here to get your petty problems fixed and leave; rich. - Funk Forty Niner

3 Answers

5
votes

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.

0
votes

My solution for are next:

  1. change a little my routes.yml parameters: no class name contain only slash
  2. use call_user_func_array($this->controller, $this->parameters)
0
votes

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();

`