| CARVIEW |
Freeform and Matrix
First of all, you need to have Freeform installed, a free from managing module by the add-on veterans at Solspace. In Freeform, you can define different form fields that can be populated by any number of forms. The only down side is, you still have to create the HTML for those forms in your templates and there’s no good way to automate this. Until now.
Secondly, you’ll need Pixel & Tonic’s Matrix. This field type allows you to create tabular data in channel entries, which can be used in a plethora of ways. You define the columns, and the client can add as many rows to the matrix as desired. Pixel & Tonic is also responsible for many other great field types, like P&T List which we’ll use in this example, too.
Channel and Fields
Now, to start automating from creation, we’ll create a designated channel called Forms. To this channel, we’ll add a couple of custom fields, for example:
form_description: a textarea for adding a form description;form_fields: a matrix field with all the form fields for this form;form_feedback: a textarea for the message displayed to the user after submitting the form;form_notify: a text input field where you can enter email addresses that will receive form notifications.
The fun starts with the Matrix field. To that, we’ll add the following columns:
field_name: the Low Freeform Field;field_label: the label associated with the form field;field_type: a drop down to determine the type of input field, eg. text, textarea, select, radio, checkbox…field_options: if the type is select, radio or checkbox, you can use this field to define the different options. P&T List is really useful here;field_required: a checkbox to select whether this field is required or not.
You could add more columns if needed. For example, you could add a field_class for custom styling or field_notes if you need to display per-field instructions. Below is a screenshot of the publish form with the above settings, but as you can imagine, the possibilities are endless.
The template
To bring it all together, we need to create a clever template. You could get creative and use an embed and relationships to add forms to other entries, but in this case, we’ll add the code to the index template in the forms template group. A link to a single form would look like this: domain.com/forms/my-custom-form. Here’s some code to go with it:
{exp:channel:entries channel="forms" limit="1"}
<h1>{title}</h1>
{if segment_3 == 'thanks'}
{form_feedback}
{/if}
{if segment_3 != 'thanks'}
{form_description}
{exp:freeform:form
collection="{title}"
notify="{form_notify}"
required="{form_fields search:field_required="y" backspace="1"}{field_name}|{/form_fields}"
return="{segment_1}/{segment_2}/thanks"}
<fieldset>
{form_fields}
<label for="{field_name}">
{field_label}
{if field_required == 'y'} <span class="required">*</span>{/if}
</label>
{if field_type == 'text'}
<input type="text" name="{field_name}" id="{field_name}" />
{if:elseif field_type == 'textarea'}
<textarea name="{field_name}" id="{field_name}" rows="10" cols="40"></textarea>
{if:elseif field_type == 'select'}
<select name="{field_name}" id="{field_name}">
{field_options}
<option value="{item}">{item}</option>
{/field_options}
</select>
{if:elseif field_type == 'radio'}
{field_options}
<label><input type="radio" name="{field_name}" value="{item}" /> {item}</label>
{/field_options}
{if:elseif field_type == 'checkbox'}
{field_options}
<label><input type="checkbox" name="{field_name}[]" value="{item}" /> {item}</label>
{/field_options}
{/if}
{/form_fields}
<button type="submit">Submit form</button>
</fieldset>
{/exp:freeform:form}
{/if}
{/exp:channel:entries}
After opening the channel:entries tag, we’ll open the freeform:form tag, using the entry’s title as the form collection. Using Matrix’ search option, we’ll define freeform’s required parameter. We can set more parameters, depending on the channel fields available.
Then we’ll loop through the form_fields. Use an advanced conditional to account for all the different input types and loop through the field_options if necessary. As you can see, the output is fully customisable.
Awesomeness achieved
This approach allows for fairly flexible custom forms, and with a bit of creative thinking, you could make it even better.
[ETA] Great minds think alike, so it seems. Here’s a write-up for the same idea in EE1 that I wasn’t aware of.
]]>Pro tip: don’t ever, ever nest a channel:entries tag inside another tag that loops. Srsly. Don’t. #eecms
…which sparked some response. The main reason for not nesting ExpressionEngine’s channel:entries tags is performance. Let me explain with an example.
Category archives
EE’s category archives tag is limited. To overcome this, some people use a channel:entries tag inside a channel:categories tag. Something like this:
{exp:channel:categories channel="news" style="linear" disable="category_fields"}
<h2>{category_name}</h2>
{exp:channel:entries channel="news" category="{category_id}" dynamic="no" disable="member_data|pagination|category_fields"}
<h3>{title}</h3>
{news_body}
{/exp:channel:entries}
{/exp:channel:categories}
Now, this will work. However, given enough content, this will slow your site down considerably. The number of queries that will be executed to generate the output is not fixed. Instead, a new channel:entries tag will be generated for each category found, which will result in an unknown number of queries. Dozens at least, hundreds if you have lots of content.
I did a test where I pasted the above code in an empty template, turned on the profiler and checked the number of queries used. With 4 categories and 6 entries, it took 41 queries to generate the page. Then I added a new entry in a new category and reloaded the page. This time it took 45 queries. Just imagine what would happen if there are 20 categories with 200 entries. And that’s not even a lot.
Fix it
To fix this potential problem, we need to make sure the amount of queries needed to generate the page is fixed. We can achieve this by un-nesting the two tags and using PHP on Output. The code is a bit more complicated, but it will improve performance dramatically. Here’s the code in full. I’ll explain each bit below.
<?php
$entries = array();
{exp:channel:entries channel="news" dynamic="no" disable="member_data|pagination|category_fields"}
$entry =<<<EOE
<h3>{title}</h3>
{news_body}
EOE;
{categories}
$entries[{category_id}][] = $entry;
{/categories}
{/exp:channel:entries}
?>
{exp:channel:categories channel="news" style="linear" disable="category_fields"}
<h2>{category_name}</h2>
<?php if (isset($entries[{category_id}])): ?>
<?=implode("\n", $entries[{category_id}])?>
<?php endif; ?>
{/exp:channel:categories}
First, we’ll define an array ($entries). Using the channel:entries tag — without a category="" parameter — we’ll fill that array with entries grouped by category. After putting the template chunk for an entry in the $entry variable, we’ll loop through each related category and add the entry to $entries. What we end up with, is a nested array with all the entries in the right order, grouped by category_id.
To output the entries, we’ll simply use the channel:categories tag to display each category. We then check if there are entries set in the $entries array for that category_id. If there are, we’ll echo them to the page after implode-ing them to a string. All done.
Performance FTW
So, exactly how many queries did we save using this method? I reloaded the page using the above code, with 5 categories and 7 entries: 29 queries. That’s right, 16 less than the nested method. How many queries would it take if there are 20 categories with 200 entries? 29.
]]>PHP in templates
My presentation slash workshop was about using PHP in templates, but also covered EE’s template parse order. Prior to the presentation, I dove right into EE’s template class and created a little cheat sheet as a handout people could refer to during my talk. I think it went fairly well and judging from the feedback I’ve read and heard, my audience felt the same way. Here are the slides, if you haven’t already seen them on SlideShare:
Next up
The next EECI conference will be held, like the first edition, in my home town Leiden. Robert already cooked up some excellent speakers and there will also be a so-called DevDay on October 1st (also my birthday, coincidently). What will happen on the DevDay is yet to be announced, but one thing’s for sure: I’ll be there eating cake.
]]>Of course, the best way to explore a foreign country is with the help of the locals. So here’s what I thought would be fun… Why not ask some fellow web geeks if they mind having me and my girlfriend over? I think it would be a fantastic way to meet people and see the country.
To be precise, we will be traveling through California from June 3rd till June 17th, and we would love to stay one or two nights. Drop me an email if you live somewhere around or in between SF and LA and you’re up for it: low@loweblog.com
]]>Template tags
The secret lies in Low Variables’ template tags: {exp:low_variables:parse}. Apart from parsing variables early (like path.php vars) or late (like user defined template vars) in the parsing order, you can parse Low Variables using the template tags, which allows you to do extra stuff apart from just a simple string replace.
For example, in the case of multiple valued variables, you can loop through the values. This means you could create a simple navigation menu that your users can manage.
Create a Select variable
First you need to create a variable with type Select. In this example, we’ll name the variable low_site_menu. You can turn early parsing off, since we’re going to use the template tags to parse it. In the Options field, we’ll add the menu items, putting each item on a new line and separating paths and labels with : . For example:
/ : Home
about-us : About us
services : Services
news : News
contact : Contact
pages/copyright : Copyright
Next, we’ll allow multiple values to be selected and select the Drag and drop lists as interface. This means your user can turn off any menu item, as well as sort them in a preferred order.

Edit your template
In your template, add the following code:
<ul id="nav">{exp:low_variables:parse var="low_site_menu" multiple="yes"}
<li><a href="{path="{value}"}">{label}</a></li>{/exp:low_variables:parse}
</ul>
That’s it! You could even enter full urls as values and omit the {path=""} variable, so external menu items are possible as well. This approach is very efficient; I compared it to using a {exp:weblog:categories} tag instead, and saved up to 3 queries per request, depending on caching settings.
Custom header image
In this example, we’ve defined the default header image in a CSS file. We’ll override that by adding a <style> block to our templates. But first, we need to create a variable with type ‘Select Files’. Let’s name the variable {my_custom_header}. Select the upload destination(s) that the user can choose images from and check the ‘Allow uploads’ checkbox.
Then, just add this code to your templates:
<style type="text/css">
#header {background-image:url({my_custom_header})}
</style>
Random masthead image
For a random image, create a similar variable, for example {my_custom_masthead}. Enable early parsing and allow for multiple files to be selected. We need early parsing to be enabled, because we’re using the variable as input for the Low Random plugin.
Here’s how it would look in our templates:
<img src="{exp:low_random:items}{my_custom_masthead}{/exp:low_random:items}" alt="" />
That’s all there is to it; custom and random images with Low Variables.
]]>Multilingual sites in ExpressionEngine 1.6.x often use a Path.php variable to determine the current language. Something like this, perhaps:
$global_vars['country_code'] = 'es';
Let’s take this approach and apply it to Low Variables.
Create a variable for each piece of text that needs to be translated. Make sure Early Parsing is turned off for these variables. In my example, I created these: {low_snippets_payoff_en}, {low_snippets_payoff_es}, {low_snippets_footer_en} and {low_snippets_footer_es}.
Then, all you have to do in your templates, is add these variables, combined with the Path.php variable we made earlier:
<p id="payoff">{low_snippets_payoff_{country_code}}</p>
<!-- More code -->
<p id="footer">{low_snippets_footer_{country_code}}</p>
But don’t stop there; all static bits of text throughout your templates can be treated like this. Your users will hug you and send you flowers ’cause they can now edit them without the heartache!
]]>Elwin and I have agreed that I will take over development for these add-ons. I’m not sure exactly when, but you can expect something like a Low Reeorder or Low Navigator in the near future. If you’re using any of Elwin’s add-ons and want to see them ported to 2.0, let me know, along with any feature requests. I’ll do my best to add a little Low-sauce while I’m at it. Thanks to Elwin for not letting his work wither and die — there’s a bottle of Pouilly-Fuissé here with your name on it, buddy!
]]>Let’s take a look at the current home page of the sandbox site. There’s a heading that reads “Latest news”. Below that are two articles. There’s also a sidebar with some contact information. In order to customize the home page, we’ll need to add a couple of variables. Here’s what I added:
{low_home_heading}: to edit the heading. Variable type: Text Input.{low_home_categories}: so the user can select categories from which to pull entries. Variable type: Select Categories (see image below).{low_home_status}: so the user can select the statuses of entries to show. Variable type: Checkbox group.{low_home_limit}: so the user can select how many entries are shown on the home page. Variable type: Radio group.{low_home_no_results}: the message shown if no entries match the given criteria. Variable type: Textarea.{low_home_sidebar}: option to show or hide the sidebar. Variable type: Checkbox.
{low_home_heading} and {low_home_no_results} do not need early parsing to be enabled, but the others do. They are used as input for the {exp:weblog:entries} tag in the template. {low_home_sidebar} is used as a global conditional. Here’s how the template might look:
<div id="content">
<div id="primary">
<h2>{low_home_heading}</h2>
{exp:weblog:entries category="{low_home_categories}" status="{low_home_status}" limit="{low_home_limit}"}
<div class="article">
<h3>{title}</h3>
{body}
</div>
{if no_results}
<p>{low_home_no_results}</p>
{/if}
{/exp:weblog:entries}
</div>
{if low_home_sidebar == 'y'}
<div id="aside">
<!-- Sidebar here -->
</div>
{/if}
</div>
There you go! You can use Low Variables to customize your template tags without the heartache!
]]>