Chapters
40 Chapters
|
4:39:58
|
Login to bookmark this video
-
Course Code
Subscribe to download the code!Compatible PHP versions: ^7.1.3
Subscribe to download the code!Compatible PHP versions: ^7.1.3
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
10.
The asset() Function & assets.context
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
Subscribe to jump to this part in the video!
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
This tutorial is built on Symfony 4 but works great in Symfony 5!
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": "^7.1.3",
"ext-iconv": "*",
"aws/aws-sdk-php": "^3.87", // 3.87.10
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"doctrine/annotations": "^1.0", // 1.10.1
"doctrine/doctrine-bundle": "^1.6.10", // 1.10.2
"doctrine/doctrine-migrations-bundle": "^1.3|^2.0", // v2.0.0
"doctrine/orm": "^2.5.11", // v2.7.2
"knplabs/knp-markdown-bundle": "^1.7", // 1.7.1
"knplabs/knp-paginator-bundle": "^2.7", // v2.8.0
"knplabs/knp-time-bundle": "^1.8", // 1.9.0
"league/flysystem-aws-s3-v3": "^1.0", // 1.0.22
"league/flysystem-cached-adapter": "^1.0", // 1.0.9
"liip/imagine-bundle": "^2.1", // 2.1.0
"nexylan/slack-bundle": "^2.0,<2.2.0", // v2.1.0
"oneup/flysystem-bundle": "^3.0", // 3.0.3
"php-http/guzzle6-adapter": "^1.1", // v1.1.1
"phpdocumentor/reflection-docblock": "^3.0|^4.0", // 4.3.0
"sensio/framework-extra-bundle": "^5.1", // v5.2.4
"stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
"symfony/asset": "^4.0", // v4.2.3
"symfony/console": "^4.0", // v4.2.3
"symfony/flex": "^1.9", // v1.21.6
"symfony/form": "^4.0", // v4.2.3
"symfony/framework-bundle": "^4.0", // v4.2.3
"symfony/property-access": "4.2.*", // v4.2.3
"symfony/property-info": "4.2.*", // v4.2.3
"symfony/security-bundle": "^4.0", // v4.2.3
"symfony/serializer": "4.2.*", // v4.2.3
"symfony/twig-bundle": "^4.0", // v4.2.3
"symfony/validator": "^4.0", // v4.2.3
"symfony/web-server-bundle": "^4.0", // v4.2.3
"symfony/yaml": "^4.0", // v4.2.3
"twig/extensions": "^1.5" // v1.5.4
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0", // 3.1.0
"easycorp/easy-log-handler": "^1.0.2", // v1.0.7
"fzaninotto/faker": "^1.7", // v1.8.0
"symfony/debug-bundle": "^3.3|^4.0", // v4.2.3
"symfony/dotenv": "^4.0", // v4.2.3
"symfony/maker-bundle": "^1.0", // v1.11.3
"symfony/monolog-bundle": "^3.0", // v3.3.1
"symfony/phpunit-bridge": "^3.3|^4.0", // v4.2.3
"symfony/stopwatch": "4.2.*", // v4.2.3
"symfony/var-dumper": "^3.3|^4.0", // v4.2.3
"symfony/web-profiler-bundle": "4.2.*" // v4.2.3
}
}
6 Comments
Hi,
When I do a dump on
$this->requestStackContext->getBasePath(),it returns me a empty string... :/
Hey YinYang,
And that's OK, right? What do you think it should return? See the explanation below:
> If our app lives at the root of the domain - like it does right now - this will just return and empty string. But if it lives at a subdirectory like thespacebar, it'll return /thespacebar.
So, if your project is not in a subdirectory - that's OK :)
Cheers!
Hello! I couldn't find information online why it's better to use RequestStackContext over RequestStack, that is available for autowiring.
One could then do:
$this->requestStack->getCurrentRequest()->getBasePath()(which seems to be preferred: https://symfony.com/doc/current/service_container/request.html)
Instead of:
$this->requestStackContext->getBasePath()Also there's Request we could have used. It's unclear for me what pointed you in that direction: the documentation doesn't even mention it. Please help :)
Yo Renaud G.!
Really interesting question :). In practice, both are probably fine. I used RequestStackContext because technically that's what the Twig
asset()function uses internally. And so, we're exactly matching its behavior.Here's what happens behind the scenes - it should help clarify a bit:
1) Symfony boots up and creates a Request object with all the data inside
2) When Symfony's router executes, it uses the data from the Request to set the data on the RequestContext - https://github.com/symfony/symfony/blob/e60a876201b5b306d0c81a24d9a3db997192079c/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php#L77-L86 - that means that (in practice) the data in Request and RequestStack are identical.
That's why... probably both will work fine. However, there is at least one edge case: running code inside a custom console command. If you run code inside a custom console command and need to generate absolute URLs, because there is no request, generating absolute URLs doesn't work (the domain "localhost" will be used). To work around this, you need to set two parameters - we show that here: https://symfonycasts.com/screencast/mailer/route-context#codeblock-414154c720
The point is, when you do that, that data is set on the request context not the request. In other words, if you correctly added these parameters so that your custom console command behaves correctly but then rely on the Request inside of the code in this video (instead of the RequestContext) it would not work.
The tl;dr is: we use request context because that's what
asset()uses internally... and it guarantees our code behaves exactly like it :).Cheers!
Thanks Ryan! I'm still having a hard time wrapping my head around how you went from asset to RequestStackContext. Asset pointed me to Packages that pointed me to Package that has a ContextInterface that is apparently instantiated at runtime with a RequestStackContext but oh boy how should I have known that?
Some concepts are still a bit opaque to me and make me wonder what else I might be doing wrong unknowingly.
Hey Renaud G.!
This is a particularly tricky/deep one to figure out.
Well done following the trail! I'm impressed! Once I aw that some Package object/service had a ContextInterface argument, I would be wondering: "I wonder what service that "ContextInterface" argument truly is"? I personally then dig into core XML files in Symfony to find the service definition (you can also grep symfony/vendor for this interface to help find those), but you can usually also get help from
bin/console debug:container. Something like this series of commands:Try those commands and see if you can follow how I'm jumping from level to level. The last command ultimately tells me that the ContextInterface argument is really the service id
assets.context, which is an instance ofSymfony\Component\Asset\Context\RequestStackContext. THAT is how I dig up what low-level service does this work. It's one of the most difficult examples of "trying to figure out what Symfony is really doing behind the scenes". So honestly, I think you're doing really well :).Cheers!
"Houston: no signs of life"
Start the conversation!