Take the following tree structure:
├───base
│ ├───0001
│ │ └───pages
│ │ file.twig
│ │ file_content.twig
│ └───ext
│ └───store
│ │ └───pages
│ │ └───all
│ │ │ file.twig
│ │ └───0001
│ │ file.twig
│ └───newsletter
│ └───pages
│ └───all
│ │ file.twig
│ └───0001
│ file.twig
└───pages
│ file.twig
└───0001
file.twig
As you can see, there's a load of file.twig
scattered around.
I want to render the contents of the file base/0001/pages/file_content.twig
.
But, I want that the following files can change the content inside blocks:
ext/<...>/pages/0001/file.twig
ext/<...>/pages/all/file.twig
/pages/0001/file.twig
/pages/file.twig
But, these files may or may not exist, may or may not be needed and must be able to change the content of any block.
Is there any way to make this work?
So far, I have the following:
{% embed 'base/pages/file_content.twig' %}
{% block page_file %}
{{ parent() }}
{% if data.store_enabled %}
{% include [
'base/ext/store/pages/0001/file.twig',
'base/ext/store/pages/all/file.twig'
] ignore missing
%}
{% endif %}
{% include ['pages/0001/file.twig', 'pages/file.twig'] ignore missing %}
{% endblock %}
{% endembed %}
This "works", in the sense that it renders the page but doesn't allow any block to be overrided.
How could I make this work?
As an example, consider this structure of files (yes, files are missing, and that's expected):
├───base
│ ├───0001
│ │ └───pages
│ │ file.twig
│ │ file_content.twig
│ └───ext
│ └───store
│ │ └───pages
│ │ └───0001
│ │ file.twig
└───pages
file.twig
The file base/0001/pages/file_content.twig
has the following:
{% block page_file %}
{% block title %}<h1>Nice title</h1>{% endblock %}
{% block price %}{% endblock %}
<div class="clearfix"></div>
{% endblock %}
The file base/ext/store/pages/0001/file.twig
has the following content:
{% block price %}<span class="price">55 €</span>{% endblock %}
And the file pages/file.twig
has:
{% block title %}{{ parent() }}<hr>{% endblock %}
{% block price %}<div>{{ parent() }}</div>{% endblock %}
The output I expect is the following:
<h1>Nice title</h1><hr>
<div><span class="price">55 €</span</div>
<div class="clearfix"></div>
But with that code, all the other files' changes are being ignored and the output is being only the following:
<h1>Nice title</h1>
<div class="clearfix"></div>
Note:
It's important to notice that I'm using Twig 1.33.2, and using the Twig_Autoloader::register();
method.
I can't use Twig 2.x, since it requires PHP 7.0+ and I'm restricted to PHP 5.3.29.
After a few more attempts, I've finally figured a way to do this.
This is as ugly as it may seem...
Assuming the structure:
├───base
│ ├───0001
│ │ └───pages
│ │ file.twig
│ │ file_content.twig
│ └───ext
│ └───store
│ │ └───pages
│ │ └───0001
│ │ file.twig
└───pages
file.twig
The main file (base/pages/file.twig
) has the following code:
{% if data.store_enabled %}
{% include [
'base/ext/store/pages/0001/file.twig',
'base/ext/store/pages/all/file.twig',
'base/pages/file_content.twig'
] ignore missing
%}
{% else %}
{% include [
'pages/0001/file.twig',
'pages/file.twig',
'base/pages/file_content.twig'
] ignore missing
%}
{% endif %}
This will include the files inside base/ext/store/pages/
if they exist. If a file is missing there, then the file base/pages/file_content.twig
is included.
All the files inside base/ext/store/pages/
must have the following code on the top:
{% extends [
'pages/0001/file.twig',
'pages/file.twig',
'base/pages/file_content.twig'
]
%}
And the files inside pages/
must have the following:
{% extends 'base/pages/file_content.twig' %}
This allows you to have override any block inside base/pages/file_content.twig
and the files are only included/extended if they exist.
Having there a garanteed file (in this case, base/pages/file_content.twig
must always exist) will still display the "default" content and won't throw a nasty exception.
Outside of the scope of this answer, I've initially found a very similar aproach, which used conditional values.
Try it on: https://twigfiddle.com/u06tur