Symfony: Assetic not using controller with bootstrap bundle? - symfony

I'm new to Symfony (2.4) and having trouble understanding how Assetic serves assets through the app instead of off the file system for development.
In particular, I'm trying to get the BrainCrafted Bootstrap Bundle setup so that I don't have to dump my assets for it to work on development.
In my base template file, I have:
<link href="{{ asset('/css/bootstrap.css') }}" rel="stylesheet" media="screen">
When I render a page using the app_dev.php, the path does not change and still tries to load it via /css/bootstrap.css, which does not exist.
My assetic setting for "use_controller" is set to true.
However, if I include a stylesheet like this:
{% stylesheets '#MyCustomBundle/Resources/public/css/*' %}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}
Then the URL to the stylesheet is properly rooted with "app_dev.php".
Why doesn't the main asset twig function prepend app_dev.php?

BootstrapBundle configures Assetic using config.yml. You need to dump the assets using php app/console assetic:dump to generate the CSS files.
If you want to configure your stylesheets inside your Twig template you should use stylesheets (as mentioned by Dovydas Bartkevičius) and if you want to configure your stylesheets in your config.yml you have to generate the static CSS using php app/console assetic:dump and use assets to include the static files in your template.
BootstrapBundle configures Assetic using config.yml so you have to dump the assets. While developing you can also use php app/console assetic:dump --watch to generate the CSS every time the source changes.

{{ asset }} function just adds a path to the assets folder of the project. It seems that your assets are in the bundle's directory therefore they are not public and cannot be reached.
http://symfony.com/doc/current/book/templating.html#linking-to-assets
{% stylesheets %} and {% javascripts %} actually takes asset files from your bundles, applies filters if present (compression, etc) and serves them at request through the controller.
You can dump asset files with command line API php app/console assetic:dump.
http://symfony.com/doc/current/cookbook/assetic/asset_management.html#dumping-asset-files

If you pass an absolute path to the asset function then it will return the argument without changing it at all.

Related

Include css and js files from vendor library via assets in Twig

I want to include css and js files from a library in my vendor directory into Twig.
I downloaded morrisjs via composer into my vendor directory of symfony. Now I want to include the main css und js files into my Twig Template. But as far as I know the asset function only works with files that are located in Bundles.
The files I want to include are located in the following paths:
project\vendor\morrisjs\morris.js\morris.js
project\vendor\morrisjs\morris.js\morris.css
I thought about some theoretical code that would look like that:
{% block stylesheets %}
<link href="{{ asset('vendor/morrisjs/morris.js/morris.css') }}" />
{% endblock %}
Is there any possibility to include these files directly from vendor and how when not?
If morrisjs is a frontend javascript library then install it via npm or bower.
Packages installed via composer should have all their public assets in Resources/public so you can publish them using:
$ php bin/console assets:install target [--symlink]
Then in a twig template use just:
<link href="{{ asset('bundles/acmedemo/css/contact.css') }}" rel="stylesheet" />
After installing new packages, run:
php app/console assets:install web
'web' being your server's document root(public_html or whatever it is).
You also need to dump your assets:
//for dev
php app/console assetic:dump
//for prod
php app/console assetic:dump --env=prod --no-debug
In your servers public root, you will have directory /bundles/ where all your files will be present, and you can easily include them in Twig with {{ asset('bundles/morri..) }}
Read up on combining assets, something you will need at some point.

assetic:dump command not dumping images

As far as I know, the command php app/console assetic:dump should take everything from app/Resources/public, process it if necessary (say Sass file -> CSS file), and dump it into the web/ folder. When I run the command, my javascript files and css files get transferred correctly, however, my images do not. They do not get transferred to web/ at all. How can I get the images to transfer from my non-public directory to the public one on assetic:dump?
My file structure:
+-symfony/
+-app/
+-Resources/
+-public/
+-css/
//All of my CSS files
+-javascripts/
//All of my JS files
+-images/
//All of my image assets
My layout file looks like so:
{% stylesheets
'css/bootstrap_loader.css.scss'
'css/bootstrapValidator.min.css'
'css/style.css.scss'
'css/learners.css'
'css/stately/*'
filter='cssrewrite'
%}
<link rel="stylesheet" href="{{ asset_url }}">
{% endstylesheets %}
{% javascripts
'js/jquery-1.11.2.min.js'
'#bootstrap_js'
'js/landing_page.js'
'js/homepage_video.js'
'//use.typekit.net/rah2apm.js'
%}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
You are wrong. Assetic is not the same as assets.
Assetic is a library that can compile your JS or CSS with some filters.
Assets is your resources.
Try to run:
php app/console assets:install --symlink
It will create symlink folder inside web/ directory that will point to your bundle's Resources/public folder.
If you omit --symlink option it will hard copy all your assets once and you will need to run this command every time you changed your assets.

Symfony Unable to Generate a URL for Route to Stylesheet

I have two CSS files in the same folder, with identical access rights. When testing in the same Twig file, one CSS file generates a URL to the file and loads perfectly and one gives an error.
Error
An exception has been thrown during the rendering of a template
("Unable to generate a URL for the named route "_assetic_a328b4c_0" as
such route does not exist.") in #GutensiteStream/Stream35163.html.twig
at line 19.
Files on Server
ls -al /var/www/core/cms/src/Templates/GutensiteAdminBundle/Resources/public/css
-rw-rw-r-- 1 chadwick developer 17K Feb 7 14:00 dashboard.css
-rw-rw-r-- 1 chadwick developer 49K Feb 6 16:00 site.css
Template with CSS that Loads
{% stylesheets '#TemplatesGutensiteAdminBundle/Resources/public/css/site.css' %}
<link rel="stylesheet" href="{{ asset_url }}">
{% endstylesheets %}
Template with CSS that does NOT Load
{% stylesheets '#TemplatesGutensiteAdminBundle/Resources/public/css/dashboard.css' %}
<link rel="stylesheet" href="{{ asset_url }}">
{% endstylesheets %}
Linking to the File Directly Works
<link rel="stylesheet" href="/gutensite/v/2/0/bundles/templatesgutensiteadmin/css/dashboard.css">
Steps Taken
I have already cleared cache multiple times, via app/console cache:clear and via rm -rf app/cache/*. I use php app/console assets:install --symlink /var/www/core/web/gutensite/v/2/0/ to symlink the public files to the bundles, and of course they are accessible (as demonstrated via the direct link).
My Config.yml
assetic:
#don't use dynamic links to assets, use full production paths
use_controller: false
When I ran into this error, the solution was quite simple:
When in doubt:
bin/console cache:clear
Assetic is looked for a cached version which doesn't exist. This could be for any number of reasons, but cache:clear seems like it should be the first stop.
It is not recommended to use the # helper and load css directly from your bundle in production.
The best practice approach is to store the css files in the app/Resources directory and using assets:install requesting them from the web root, but seing as you don't have an AppBundle, the second best thing would be to request them from the web/bundles directory:
{% stylesheets
'bundles/templategutenstideadmin/css/site.css'
'bundles/templategutenstideadmin/css/dashboard.css'
%}
<link rel="stylesheet" href="{{ asset_url }}">
{% endstylesheets %}
Make sure you run assets:install beforehand.
This way, your css files will be compressed to one file and they will be loaded with the latest changes from the assets:install command.
Loading css files directly from your bundle using # is not recommended outside of local testing. I suspect your first issue is the usage of muliple stylesheets tags in assetic (stylesheets tag is not a part of Twig), but generally using # for file linking is not a good idea for assets. Use it for things like routing and config in .yml files, but not for assets! :)
One instance where this error will occur is when you try to load such an asset in a child template, that is already being loaded in one of the parent templates.
To fix it, load the asset only once in a template chain.
(Have to post this as answer, as I can't comment, yet.)
config.yml
assetic:
bundles: [you bundle name , otherbundlename] #add this

Exporting assets from non-standard Symfony public resources directory

How can you specify an additional (alternate) location for assets:install or assetic:dump to look in, e.g.
`php app/console assets:install --symlink`
By default this scans and creates symlinks for all bundles with a Resources/public directory.
But I would like to use an alternative directory structure that adds 2 extra levels, e.g.
/Gutensite/TemplateBundle/Templates/Admin/Resources/public
/Gutensite/TemplateBundle/Templates/Lunar/Resources/public
/Gutensite/TemplateBundle/Templates/Solar/Resources/public
Using this structure, assetic:dump and assets:install doesn't find the files. And therefore I can't load them like this:
{% stylesheets '#GutensiteTemplateBundle/Templates/Admin/Resources/public/css/site.css' %}
<link rel="stylesheet" href="{{ asset_url }}">
{% endstylesheets %}
NOTE: most of my bundles follow the standard format, but this template bundle will contain a directory for every template so the public resource directory is 2 levels deeper. I also need to be able to install assets in client specific directories outside of the symfony root, but that may just need to happen manually. However, I need to be able to link to them.
Have you registered your bundle in AppKernel.php ?
Alternatively, if you don't have a bundle class in your bundle, you can use this notation in your twig template:
{% stylesheets '%kernel.root_dir%/../src/Gutensite/TemplateBundle/Templates/Admin/Resources/public/css/site.css' %}
<link rel="stylesheet" href="{{ asset_url }}">
{% endstylesheets %}

Difference between assetic:dump and assets:install

In Symfony2, what is the difference between assetic:dump and assets:install? In what scenarios should each of these commands be used, and in what order (if order is relevant)?
I actually wrote about this recently in an article about OroCRM, which is based on Symfony 2. If you want some of the context/why of the different commands, you might find it interesting.
There are two different systems for including frontend files (javascript, css, images, etc.) in a Symfony application. The assets:install command came first. This command will search all the Symfony Bundles in an application for a
Resources/public
folder. If found, the assets:install command will copy or symlink files from Resources/public to web/public/bundle/[bundle-name]. This is where links created with the twig assets function will look for these files. This
<script src="{{ asset('js/script.js') }}" type="text/javascript"></script>
Becomes this
<script src="/bundles/[bundle-name]/js/script.js" type="text/javascript"></script>
That's all the assets system does. It lets you store your frontend files with the bundle.
The assetic system is different. With assetic, you link to files like this.
{% javascripts '#AcmeFooBundle/Resources/public/js/foo.js' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
There's similar tags for stylesheets and images. Notice that assetic allows you to link to files in any bundle. (#AcmeFooBundle). Assetic will also let you link to multiple files in a folder with a wildcard.
{% javascripts '#AcmeFooBundle/Resources/public/js/*' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
Another difference with assetic is in the links generated. In the dev environment they'll look something like this.
<script type="text/javascript" src="/app_dev.php/js/foo.js"></script>
<script type="text/javascript" src="/app_dev.php/js/bar.js"></script>
That is, requests for these files will run through the PHP front controller (app_dev.php) via special routes setup in the assetic bundle. This means, when you're in dev mode, you never need to dump you assets. They're included automatically. It also allows you to apply filters to the files. For example, the following applies the cssrewrite filter to the files pulled in.
{% stylesheets 'bundles/acme_foo/css/*' filter='cssrewrite' %}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}
If you ever wanted to programmatically alter the output of your frontend assets — assetic lets you do that by writing custom twig filters.
However, this is performance intensive. In production, instead of linking each file individually via a the PHP front controller file, the generated HTML will look like this
<script type="text/javascript" src="/js/as5s31l.js"></script>
Where does as5s31l.js come from? That's what the assetic:dump command does. It combines all the individual javascript/css files (after applying the filters) and creates a nice, static, cacheable file for production.
What You Need to Do
Unless the project specifically tells you otherwise, you should always run assets:install and assetic:dump, because you'll never know which of your third party bundles use these commands. You only need to run assetic:dump before you deploy or view the application in prod mode. Order is irrelevant.
As for which system your bundle should use — if you've read the above and you're unsure what assetic can do for you, use assets. You'll be fine.

Resources