symfony 2 template inheritance and assets management in multi app environment - php

I have a problem,
An exception has been thrown during the rendering of a template ("Unable to generate a URL for the named route "_assetic_3625095_0" as such route does not exist.") in #base_templates/base.html.twig at line 9.
Sturcture of my app directory:
Resources // Contains common layouts and assets for all of my apps
config // Contains common configs
current_app // yes, this is a current application directory
So. I have a base.html.twig in my Rosurces/views/ directory with such markup:
<html>
<head>
<meta charset="UTF-8"/>
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}{% endblock %}
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}"/>
{% block javascripts %}
{% javascripts
'#jquery'
'#global' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
And my current_app/Resources/views/base.html.twig inherit this Resources/views/base.html.twig
And I experience that problem I was talking about in the beginning.
Has anyone experienced such kind of problems already ? Do you have a solution ?
I know if I put javascripts code block inside my current_app/Resources/views/base.html.twig it works, but I need to keep common javascripts inside common layout. And I don't want to use symlink

Related

CSS and javascript not working in Symfony project

I recently started a new project in Symfony and I did everything here
but it didn't help.
I work for first time with Symfony and this is my first project. I strictly follow the documentation and I am trying to add some CSS but its now working. I use Encore and downloaded Yarn as the documentation says to do.
Below I will upload some of my code. It seems fine but it's not.
html.twig
<!DOCTYPE html>
<html lang="en" xmlns:th="http:thymeleaf.org">
<head>
<title>Events & People</title>
<meta charset="UTF-8">
{% block stylesheets %}
{#{% stylesheets '#AppBundle/public/build/app.css' %}#}
{{ encore_entry_link_tags('app') }}
<link src="/build/app.css" rel="stylesheet"/>
{#{% endstylesheets %}#}
{% endblock %}
</head>
webpack.config.js
var Encore = require('#symfony/webpack-encore');
Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
// public path used by the web server to access the output path
.setPublicPath('/build')
// only needed for CDN's or sub-directory deploy
//.setManifestKeyPrefix('build/')
/*
* ENTRY CONFIG
*
* Add 1 entry for each "page" of your app
* (including one that's included on every page - e.g. "app")
*
* Each entry will result in one JavaScript file (e.g. app.js)
* and one CSS file (e.g. app.css) if you JavaScript imports CSS.
*/
.addEntry('app', './assets/js/app.js')
//.addEntry('page1', './assets/js/page1.js')
//.addEntry('page2', './assets/js/page2.js')
// will require an extra script tag for runtime.js
// but, you probably want this, unless you're building a single-page app
.enableSingleRuntimeChunk()
/*
* FEATURE CONFIG
*
* Enable & configure other features below. For a full
* list of features, see:
* https://symfony.com/doc/current/frontend.html#adding-more-features
*/
.cleanupOutputBeforeBuild()
.enableBuildNotifications()
.enableSourceMaps(!Encore.isProduction())
// enables hashed filenames (e.g. app.abc123.css)
.enableVersioning(Encore.isProduction())
//11111111111
// .enableSassLoader()
//
// // processes files ending in .less
// .enableLessLoader()
//
// // processes files ending in .styl
// .enableStylusLoader()
//11111111111
// enables Sass/SCSS support
//.enableSassLoader()
// uncomment if you use TypeScript
//.enableTypeScriptLoader()
// uncomment if you're having problems with a jQuery plugin
//.autoProvidejQuery()
;
module.exports = Encore.getWebpackConfig();
Here is an image of my tree of files:
If it's done right it should load the files from my /build/app.css, but it's not loading it.
For me, it was just a caching problem.
let's try to delete the cache.
I didn't search deeply, but one bad think is your link tag...
Replace (src by href)
<link src="/build/app.css" rel="stylesheet"/>
By
<link href="/build/app.css" rel="stylesheet"/>
Have you tried this:
<link src="build/app.css" rel="stylesheet"/>
removing the leading "/" only and see if that works? not certain though.
I solved my problem I just have an error in my CSS and yarn didn't compile it
Move your link tag outside of the stylesheet block's. And use twig asset() function instead of the absolute path.
PS: use href instead of src in link tag
<!DOCTYPE html>
<html lang="en" xmlns:th="http:thymeleaf.org">
<head>
<title>Events & People</title>
<meta charset="UTF-8">
<link href="{{ asset('build/app.css') }}" type="text/css" rel="stylesheet"/>
{% block stylesheets %} {% endblock %}
</head>
If you really want the place the link tag inside your stylesheet block's, you must call this by using twig parent() function's in each template view
{% extends 'base.html.twig' %}
{% block stylesheets %}
{# call the parent content inside stylesheet block #}
{{ parent() }}
{# other css code here #}
{% endblock %}
the script & stylesheets should be outside the body tag like this!
> <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
</head>
<body>
{% block body %}{% endblock %}
</body>
{% block stylesheets %}
{{ encore_entry_link_tags('app') }}
{% endblock %}
{% block javascripts %}
{{ encore_entry_script_tags('app') }}
{% endblock %}
</html>
The script and stylesheets should be outside the body tag, like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
</head>
<body>
{% block body %}{% endblock %}
</body>
{% block stylesheets %}
{{ encore_entry_link_tags('app') }}
{% endblock %}
{% block javascripts %}
{{ encore_entry_script_tags('app') }}
{% endblock %}
</html>

Symfony get Asset Name in Assetic output

I generate my file with code like this:
{% block head_stylesheets %}
{% stylesheets
filter='?uglifycss'
'#MyBundle/Resources/public/less/myfile.less'
%}
<link href="{{ asset_url }}" type="text/css" rel="stylesheet" media="screen"/>
{% endstylesheets %}
{% endblock head_stylesheets %}
It dumps a file named like this: c543k540_myfile_1.css
This file is composed of the asset name followed by the filename: {assetName}_{filename}.css
How can I customize the output in keeping the asset name in the output?
{% block head_stylesheets %}
{% stylesheets
output="css/mynewfilename.{assetName}.css" // <--- Here
filter='?uglifycss'
'#MyBundle/Resources/public/less/myfile.less'
%}
<link href="{{ asset_url }}" type="text/css" rel="stylesheet" media="screen"/>
{% endstylesheets %}
{% endblock head_stylesheets %}
Update to clarify
I know that if I use the name option, in prod it will compile to myouputname.css but what I would like to have in debug/dev environment is following the bellow code something like myfile_myouputname_1.css
{% block head_stylesheets %}
{% stylesheets
name="myouputname" // <--- Here
filter='?uglifycss'
'#MyBundle/Resources/public/less/myfile.less'
%}
<link href="{{ asset_url }}" type="text/css" rel="stylesheet" media="screen"/>
{% endstylesheets %}
{% endblock head_stylesheets %}
Thanks for your reply.
Using Assetic to manage web assets in Symfony applications is no longer recommended. Instead, use Webpack Encore.
https://symfony.com/doc/current/frontend/assetic/index.html#dumping-asset-files
Page-Specific JavaScript or CSS (Multiple Entries) is described here:
https://symfony.com/doc/current/frontend/encore/simple-example.html#multiple-javascript-entries
// webpack.config.js
Encore
// ... general CSS file here...
.addStyleEntry('some_page', './assets/css/assetName.css')
;
Using addStyleEntry() is supported, but not recommended. A better option is to follow the pattern above: use addEntry() to point to a JavaScript file, then require the CSS needed from inside of that.

Theme assets management in Symfony2

I have a Symfony2 app that must serve different themes. These themes are essentially directories containing CSS files (eventually other files and minified into a single one).
In Phalcon, I could dynamically set the asset location of my assets in the controller. In Symfony, assets are explicitly defined. My current solution is as follows, but it doesn't look great. This is the HTML of my base.html.twig. I have a property theme in my entity and I define the theme object in my controller.
Basically I'm looking for the proper way to do this in Symfony. Otherwise, I'll just do it like this.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>{% block title %}Welcome!{% endblock %}</title>
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
{% if theme is defined %}
{% for asset in theme.css %}
<link rel="stylesheet" href="{{ asset.url }}"/>
{% endfor %}
{% endif %}
</head>
<body>
{% block page %}
Welcome to the default page!
{% endblock %}
{% block javascripts %}
{% if theme is defined %}
{% for asset in theme.js %}
<script src="{{ asset.url }}"></script>
{% endfor %}
{% endif %}
{% endblock %}
</body>
</html>
I think the most elegant way is to define a default theme, and put the diffrent themes into a root folder, just like this:
themes/
default/
css|js|images...
blue/
css|js|images...
yellow/
css|js|images...
then in Twig template engine, you can use it like this way:
<link rel="stylesheet" href="themes/{{ theme_name|default("default") }}/css/app.css"/>
<script src="themes/{{ theme_name|default("default") }}/js/app.js">

Symfony2: How to properly include assets in conjunction with Twig template inheritance?

I'm currently developing a web application using Symfony 2.1.0.
I've read through the Templating chapter of the book and I'm trying to include assets (right now, it's just a single stylesheet) in my web pages.
I'm using the Three-level inheritance system that is mentioned in the book, and my application structure currently looks like this:
app/Resources/views/
base.html.twig: base template, containing title, stylesheets and body blocks.
src/My/PageBundle/Resources/views
layout.html.twig: layout template (extending the base template), appending the main stylesheet to the stylesheet block, and overwriting the body block, including navigation.html.twig and defining a content block
layout-admin.html.twig: same thing as above, but including navigation-admin.html.twig
src/My/PageBundle/Resources/views/Main
standard templates, extending the layout template and overwriting its content block
src/My/PageBundle/Resources/views/Administration
administration templates. Same thing as above, but extending the administration layout template.
src/My/PageBundle/Resources/public/css
main.css: main stylesheet
As you can see, I have put the stylesheet in my bundle. I don't know whether this is good practice or not.
Now, the thing is, in layout.html I added this:
{% block stylesheets %}
{{ parent() }}
<link rel="stylesheet" type="text/css" href="{{ asset('css/main.css)' }}" />
{% endblock %}
But asset('css/main.css') is just linking to /css/main.css, whereas ./app/console assets:install installs the assets in web/bundles/mypagebundle/. I don't like the fact that this way, my bundle name would be publicly visible (which could make users suspect I'm using Symfony, and I like keeping the internals of my webpage, well, internal). Is it possible to change the directory where assets:install would install the assets? It seems tedious to me to manually install the assets in web/.
I'm also thinking about using Assetic for asset management, as I personally like the possibility to automatically minify my scripts/stylesheets and store them all together in one file. However, I hear that this is not possible if you include stylesheets at different levels, i.e. it wouldn't work with the three-level inheritance system. Is it possible to work around that? Also, would using Assetic enable me to hide my bundle name from the public?
Using assetic would address all your issues.
I hear that this is not possible if you include stylesheets at different levels, i.e. it wouldn't work with the three-level inheritance system
You can, but it will generate a css file for each level (just like with asset(), actually).
Example:
layout:
{% block stylesheets %}
{{ parent() }}
{% stylesheets 'main.css' %}
<link rel="stylesheet" type="text/css" href="{{ asset_url }}" />
{% endstylesheets %}
{% endblock %}
sub-template:
{% block stylesheets %}
{{ parent() }}
{% stylesheets 'sub.css' %}
<link rel="stylesheet" type="text/css" href="{{ asset_url }}" />
{% endstylesheets %}
{% endblock %}
result:
<link rel="stylesheet" type="text/css" href="..." />
<link rel="stylesheet" type="text/css" href="..." />
Alternatively sub-template can completly override the stylesheets block, so that only one stylesheet is generated (but it's less dry):
{% block stylesheets %}
{% stylesheets 'main.css' 'sub.css' %}
<link rel="stylesheet" type="text/css" href="{{ asset_url }}" />
{% endstylesheets %}
{% endblock %}
result (in production / non debug):
<link rel="stylesheet" type="text/css" href="..." />

How to include css from resources folder in symfony 2

I hvae the css located in
app/Resources/FOSUserbundle/css
How can i include that in my twig template
The reason i am putting css there is that my all overridden FOSUser templates in in that folder. So i want to keep css , js images all in there so that if i need to use in other website i just copy that folder
I'm not quite sure how you would include that in your TWIG templates, but ...
1) I put the resources I use in several bundles / projects in the web/ directory. Then you can reference then like this:
{% stylesheets 'css/styles.css' %}
<link href="{{ asset_url }}" type="text/css" rel="stylesheet" />
{% endstylesheets %}
2) If you need to override the FOSUserbundle anyway, you can put the resources inside the inheriting bundle, referencing them like this:
{% javascripts '#YourBundle/Resources/public/js/scripts.js' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
What you have done is perfectly all right.
Just do the following:-
$ app/console assets:install web
It will install the assets in the public "web" directory, where the assets should technically be, to be used with your Twig Templates.
Assets can then be used within Twig templates like this:-
{% block stylesheets %}
<link href="{{ asset('/css/main.css') }}" type="text/css" rel="stylesheet" />
{% endblock %}
{% block javascripts %}
<script src="{{ asset('/js/main.js') }}" type="text/javascript"></script>
{% endblock %}
Although the question suggests and override case, it also aks for a case where the css or js are in a common folder, away from the bundle structure.
One answer is to use the available twig variables. For example if I have one css file located here
app/Resources/views/clientSite/customFolder/css/mycss.css
I can load in any template using something like this (note the example overrides the full stylesheets block, but not required, the stylesheet twig tag can be added in any block):
{% block stylesheets %}
{{ parent() }}
{% stylesheets '%kernel.root_dir%/Resources/views/clientSite/customFolder/css/mycss.css'
%}
<link rel="stylesheet" type="text/css" href="{{ asset_url }}" />
{% endstylesheets %}
{% endblock %}
Also remember to execute the assetic:dump command, so symfony knows it had to publish the css to the web/css folder with all the other files.

Categories