Lots of people have asked, so here are a few common tasks you might do in your templates, as they would be written in ExpressionEngine vs. Craft.
{if something == 'value'}
...
{if:elseif something_else == 'other_value'}
...
{if:else}
...
{/if}
{% if something == 'value' %}
...
{% elseif somethingElse == 'otherValue' %}
...
{% else %}
...
{% endif %}
See Twig’s {% if %} docs for more info.
EE loops are always done with a tag pair, named after what we’re looping through.
{exp:channel:entries channel="news"}
{matrix_field}
...
{/matrix_field}
{/exp:channel:entries}
Looping through things in Craft is always done with a for-loop, where you pass in what you want to loop through, as well as what you want to call each item within the loop.
{% for entry in craft.entries.channel('news') %}
{% for block in entry.matrixField %}
...
{% endfor %}
{% endfor %}
There are pros and cons to both ways: EE’s is more elegant for simple things, but you can quickly run into tag name conflicts and other gotcha’s when dealing with more complex templates. That’s never an issue with Craft, but it’s at the expense of a more verbose and less straightforward syntax.
Both CMSes have various tags that are available within the loops, as well:
Thing | ExpressionEngine | Craft |
---|---|---|
How many items? | {total_results} | {{ loop.length }} |
1-based index | {count} | {{ loop.index }} |
0-based index | SOL | {{ loop.index0 }} |
Number of items left | SOL | {{ loop.revindex0 }} |
Number of ites left, inc. this one | SOL | {{ loop.revindex }} |
First item? | {if count == 1} | {% if loop.first %} |
Last item? | {if count == total_results} | {% if loop.last %} |
Odd? | {if count % 2 == 1} | {% if loop.odd %} |
Even? | {if count % 2 == 0} | {% if loop.even %} |
Cycle through values for each item | {switch='odd|even'} | {{ cycle(['odd','even'], loop.index0 }} |
The parent loop’s index | SOL | {{ loop.parent.loop.index }} |
See Twig’s {% for %} docs for more info.
ExpressionEngine’s {exp:channel:entries}
tag is optimized for this task (assuming you’re not on a single-entry page!). Just tell it which channel, how many, and so on.
{exp:channel:entries channel="news" limit="10"}
<h2><a href="{path='news/{url_title}'}">{title}</a></h2>
<p>{summary}</p>
{/exp:channel:entries}
In Craft you grab the entries using craft.entries and loop through them with a for-loop. You get to choose a variable name that each entry is going to be set to. In this case we’re going with newsEntry
so it’s clear which ‘title’ we’re outputting, etc..
{% for newsEntry in craft.entries.section('news').limit(10) %}
<h2><a href="{{ newsEntry.url }}">{{ newsEntry.title }}</a></h2>
<p>{{ newsEntry.summary }}</p>
{% endfor %}
See EntryModel for more info on those entry variables.
Assuming everything’s in the right place, this is the one time the dynamic
parameter will actually help you out, saving you from having to type url_title="{segment_2}" limit="1"
(Whew!).
{exp:channel:entries channel="news"}
<h1>{title}</h1>
{body}
{/exp:channel:entries}
Entries in Craft have their own URLs, so Craft knows for a fact which entry you’re trying to access, and which template it should load. In the process it will pass an entry
variable, pre-set to the entry you’re accessing. (In this case you don’t get a choice on what the entry
variable name is going to be called.)
<h1>{{ entry.title }}</h1>
{{ entry.body }}
Matrix follows the standard EE fieldtype convention of parsing a tag pair based on the field’s short name:
{matrix_field}
{column_one}
{column_two}
{/matrix_field}
As with looping through entries, we loop through Matrix blocks using a for-loop.
{% for block in entry.matrixField %}
{{ block.fieldOne }}
{{ block.fieldTwo }}
{% endfor %}
If you have multiple block types, you can add conditionals for them:
{% for block in entry.matrixField %}
{% if block.type == "text" %}
{{ block.textField }}
{% elseif block.type == "quote" %}
<blockquote>{{ block.quoteField }}</blockquote>
<p>– {{ block.authorField }}</p>
{% endif %}
{% endfor %}
See MatrixBlockModel for more info on those Matrix block variables.
Like Matrix/EE, Assets uses a tag pair based on the field’s short name:
{assets_field}
<img src="{url:image_manipulation_name}" alt="{title}"> {filename}
{/assets_field}
Like entries and Matrix fields in Craft, we once again use the for-loop to loop through assets:
{% for asset in entry.assetsField %}
<img src="{{ asset.url('transformHandle') }}" alt="{{ asset.title }}"> {{ asset.filename }}
{% endfor %}
See AssetFileModel for more info on those asset variables.
In EE you would do this with two embedded templates, which you’d manually include in every normal template.
<html>
<head>
<title>{if embed:page_name}{embed:page_name} - {/if}{site_name}</title>
</head>
<body>
<p class="copyright">
© {current_time format='%Y'} {site_name}
</p>
</body>
</html>
{embed="includes/_header" page_name="News"}
<h1>News</h1>
...
{embed="includes/_footer"}
Craft has the concept of Template Inheritance, which lets you define all of the common site elements in a single template, and extend it with sub-templates where necessary.
<html>
<head>
<title>{% if pageName is defined %}{{ pageName }} - {% endif %}{{ siteName }}</title>
</head>
<body>
{% block body %}
Default content
{% endblock %}
<p class="copyright">
© {{ now | date('Y') }} {{ siteName }}
</p>
</body>
</html>
{% extends "_site_layout" %}
{% set pageName = "News" %}
{% block body %}
<h1>News</h1>
...
{% endblock %}
this should be on the craft docs yeah?