gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
Okay, team, things are looking good. We created a Recipe
"value type", a custom query to load them, and a value converter to help layouts understand our Recipe
objects.
What we have not done yet is tell Layouts how to render a Recipe
item, item being the word Layouts uses for the individual "things" that grid and list blocks render. And actually, we need to tell Layouts both how to render an admin version of a recipe item, which will show up here, as well as the more-important frontend version of the item.
How an item is rendered is called an "item view". To add a new item view, we'll start in the config. Add a view
key with item_view
below it and app below that. I'll add a comment, because, in Layouts, app
means "admin". So what we're about to define under the app
key will be the admin view for our recipe item:
netgen_layouts: | |
... lines 2 - 12 | |
view: | |
item_view: | |
# app = admin | |
app: | |
... lines 17 - 22 |
Next, add recipes_app
... with a little note to say that this key is not important:
netgen_layouts: | |
... lines 2 - 12 | |
view: | |
item_view: | |
# app = admin | |
app: | |
# this key is not important | |
recipes_app: | |
... lines 19 - 22 |
Unlike other things, such as latest_recipes
, this internal key won't be used anywhere. Below, we need two important things. First, template
- don't include the "s" like I did - set to a template path, like nglayouts/
- that's a standard directory name to use for templates, but you could use anything - then, how about admin/recipe_item.html.twig
:
netgen_layouts: | |
... lines 2 - 12 | |
view: | |
item_view: | |
# app = admin | |
app: | |
# this key is not important | |
recipes_app: | |
template: 'nglayouts/admin/recipe_item.html.twig' | |
... lines 20 - 22 |
The second important thing is the very special match
key. We need to tell Layouts that this is the template that should be used when a recipe item is being rendered. For example, imagine if we had two value types: recipes and also blog posts. Well, layouts would need to know that this is the template to use for recipes... but to use a different item template for blog posts.
To do that, we'll use a strange syntax: item\value_type
set to doctrine_recipe
:
netgen_layouts: | |
... lines 2 - 12 | |
view: | |
item_view: | |
# app = admin | |
app: | |
# this key is not important | |
recipes_app: | |
template: 'nglayouts/admin/recipe_item.html.twig' | |
match: | |
item\value_type: 'doctrine_recipe' |
Where doctrine_recipe
references the name of our value type up here:
netgen_layouts: | |
... lines 2 - 3 | |
value_types: | |
doctrine_recipe: | |
... lines 6 - 22 |
We're going to see this match
key several more times in this tutorial. Layouts has a bunch of built-in "matchers", which are identified by strings like item\value_type
. These are used to help match one piece of config, like this template, with some other piece of config, like the doctrine_recipe
value type. There are a finite number of these matchers, and we're going to see the most important ones along the way. So don't worry too much about them.
Oh, but let me fix my typo: this should be template
with no "s".
Anyways, I want to mention one quick thing about the view
config key: there is only a small number of sub-keys that go under it.
Find your terminal and run:
php ./bin/console debug:config netgen_layouts view
This will dump a huge list of config, but don't be overwhelmed! We'll check out the important parts of this later. What I want you to look at are the root keys that go below view
, like block_view
and layout_view
.
It turns out that there are six different keys you are allowed to put below the view
key in your config, but we only care about two of them... which is why I'm mentioning this. When it comes to customizing your views, it's really quite simple! The first key we care about is item_view
, which controls the templates used when rendering "items": so when rendering things inside of a grid or list. The only other sub-key we care about is block_view
, which is how you configure the template used to render different block types, like the title
block or the text
block.
Yup, you're either rendering a block and want to customize its template or you're rendering an item inside of a block and you want to customize the template for that item. So the configuration looks gigantic, but most of these things are internal and you'll never need to worry about them.
Ok: we have our item_view
for our doctrine_recipe
for the admin area. Let's go add that template. In the templates/
directory, create two new sub-directories: nglayouts/admin/
. And then, a new file called recipe_item.html.twig
. Inside, write Does it work?
and... let's also use the dump()
function so we can see what variables we have access to:
Does it work? | |
{{ dump() }} |
Alright, head back to your browser, refresh the layouts admin and... it does work! And, apparently, we have access to several variables. The most important is item
. This is a CmsItem
object from Layouts... and it has a property called object
set to our Recipe
!
Let's use that! Say {{ item.object.name }}
, then a pipe, and... let's also print a date: {{ item.object.createdAt }}
- one of the other properties on Recipe
piped into the date
filter with Y-m-d
:
{{ item.object.name }} | <time>{{ item.object.createdAt|date('Y-m-d') }}</time> |
Let's check it! Move over, refresh and... got it! You can make this fancier if you want, but that'll work for us.
Next: let's create the frontend item view.
"Houston: no signs of life"
Start the conversation!
// composer.json
{
"require": {
"php": ">=8.1.0",
"ext-ctype": "*",
"ext-iconv": "*",
"babdev/pagerfanta-bundle": "^3.7", // v3.7.0
"doctrine/doctrine-bundle": "^2.7", // 2.7.0
"doctrine/doctrine-migrations-bundle": "^3.2", // 3.2.2
"doctrine/orm": "^2.13", // 2.13.3
"easycorp/easyadmin-bundle": "^4.4", // v4.4.1
"netgen/layouts-contentful": "^1.3", // 1.3.2
"netgen/layouts-standard": "^1.3", // 1.3.1
"pagerfanta/doctrine-orm-adapter": "^3.6",
"sensio/framework-extra-bundle": "^6.2", // v6.2.8
"stof/doctrine-extensions-bundle": "^1.7", // v1.7.0
"symfony/console": "5.4.*", // v5.4.14
"symfony/dotenv": "5.4.*", // v5.4.5
"symfony/flex": "^1.17|^2", // v2.2.3
"symfony/framework-bundle": "5.4.*", // v5.4.14
"symfony/monolog-bundle": "^3.0", // v3.8.0
"symfony/proxy-manager-bridge": "5.4.*", // v5.4.6
"symfony/runtime": "5.4.*", // v5.4.11
"symfony/security-bundle": "5.4.*", // v5.4.11
"symfony/twig-bundle": "5.4.*", // v5.4.8
"symfony/ux-live-component": "^2.x-dev", // 2.x-dev
"symfony/ux-twig-component": "^2.x-dev", // 2.x-dev
"symfony/validator": "5.4.*", // v5.4.14
"symfony/webpack-encore-bundle": "^1.15", // v1.16.0
"symfony/yaml": "5.4.*", // v5.4.14
"twig/extra-bundle": "^2.12|^3.0", // v3.4.0
"twig/twig": "^2.12|^3.0" // v3.4.3
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.2
"symfony/debug-bundle": "5.4.*", // v5.4.11
"symfony/maker-bundle": "^1.47", // v1.47.0
"symfony/stopwatch": "5.4.*", // v5.4.13
"symfony/web-profiler-bundle": "5.4.*", // v5.4.14
"zenstruck/foundry": "^1.22" // v1.22.1
}
}