J7mbo / Aurex

Aurex is a merge between the Silex micro-framework and the awesome Auryn dependency injector.
MIT License
38 stars 2 forks source link

Twig function asset() not working #3

Closed raphaelcazorla closed 9 years ago

raphaelcazorla commented 9 years ago

Hi,

Whenever I try to call the asset() function in my twig files, I get this error:

Twig_Error_Runtime in Template.php line 158:
An exception has been thrown during the rendering of a template ("Identifier "request" is not defined.") in "layout.html.twig" at line 14.

I just pointed out that variable "$aurex" is empty in Aurex/lib/Framework/Module/Modules/TwigModule/TwigModule.php line 45

$twig->addFunction(new \Twig_SimpleFunction('asset', function ($asset) use ($aurex) {
    /** @var Request $request */
    var_dump($aurex);  //==> returns nothing!
    $request = $aurex['request'];
    return sprintf('%s/assets/%s', $request->getBasePath(), ltrim($asset, '/'));
}));

but is still available line 42, just before the addFunction() call :

$aurex['twig'] = $aurex->extend('twig', function($twig, $aurex) {
    /** @var \Twig_Environment $twig */
    var_dump($aurex);  //==> returns something !
    $twig->addFunction(new \Twig_SimpleFunction('asset', function ($asset) use ($aurex) {
        /** @var Request $request */
        $request = $aurex['request'];
        return sprintf('%s/assets/%s', $request->getBasePath(), ltrim($asset, '/'));
    }));
    return $twig;
});

I think there is a problem there...or am I missing something?

Also, I got no access to "app" in twig templates?!

Thank you for your help. Good job by the way ;)

raphaelcazorla commented 9 years ago

In addition, I think there is something strange, maybe due to my installation but, here it is: Whenever I try to use Silex specific variable like request, session, etc., I got NULL values everywhere.

Like in Aurex/lib/Framework/Installation/Application/Controller/HomeController.php, I tried this:

/**
     * @param AuthenticationUtils $utils
     * @param LoginFormType       $type
     *
     * @return array
     */
    public function loginAction(AuthenticationUtils $utils, LoginFormType $type)
    {
        var_dump($this->request);
        /** If the user is already logged in, forward them to the homepage **/
        if ($this->authorizationChecker->isGranted('IS_AUTHENTICATED_FULLY'))
        {
            return new RedirectResponse($this->urlGenerator->generate('home'));
        }
        /** Create the form **/
        $loginForm = $this->formFactory->getSymfonyFormFactory()->createBuilder($type, null, [
            'action' => $this->urlGenerator->generate('login_check')
        ])->getForm()->createView();
        return [
            'login_form'    => $loginForm,
            'error'         => $utils->getLastAuthenticationError(),
            'last_username' => $utils->getLastUsername(),
        ];
    }

and got this in the dump of the request:

object(Symfony\Component\HttpFoundation\Request)#384 (21) {
  ["attributes"]=>
  object(Symfony\Component\HttpFoundation\ParameterBag)#387 (1) {
    ["parameters":protected]=>
    array(0) {
    }
  }
  ["request"]=>
  object(Symfony\Component\HttpFoundation\ParameterBag)#385 (1) {
    ["parameters":protected]=>
    array(0) {
    }
  }
  ["query"]=>
  object(Symfony\Component\HttpFoundation\ParameterBag)#386 (1) {
    ["parameters":protected]=>
    array(0) {
    }
  }
  ["server"]=>
  object(Symfony\Component\HttpFoundation\ServerBag)#390 (1) {
    ["parameters":protected]=>
    array(0) {
    }
  }
  ["files"]=>
  object(Symfony\Component\HttpFoundation\FileBag)#389 (1) {
    ["parameters":protected]=>
    array(0) {
    }
  }
  ["cookies"]=>
  object(Symfony\Component\HttpFoundation\ParameterBag)#388 (1) {
    ["parameters":protected]=>
    array(0) {
    }
  }
  ["headers"]=>
  object(Symfony\Component\HttpFoundation\HeaderBag)#391 (2) {
    ["headers":protected]=>
    array(0) {
    }
    ["cacheControl":protected]=>
    array(0) {
    }
  }
  ["content":protected]=>
  NULL
  ["languages":protected]=>
  NULL
  ["charsets":protected]=>
  NULL
  ["encodings":protected]=>
  NULL
  ["acceptableContentTypes":protected]=>
  NULL
  ["pathInfo":protected]=>
  NULL
  ["requestUri":protected]=>
  NULL
  ["baseUrl":protected]=>
  NULL
  ["basePath":protected]=>
  NULL
  ["method":protected]=>
  NULL
  ["format":protected]=>
  NULL
  ["session":protected]=>
  NULL
  ["locale":protected]=>
  NULL
  ["defaultLocale":protected]=>
  string(2) "en"
}

Very strange, isn't it?

Am I missing something? Many thanks.

J7mbo commented 9 years ago

Hey, thanks for the issue report. I've taken a look at {{ asset() }} and I can see exactly what the issue is.

Symfony 2.4 has the RequestStack, which you can read about here. They advocate calling getCurrentRequest() to retrieve the request you want.

As for why Request is empty, Auryn is injecting a blank instance of the Request object, not the one that the current application is using. The reason for this is here, we're "sharing" the request stack around the application for injection, but not the request object. You could add request to that list, so that the DelayedInjectionHandler will pick it up and call Auryn::share() on it, so that when it reaches your controller, you'll have a shared Request object. The same goes for Session etc. It's all designed to be entirely configurable by the end user, could do with much better docs, though.

It's up to you, I'd just stick with the RequestStack.

I'll submit a fix for {{ asset() }} now, though :-)

J7mbo commented 9 years ago

Please update to 0.2.2 - that should be fixed.

raphaelcazorla commented 9 years ago

OK, thanks for your explanation and fast reply ;)

2 things left I don't get: 1/ When I try to add request or session to boot_delay_injections (in global.yml):

  - request_stack
  - security.token_storage
  - security.authorization_checker
  - session
  - request

I got the following error:

InvalidArgumentException in Container.php line 95:
Identifier "request" is not defined.

2/ I thought that AbstractController was dealing with passing request, session, etc. to the controller?

 public function __construct(
        Request              $request,
        Session              $session,
        FormFactory          $formFactory,
        UrlGenerator         $urlGenerator,
        UserProvider         $userProvider,
        EntityManager        $entityManager,
        AuthorizationChecker $authorizationChecker,
        TokenStorage         $tokenStorage
    )
    {
        $this->request              = $request;
        $this->session              = $session;
        $this->formFactory          = $formFactory;
        $this->urlGenerator         = $urlGenerator;
        $this->userProvider         = $userProvider;
        $this->entityManager        = $entityManager;
        $this->authorizationChecker = $authorizationChecker;
        $this->tokenStorage         = $tokenStorage;
    }

Think I'm missing something in here :)

Anyway, good job and thanks again.

J7mbo commented 9 years ago

So, for your first question - why can't we use the Request object, that's because we're using Silex 2.0 - the Silex changelog shows:

[BC BREAK] $app['request'] service removed, use $app['request_stack'] instead

You could always make a factory to get your Request for you, Auryn does allow you to create instantiation delegates. If you check the config, you can see that the auryn module already calls delegate on the things there to create your Doctrine Repositories for you when you typehint for them, so you could do the same for your request.

As for AbstractController, nice spot, that's another bug - it needs to be changed to RequestStack that is injected, but I'll just pull the current Request object from it so there'll be no change to $this->request, except that it'll just work as expected now :-)

raphaelcazorla commented 9 years ago

Cool, seems I'm quiet getting things altogether!

Last thing, I think quiet annoying, but could be understandable if we consider Aurex is some kind of "skeleton":

The installation process does not allow future updates...like upgrading from 0.2.1 to 0.2.2 :-) Maybe you have a simple solution, but from my understanding, apart from doing some kind of merge with git, it's not that simple...am I wrong? Do you any other solution in mind?

Many thanks again!

J7mbo commented 9 years ago

Fix applied to 0.2.3.

J7mbo commented 9 years ago

You're completely right on the upgrade path, there currently isn't a simple one available. I'm looking at how Symfony does it and it doesn't seem to be an easy task, however I'll open that as an issue and see what I can do to make it work over the next few weeks.

raphaelcazorla commented 9 years ago

That's exactly what I was going to propose. Could be definitively simple to do it with vanilla "composer update"

Great job ! ;-)