prefixing asset path for files in Symfony2 and Twig - php

I upoad my files to web/files/images/ and i'm trying to link them using asset function:
<img src='{{ asset(article.image) }}'/>
but this produces URLs like /img1.jpg
I need to prefix (setting a base folder) asset URLs to force it to make /files/images/img1.jpg
How can I prefix asset urls?

While you could easily introduce a new twig variable for that purpose (i.e. in your base template) ...
{% set asset_base = '//files/images' %}
... or create a static global twig variable ...
# app/config/config.yml
twig:
globals:
asset_base: //files/images
... and afterwards use it inside i.e. the src attribute of your img tag ...
<img src='{{ asset_base }}{{ asset(article.image) }}'/>
... symfony2 already provides this functionality in form of the assets_base_urls directive:
# app/config/config.yml
framework:
templating:
assets_base_urls:
http: [http://domain/files/images]
ssl: [https://domain/files/images]
You can aswell set the base urls both at once by providing a protocol-relative url:
framework:
templating:
assets_base_urls: //files/images
More information about the directive can be found in the documentation chapter FrameworkBundle Configuration#assets-base-urls.

Note that since symfony 2.7 the assets_base_urls solution from #nifr will only work with valid urls, not with relative pathes.
See here https://github.com/symfony/symfony/issues/14332
The solution for > 2.7 is to use the new assets component for relative base path as prefix.
framework:
assets:
base_path: 'assets'

If you don't want to prefix all assets, the asset helper provides another really nice way to do this using packages.
Packages have a name and can have other settings, such as the version and the base path. You configure packages in the configuration and you can set the name of the package to use in the second argument of the asset function.
In your case:
framework:
templating:
packages:
images:
base_url: /web/files/images # can also be scheme specific
And then in you template:
<img src="{{ asset('...', 'images'). }}">
More information: http://symfony.com/doc/current/components/templating/helpers/assetshelper.html#multiple-packages

Related

Symfony 4 _instanceof in Bundle's services.yaml

I have a bundle which has interface Optimax\HealthCheckBundle\Service\HealthInterface
I need set tags to all services which implement this interface. I do it with the following directive:
_instanceof:
Optimax\HealthCheckBundle\Service\HealthInterface:
tags: ['health.service']
It works fine when I put this directive into config/services.yaml. But if I put this code into my bundle's config (which required via composer) vendor/optimax/health-check/src/Resources/config/services.yaml it doesn't work. I don't want copy-paste this directive into services.yaml every time when I require this bundle to a new project.
How can I move this directive into services.yaml which is in my Bundle's directory or at least into another file in config/packages folder of the project?
To expand on the issue for others.
_instanceof functions identically to the _defaults definition. In that the _instanceof definition only applies to the file it is used in.
This prevents third-party bundle definitions from affecting your entire application with definitions like:
_defaults:
public: true
autowire: false
_instanceof:
Psr\Log\LoggerAwareInterface:
- method: setLogger
arguments:
- '#custom_logger'
tags:
- { name: monologer.log, channel: 'custom_channel' }
Therefor if the service you are attempting to tag with _instanceof is not declared in the same services.yml file the tag will not be added.
To tag services that implements an Interface in the entire application, you would need to use the method provided by #Jeroen
Did you try auto tagging all services with this interface in your Bundle extension like this:
$container->registerForAutoconfiguration(CustomInterface::class)
->addTag('app.custom_tag')
;
Taken from the Symfony docs:
https://symfony.com/doc/current/service_container/tags.html

Twig path without default locale

in my Symfony 3.3 project I use locale system to change the user language. I have configured my routing to allow the 'en' version for not having it in the url.
acme_front_office:
resource: "#AcmeFrontOfficeBundle/Resources/config/routing.yml"
prefix: /{_locale}
defaults: { _locale: 'en'}
requirements:
_locale: '|en|fr'
So those url redirect all to the same page :
/home
/en/home
/fr/home
But in my twig templates the {{ path() }} function set by default the right locale except that when my user see the english version of the website I want that the generated url head to /home and not /en/home.
If you have a clue on how to do that without changing all the path() calls to override the _locale param I will be very thankful.
Have a good day ;)
So after some digging, the solution that I came up with is to rewrite some parts of the Symfony Routing system. If you want to check the solution you can find the code in the following gitlab repo, in the Routing dir.
TranslateBundle Repo

How can I override resources for Third-Party bundles in Symfony 4?

I did a fresh Symfony installation by using Symfony Flex and the new skeleton belong to the next Symfony 4 directory structure. Next, I'm going to override some resources like templates, translations, etc. from an external bundle.
I've tried to create all these paths for templates (to start) but nothing works:
templates/EasyAdminBundle/views/...
templates/Resources/EasyAdminBundle/views/...
app/Resources/... (just a proof from old structure)
Where should I puts my resources files to override third-party bundle resources?
For all Symfony versions the resources path is %kernel.root_dir%/Resources/ . As the new 4.0 structure puts the Kernel.php into src/ directory, then it is:
# local resources directory
src/Resources/
# still works this path for local templates
src/Resources/views/
# override resources for third-party bundles
src/Resources/AcmeDemoBundle/views/ # legacy convention to override templates
src/Resources/AcmeDemoBundle/translations/ # for override both translations and validations files
src/Resources/AcmeDemoBundle/... # etc.
New conventions to override resources (since Symfony 3.4)
Twig Templates:
Just follow the convention:
templates/bundles/AcmeDemoBundle/path/to/template.html.twig
If you are upgrading to Symfony 3.4 & 4.0 and you want to use the previous templates conventions, configure your own Twig's paths:
# app/config/config.yml (3.3)
twig:
paths:
# Default templates directory, since 3.4+
templates: ~
# Directory convention to override bundle templates, since 3.4+
# make sure to know the actual Twig namespace for each bundle.
# e.g. AcmeDemoBundle -> AcmeDemo:
templates/bundles/AcmeDemoBundle: AcmeDemo
Translations: Similar to templates/ you have the translations/ directory at the root of the project (by default):
translations/bundles/AcmeDemoBundle/messages.en.yml
Note: The /bundles/AcmeDemoBundle/ sub-directory is not mandatory because translations are not related to bundles, but to domains. That means that you can override translations as long as it is in the correct domain.

Symfony parameter yml configuration for paths into a specific bundle

I have declared a controller as service and want to pass the template path to be rendered by the twig engine as a parameter.
The twig template file is in the same Bundle of the controller, and I'm defining it in the same service.yml file.
Given that the template is under MyBundle\Resources\views\my\path\templatename.html.twig how can I reference to it in the yml?
Solved:
parameters:
templatePath: 'MyBundle:my/path/filename.html.twig'

Symfony2 KnpLabsGaufrette - Get local filesystem per twig (downloadable files)

i'm using this config.yml.
knp_gaufrette:
adapters:
uploaded_files:
local:
directory: "%kernel.root_dir%/../web/uploads"
create: true
filesystems:
uploaded_files:
adapter: uploaded_files
alias: uploaded_files
Now i want to access uploaded files per twig.
Also for example:
<a href="{{ path('gaufrette_download', {system: 'uploaded_files', file: 'test.txt'}) }}>{{ 'Download' | trans }}</a>
The file should have a path like...
http://localhost/web/uploads/test.txt
I want a direct access to the file(s).
No controller (action).
Is this possible? Any ideas?
If your folder is web-accessible (i.e. you can type the url http://localhost/web/uploads/test.txt in your address bar and download the file), all you have to do is map the route gaufrette_download to that path. Your bundle's routing.yml could look like this (notice the missing defaults: { controller: ... }):
gaufrette_download:
path: /web/uploads/{file}
If your .htaccess is defined properly your web server should serve the file instead of accessing your application. You might have to add requirements for file, e.g. to allow for slashes (search the symfony cookbook for this)
If you just want to skip writing a controller (action), you could just as well create an event listener which is triggered when your request matches the route.

Categories