gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
Our "item" template for skills is now being used! So, let's finish it!
We already know what we want the skills to look like... so let's go steal that from templates/main/homepage.html.twig
. Find the featured_skills
block, copy what one of those skills looks like, and paste that into skill.html.twig
. Let's also add dump(item.object)
at the top:
{{ dump(item.object) }} | |
<a href="#" class="text-center skill-item-container p-3"> | |
<h3>Folding in Cheese</h3> | |
<div class="p-3 mt-3 skill-img"> | |
<img src="{{ asset('images/pup-cup.png') }}" width="auto" height="80" alt="grater skill image"> | |
</div> | |
</a> |
We've created an item template before, so we know item.object
should give us the underlying "object" that represents this Contentful entry.
If we head over and refresh... awesome! This dumps a ContentfulEntry
object. And, though you can't see it from here, this class has a get()
method we can use to read any of the underlying data from Contentful.
For skills, if we dig a little... we have fields like title
and shortDescription
. Let's use those! For example, in the <h3>
, say {{ item.object.get('title') }}
:
{{ dump(item.object) }} | |
<a href="#" class="text-center skill-item-container p-3"> | |
<h3>{{ item.object.get('title') }}</h3> | |
... lines 4 - 6 | |
</a> |
And... yup! That worked!
For the <img src="">
, replace the asset()
stuff with item.object.get('image')
, followed by .file.url
, which is specific to Contentful. Also fill in the alt
attribute with item.object.get('title')
:
<a href="{{ path('cmf_routing_object', {'_route_object': item.object}) }}" class="text-center skill-item-container p-3"> | |
<h3>{{ item.object.get('title') }}</h3> | |
<div class="p-3 mt-3 skill-img"> | |
<img src="{{ item.object.get('image').file.url }}" width="auto" height="80" alt="{{ item.object.get('title')}} skill image"> | |
</div> | |
</a> |
The last thing we need to update is the URL. But, hmm. If we had created a "skill show" page in Symfony, we could use the Twig path()
function to link to that route! However, each skill page is actually created via a dynamic route thanks to the Contentful bundle. And, to create those routes, it uses something called the CMF routing system.
So, to link, we need to use that system. Say path('cmf_routing_object')
and pass _route_object
set to item.object
:
<a href="{{ path('cmf_routing_object', {'_route_object': item.object}) }}" class="text-center skill-item-container p-3"> | |
... lines 2 - 5 | |
</a> |
If you were using Sylius or Ibexa CMS, you would use some function from their system to create the link: this is specific to the CMF routing system.
Head over and try that. Yes! And if we click the link... double yes!
Let's celebrate by removing the dump()
. We can also delete this featured_skills
block from our homepage template: We won't need that at all anymore. But let's remake this <h2>
inside of the layouts admin first. To do that, add a Title block called "Featured Skills", make that "H2"... and give it those same CSS classes: text-center mb-4
.
The Grid is already in a container... but we want all of this in a container. So add a Column, wrap that in a Container, move the Grid and Title blocks inside of it... then we won't need a Container on the Grid anymore. Delete the "Features Skills" block... then finally hit "Publish and continue editing". While we're waiting, delete that block also from the Twig template.
And now... yes! It looks perfect!
Okay, while we're talking about item views, let's customize the item template for our other content type inside of Contentful: Advertisement. We're only rendering that in one place, on the individual skill page... right over here. Let's go check that out.
Publish this layout... then edit the individual skill layout. Earlier, we used the Contentful Entry Field block to render the advertisement
field, which is a "referenced entity". Yup, if you modify a skill in Contentful, down on the bottom, the "Advertisement" field allows you to choose from the Advertisements in our system.
Click on the Twig icon of the web debug toolbar... search for "item", and scroll down.. No surprise: it's using the standard Contentful "item" template. And, good news, we already know how to override that!
Head over to our configuration, copy the contentful_entry/skill
section, and paste it below. Replace skill
with ad
for the section name and template
... and update the content_type
to advertisement
... because that's the internal name of that type in Contentful:
netgen_layouts: | |
... lines 2 - 12 | |
view: | |
item_view: | |
... lines 15 - 21 | |
# default = frontend | |
default: | |
... lines 24 - 33 | |
contentful_entry/ad: | |
template: '@nglayouts/item/contentful_entry/ad.html.twig' | |
match: | |
item\value_type: 'contentful_entry' | |
contentful\content_type: 'advertisement' | |
... lines 39 - 46 |
Ok! Let's go add that template. In contentful_entry
, create a new file called ad.html.twig
... and then just print some text: Advertisement
:
Advertisement |
Moment of truth. Head back over and refresh. We got it! That was easy!
For the real template contents, I'll just paste them in. Once again, we use item.object.get()
to read the url
field. There's also an image
field and a shortText
field:
<a href="{{ item.object.get('url') }}" class="p-3 text-center ad-item-container" target="_blank"> | |
<h3>Sponsored Product</h3> | |
<img src="{{ item.object.get('image').file.url }}" width="auto" height="200" alt="Ad image"> | |
<p class="pt-3">{{ item.object.get('shortText') }}</p> | |
</a> |
And now... we've got it!
Next: What if we wanted to create a Grid of items... but make that one Grid look different than every other Grid on the site? We can do that by creating an extra "block view" for an existing block.
"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
}
}