1

I've been assigned to a project which needs include the Symfony components in order to re-organize its business logic. However, I got confused by looking at the Symfony HTTP-foundation document. Hope someone here could help me explain a bit how this component deals with users Http requests and responses.

Basically, what I did in the project was:

  1. having a PHP page creates the Request object with requests' URL and method

  2. Using an ApiRouter to direct the code to the desired controller

  3. Within the controller, it will send the HTTP request to the server and convert responses as a Symfony Response object base on the Request URL.

location.php

class GetLocation
{
public function __construct($q)
   {
    $request = Request::create('location?v=full&q=' . 
    urlencode($q), 'GET'); //simulates a request using the url
    $rest_api = new RestApi();  //passing the request to api router
    $rest_api->apiRouter($request);
    }
}

ApiRouter.php

    //location router
       $location_route = new Route(
            '/location',
            ['controller' => 'LocationController']
        );
       $api_routes->add('location_route', $location_route);

    //Init RequestContext object
    $context = new RequestContext();
    //generate the context from user passed $request
    $context->fromRequest($request);

    // Init UrlMatcher object matches the url path with router
    // Find the current route and returns an array of attributes
    $matcher = new UrlMatcher($api_routes, $context);
    try {
        $parameters = $matcher->match($request->getPathInfo());
        extract($parameters, EXTR_SKIP);
        ob_start();

        $response = new Response(ob_get_clean());
    } catch (ResourceNotFoundException $exception) {
        $response = new Response('Not Found', 404);
    } catch (Exception $exception) {
        $response = new Response('An error occurred', 500);
    }

What I hope to know is whether my understanding is correct regards to the logic or not? And what does the method Request:createFromGlobal means, what are the differences between this and Request:create(URL)

Please do let me know if my question needs to be more specific.

Stephan Vierkant
  • 9,674
  • 8
  • 61
  • 97
Hazel Wang
  • 111
  • 1
  • 10

1 Answers1

1

First the easier of your questions:

Request::createFromGlobals() will create a request basedon some PHP global variables, e.g. $_SERVER, $_GET and $_POST, meaning it will create a request from the current request we are "in", i.e. the user request that triggered our application. Request::create() on the other hand will build a "new" request without this context being applied, meaning you have to pass certain info, like the path and HTTP-method yourself.

Now regarding your code and whether it will work. Short answer is, probably not. In GetLocation you create both a new request and a new router and inside the controller you create a route, that will then be added to the router. Meaning unless the controller code is executed before GetLocation, the route will not be available in the router, meaning the controller is never called.

You might want to look into the series: Create your own PHP Framework inside the symfony docs, especially the parts from The HttpFoundation Component onwards. Hopefully this will clear things up for you.

dbrumann
  • 16,803
  • 2
  • 42
  • 58
  • @dbrunmann Thank you indeed for the answer, but it appears that I have mistyped my router name as ApiController in my previous post. For the updated code, within my router, each path is mapped with a controller, and defines the router in this way, would it be directed to the desired controller, or do I have to add some code in order to call the controller class? – Hazel Wang Jun 10 '19 at 21:01
  • I still don't have a full picture, but there might still be a few things wrong. The controller assigned in the route must be a callable (if the controller implements `__invoke` you should be fine). The bigger issue is, that from what I see you never execute the controller. Instead of `ob_start() and then new Response(ob_flush())`, I would expect you call the controller returned by the matcher, which then returns a response. You could check [HttpKernel::handleRaw()](https://github.com/symfony/symfony/blob/4.4/src/Symfony/Component/HttpKernel/HttpKernel.php#L134-L151) for reference – dbrumann Jun 10 '19 at 21:19
  • I am sure you are correct. Ignoring the question above, may I please know if the Routing component in Symfony able to hide the PHP extension in URL? – Hazel Wang Jun 13 '19 at 13:27
  • Short answer: yes. All your requests go through a webserver, e.g. apache or nginx, if that webserver routes these requests internally to your front controller (`public/index.php` or in older projects `public/app.php` or `web/app.php`) then your Symfony application will be able to get the originally requested path (i.e. the browser url), no matter if it was `/foo` or `/foo.php`. Then the router will read this path and match it with a route. Similarly, if you use the UrlGenerator it will take the name of a route and then create a URL/path that matches it, with or without any extension. – dbrumann Jun 13 '19 at 13:56
  • See: https://symfony.com/doc/current/setup/web_server_configuration.html#adding-rewrite-rules for making sure your webserver routes the requests to your application, instead of actually looking for a file/folder when typing `http://example.com/foo`. – dbrumann Jun 13 '19 at 13:56