The Mijingo Blog

Latest news, updates, free tutorials, and more from Mijingo.

Craft 3 Remote Volumes with AWS S3

by Ryan Irelan

Watch as Ryan converts a Local Folder Assets Volume to Amazon S3. The video includes setting up an S3 bucket, creating a IAM policy, group, and user.

Getting Started with Craft Plugin Development

by Ryan Irelan

I spent 90 minutes talking with Andrew Welch about Craft plugin development. This was live streamed, which is why the video is different than what you usually see from Mijingo.

We covered:

  • Why and when you want to create a plugin
  • Easiest way to start your first plugin
  • Moving from a project plugin to a public plugin
  • Craft modules
  • Andrew’s awesome PhpStorm tips



If you like videos from Mijingo, please subscribe to the YouTube channel.

When is Craft 3 Coming Out?

by Ryan Irelan

April 4, 2018

See the Craft 3 Launch FAQ for more.

I’ve already updated Craft Essentials for Craft 3 and there are more updates to come. It’s the best and easiest way to learn Craft CMS.

Course Updates for Craft 3

by Ryan Irelan

Last week Pixel & Tonic released Craft 3 RC1, the first release candidate after the beta period. The final release of Craft 3 won’t be until April 2018.

The new version includes some improvements and minor changes to how we build sites with Craft but the general approach we all use (and the one I teach) will not change. There will be code changes here and there but it’s not a “rip it up and do it again” type of upgrade.

Where does this leave Mijingo’s Craft courses?

As of right now, the courses are still the best way to learn Craft. The general approach to building sites with Craft has not changed.

Here’s my plan to update them for Craft 3:

  • Updates to courses for Craft 3 will be free for all students who purchase the courses. The only exception is the Craft Plugin Development course.
  • I will redo Up and Running with Craft first because it is the one most impacted by the changes.
  • I will redo Fundamentals of Craft Commerce as soon as Pixel & Tonic releases the Commerce 2 beta and I can review what I need to update in the course.
  • I will evaluate the remaining courses for Craft 3’s impact on the material and amend or update accordingly.
  • I will keep you updated as I go.

Where does this leave you?

If you need to learn Craft now, then now is still the time to learn it. Grab a copy of Craft 2, a copy of Craft Essentials, and get to work.

After you complete the courses, then you can get acquainted with Craft 3 using my free lessons.

Major software releases are always a juggling act but as the official training partner for Craft we’re in a good spot going forward.

Happy learning!

Hashing Redirect Params in Craft

by Ryan Irelan

Back in version 2.6.2945 of Craft 2, Pixel & Tonic introduced the ability to require hashing of the redirect parameters that are set in forms (like when you sign in or sign up).

They introduced this enhancement to make Craft more secure. There is a potential Denial of Service (DoS) security issue with in-the-clear form data. In the example of a redirect parameter, this could allow someone to redirect the user to something other than what is specified in the hidden form element.

We need to protect our form data. Let’s learn how to do that, starting with Craft 2.

Protecting Return Parameters in Craft 2

The solution to protecting the redirect parameter in Craft 2 is two-fold:

  • In Craft 2.5.2750, the developers introduced the hash filter, which takes the input and hashes it using a HMAC (Hashed Message Authentication Code). On the back-end, while processing the request, the developer can validate the hash using a validateData method.
  • In Craft 2.6.2945. the developers introduced a configuration setting that forced each request with a redirect parameter to be hashed. This new config setting is called validateUnsafeRequestParams and it takes a boolean value. When set to true then the unsafe parameters (which is just the redirect parameter and perhaps some third party plugin parameters).

Together, these will protect your form redirect parameter from any security issues.

Let’s use the login form as an example:


<form method="post" accept-charset="UTF-8">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="users/login">
    <input type="hidden" name="redirect" value="{{ '/profile' | hash}}">
    <h3><label for="loginName">Username or email</label></h3>
    <input id="loginName" type="text" name="loginName"
        value="{{ craft.session.rememberedUsername }}">

    <h3><label for="password">Password</label></h3>
    <input id="password" type="password" name="password">

    <label>
        <input type="checkbox" name="rememberMe" value="1">
        Remember me
    </label>

    <input type="submit" value="Login">
</form>

We have our standard hidden field with the redirect name and the value is populated with a Twig output tag, a string for our redirect location. We use the hash filter on the string to hash it.

If we load this in the browser we should see that the string is hashed:


<input type="hidden" name="redirect" value="58c6ace5c2af26ac04772d20aea67659590b9441/profile">

Now, we need to require all redirect parameters to be hashed using the config option.

In our craft/config/general.php file we add the following item:


'validateUnsafeRequestParams' => true,

And now when we go to submit our form, it’ll validate the hash we pass as the redirect parameter and process the request.

If for some reason we have this enabled but we don’t hash our redirect parameter, Craft will return a error.

Protecting Redirect Parameters in Craft 3

Protect the redirect parameter in Craft 3 is a simpler process because Craft 3 requires hashing of all redirect parameters. The validateUnsafeRequestParams config setting we have in Craft 2 is gone. You can’t opt in (and you can’t opt out).

The only step we need to do in Craft 3 is to set our redirect hidden field in the form we’re using and pass it through the hash filter.


<input type="hidden" name="redirect" value="{{ '/profile' |  hash}}">

And what happens in Craft 3 if don’t hash the redirect parameter?

In the case of the login form, the login routine will proceed (successful if the username and password are correct) but the redirect will fail. The value of the redirect parameter will not be honored.

The Takeaway

Whether we are using Craft 2 or 3, we should be hashing the redirect parameters. It’s a good security practice in Craft 2 and by doing so you’ll be making your sites even more ready for a Craft 3 upgrade.

Global Sets in the Craft Element API

by Ryan Irelan

This article covers both Craft 2 and Craft 3. The Craft 3 changes are at the bottom of the article.

I’ve used the Element API in Craft CMS to share data with a Vue.js app, create a headless CMS for a blog, and to share common information among a group of related sites.

The Element API makes it easy to expose your Craft-powered website’s data via JSON so other applications can consume it and use it.

The third example is what we’ll work on in this article.

I have a network of related sites that all have the same footer containing a list of links (for a “network” of sites). I want to manage this set of links with the Craft CMS installation of the anchor site and share the links with the other sites in the network.

I’m storing this set of links and display information (like headers and new column indicators) in a Global Set called Network (with the handle network).

The Network Global Set has a single Matrix field called Sites (sites) with this setup:

  • Site (site)
    • Site Name (siteName), Plain Text
    • Site URl (siteUrl), Plain Text
  • Section Header (sectionHeader)
    • Section Title (sectionTitle), Plain Text
  • Column (column)
    • New Column (newColumn), Lightswitch

I’m organizing the Sites into sections (via a Section Header). I can control when a new column is created using g the New Column Lightswitch field. I want to ensure the same exact layout across all sites, so it made the most sense to include layout data in the Global Set.

In my video lesson on the Element API, I only worked with Entries. In this example we need to expose the data in a Global Set. The approach is similar but instead of using an Entries element type we use a GlobalSet element type.

Let’s code the Element API and see how it works.

Coding the Element API for Global Sets

If you’re not familiar with the basics of using Element API in Craft, please first review my video lesson on the topic.

We start with a basic Element API wrapper:


<?php
namespace Craft;

return [
    'endpoints' => [
    ]
];

We define our first endpoint. It can be whatever we want, but let’s call it api/network.json.


<?php
    namespace Craft;
    return [
        'endpoints' => [
            'api/network.json' =>
            [
                    
            ],
                
        ]
    ];

We need to decide what we want to return. Our network data is in a Global Set, so we need to set the elementType for this endpoint to ElementType::GlobalSet.

Then set the criteria for retrieving the Global Set by defining the handle of the set we want.

   
<?php
    namespace Craft;
    return [
        'endpoints' => [
          'api/network.json' =>
          [
            'elementType' => ElementType::GlobalSet 
            'criteria' => ['handle' => 'network'],
          ]
                
        ]
    ];

Now that we have our data, we need to transform it into a format that is acceptable as JSON. To do that we use a transformer. In the transformer, we create an anonymous function which passes in the GlobalSetModel so Craft knows the data model it should use.

   
<?php
    namespace Craft;
    return [
        'endpoints' => [
          'api/network.json' =>
          [
            'elementType' => ElementType::GlobalSet 
            'criteria' => ['handle' => 'network'],
            'transformer' => function(GlobalSetModel $globalSet) 
            {
                // our data here
            }
          ]
                
        ]
    ];

Inside of the transformer function we define our data as we want it to appear in the JSON output.

   
<?php
    namespace Craft;
    return [
        'endpoints' => [
          'api/network.json' =>
          [
            'elementType' => ElementType::GlobalSet 
            'criteria' => ['handle' => 'network'],
            'transformer' => function(GlobalSetModel $globalSet) 
            {
              $networkBlocks = [];
              foreach ($globalSet->sites as $block) {
                switch ($block->type->handle) {
                  case 'site':
                    $networkBlocks[] = [ 
                     array(
                       'siteName' => $block->siteName,
                       'siteUrl' => $block->siteUrl,
                     )
                    ];
                  break;
                  case 'sectionHeader':
                    $networkBlocks[] = [
                      'sectionTitle' => $block->sectionTitle,
                     ];
                  break;
                  case 'column':
                    $networkBlocks[] = [
                      'newColumn' => $block->newColumn,
                    ];
                }   
              }

            }
          ]
                
        ]
    ];

We define an empty array called $networkBlocks and then we fill up this array with our data.

At foreach ($globalSet->sites as $block) { we iterate over each site row in the Matrix field. For each one we are checking the block type using a switch statement.

If the block has more than one field, we assign its data to a nested array because we want those values to stick together. The keys we choose (e.g. siteName and siteUrl) will be used in the JSON.

We add the single field blocks to the main array with the keys set to the name we want to appear in the JSON.

To get our newly transformed data out, we need to return the array from the transformer function.

   
<?php
    namespace Craft;
    return [
        'endpoints' => [
          'api/network.json' =>
          [
            'elementType' => ElementType::GlobalSet 
            'criteria' => ['handle' => 'network'],
            'transformer' => function(GlobalSetModel $globalSet) 
            {
              $networkBlocks = [];
              foreach ($globalSet->sites as $block) {
                switch ($block->type->handle) {
                  case 'site':
                    $networkBlocks[] = [ 
                     array(
                       'siteName' => $block->siteName,
                       'siteUrl' => $block->siteUrl,
                     )
                    ];
                  break;
                  case 'sectionHeader':
                    $networkBlocks[] = [
                      'sectionTitle' => $block->sectionTitle,
                     ];
                  break;
                  case 'column':
                    $networkBlocks[] = [
                      'newColumn' => $block->newColumn,
                    ];
                }   
              }

              return ['network' => $networkBlocks];

            }
          ]
                
        ]
    ];

Let’s test the API and see what we get. If we coded it properly, we should see something like this at, for example, yoursite.com/api/network.json:



    {
      "data": [
        {
          "network": [
            {
              "sectionTitle": "Insight"
                },
                [
                    {
                        "siteName": "Personal Blog",
                        "siteUrl": "http://ryanirelan.com/"
                    }
                ],
                    {
                        "sectionTitle": "Training"
                    },
                [
                    {
                        "siteName": "Mijingo",
                        "siteUrl": "https://mijingo.com"
                    }
                ],
                [
                    {
                        "siteName": "Up and Running with SVG",
                        "siteUrl": "http://svgtutorial.com"
                    }
                ],
                [
                    {
                        "siteName": "Craft CMS Essentials",
                        "siteUrl": "http://craftcmsessentials.com"
                    }
                ],
                {
                    "newColumn": "1"
                },
                {
                    "sectionTitle": "Running"
                },
                [
                    {
                        "siteName": "Ryan Runs",
                        "siteUrl": "http://www.ryanruns.com"
                    }
                ],
            ]
        }
      ],
      "meta": {
    "pagination": {
      "total": 1,
      "count": 1,
      "per_page": 100,
      "current_page": 1,
      "total_pages": 1,
      "links": []
    }
      }
    }

With our Global Set data exposed as JSON via the Element API, we’re now ready to pull it into our target sites.

Making it Work in Craft 3

To get this same approach to work in Craft 3 (in RC1 as a I write this), we need to make a couple adjustments.

First, the file name inside of the config directory should be element-api.php instead of the elementapi.php name in Craft 2.

Second, at the top of the file we no longer need to specify the Craft namespace but instead specify the element type (or types) class name we plan to access. In our case we only need to access a Global Set, so the top of our file looks like this:


<?php
  use craft\elements\GlobalSet;

If we also want to fetch and return entries we’d would need to specify the Entry class name, too.

Next, we need to change where we refer to the Element Type and replace that with the Element Type class name we just added.


<?php
    use craft\elements\GlobalSet;
    return [
            'endpoints' => [
                'api/network.json' =>
                [
                    'elementType' => GlobalSet::Class
                    'criteria' => ['handle' => 'network'],
                    'transformer' => function(GlobalSet $globalSet) 
                    {

We also change the transformer to use GlobalSet instead of GlobalSetModel.

Everything else should work as-is!

If you need some assistance with Craft 3’s implementation of the Element API, you can refer to the official documentation.

11 Things You Need to Know About Craft 3

by Ryan Irelan

There are dozens of changes to Craft in version 3 but below I’ve compiled the eleven things you need to know to have a smooth transition from Craft 2 to Craft 3.

Ready? Let's go.

1. Installable via Composer

If you installed Craft 3 during the beta period then you will know that Craft can now be installed with Composer. A nuisance to some but a big step up for others, Composer will make it easy to manage dependencies in Craft.

So how do you install Composer? This video walks through the process:


Note: The final release of Craft 3 will allow a non-Composer installation.

After you have Composer installed, you are ready to install Craft 3.

Follow the instructions in this video to get your first Craft 3 installation going:


Need help upgrading a Craft 2 site to Craft 3? Watch this video

2. Uses Twig 2

Craft 3 uses Twig 2. This update to Twig is, for the most part, a clean-up release. Here are a few important things to know about Twig 2 with regards to Craft:

  • Twig 2 Requires PHP 7 (and so does Craft 3)
  • Your current templates should work as-is with Twig 2. There is some deprecated template code but that’s related to Craft services, not Twig.
  • Twig slightly changed how macros are handled. All macros defined in-template must be imported explicitly in each template in which you want to use them (including “included” templates). See the docs for more information on macros.

3. Access to Craft service APIs in your templates

As of Craft 3 you now have access to the Craft service APIs right inside of your templates. Previously, Craft made available some special template functions that made some of the service APIs available.

Many of those template functions are going away in Craft 3 in favor of using the new service API access.

These template functions were mostly just Twig variables that exposed the data via an existing function. So instead of doing that we just get direct access to the function itself.

There is no PHP allowed in Craft templates, so previously if you wanted to access something in the backend of Craft you had to use a plugin.

Using a plugin is still a good idea if you have a significant amount of features you need to achieve, but for simple one-off things, having access to the Services inside of your template is going to be a game changer.

Here’s a look at how you can use this new functionality in your templates:


4. Multi-site Support

Another new feature in Craft 3 is multi-site. This was a popular feature when it was first announced but there was some confusion about it so let’s clear things up.

The Craft 3 multi-site feature allows you to handle multiple sites of content right from the Craft control panel. This could be a multi-language site, where there’s a different version of the site for different languages, or multiple sites with similar content (like micro sites for product lines).

Note: this feature is an enhancement of and replaces Locales in Craft 2.

Here's a walk-thru of using the new multi-site feature:


5. Better Debugging

The Yii Debug Toolbar is a new feature in Craft 3 that allows you to have a constant toolbar at the bottom of your front-end and control panel pages.

This toolbar gives you access to important debugging information including items that aren’t specific to Craft.

Here’s how it works and how you enable it:


6. Command Line Interface

When you are done installing Craft with Composer, you'll notice a little message at the end, just before the new command prompt, encouraging you to use the Craft setup command.

Craft 3 offers a new way to set up the site, which replaces the normal set up you do via the web browser.

So, why is this important?

  • Keeps you right in the terminal after installing
  • Possible to script the setup process--maybe part of a bigger routine where you're installing and setting up a new installation.
  • It automates the populating of your .env file for the site's database connection.

The craft CLI offers several options, but we're only going to concern ourselves right now with setup command.

Here’s how it works:


7. Hash Redirect Parameters

Back in version 2.5, Pixel & Tonic introduced a hash filter and later in a 2.6 release the ability to require hashing of the redirect parameters that are set in forms (like when you sign in or sign up).

They introduced this enhancement to make Craft more secure. There is a potential Denial of Service security issue with in -the-clear form data. In the example of the redirect parameter, this could allow someone to redirect the user to something other than what is specified in the hidden form element.

In Craft 3, however, the hashing of redirect parameters is required.

Here’s an overview of how that works:


8. Always use .all()

In Craft 2, we might do something like:

{% for entry in craft.entries.section('news') %}
       {{ entry
.title }}
    {
% endfor %

We iterate over the element query directly. Behind the scenes Craft knew we wanted that actual data so it calls find() for us automatically.

Based on a problem discovered with Twig’s loop variables and Craft, the Craft team decided to just force the usage of .all() and deprecate the usage of iterating over the element query without explicitly calling for the results.

What does this mean?

We need to now use all() on every element query in Craft 3. If you don’t it will still work but you’ll receive a deprecation error in your log (and it’ll break in Craft 4).

So the above code is now:

{% for entry in craft.entries.section('news').all() %}
       {{ entry
.title }}
    {
% endfor %

Here’s a hands-on review of this:


9. Use one() instead of first()

In Craft 3 the first() method to execute an Element Query is now deprecated in favor of one(). The new method will return the same thing as first() (the first matching element) and also return null if there are no matches.

So, this code:

{set entry craft.entries.section('news').first() %}
    {{ entry
.title }} 

Will now need to be written as:

{set entry craft.entries.section('news').one() %}
    {{ entry
.title }} 

10. Support for PostgreSQL

You hatin’ on MySQL or maybe your systems admininistrator thinks PostgreSQL is better? Now you can run Craft off a PostgreSQL database server.

11. Remote Assets are Now Plugins

Remote Assets Volumes (they’re called Volumes in Craft 3) now require a free, third-party plugin. The default installation of Craft only includes Local Volume support.

Until the Craft Plugin Store is available, you can download the Remote Volumes plugins from their Github repositories:

Is that it?

Well, that’s 11. But if you want even more here’s a big list of changes from Craft 2 to Craft 3.

How to Install Craft 3

by Ryan Irelan

Now that Craft 3 is available (as of this writing it is still in public beta), it’s time to learn how to install it.

There is one pre-requisite to installing Craft 3:

  • Install and configure Composer

What’s Composer? It’s a dependency management tool for PHP that helps manage software needed for individual projects (as opposed to traditional package managers that let you install software on your computer or server globally.)

Don’t have it installed yet? Watch my video install Composer.

After that you’re ready to install Craft 3. Here’s how:

 



What is the Element API in Craft CMS?

by Ryan Irelan

The Element API is a first-party plugin by Pixel & Tonic that allows you to create an API for sharing your data from Craft CMS. The responses are formatted as JSON (what is JSON?).

Using the plugin you can create an API that exposes Craft Elements via a JSON-formatted responses. The API only is read-only. You cannot write to Craft using this API and there’s no authentication built in. Be careful what you share!

The Element API is made up of the following pieces:

  • The plugin package itself
  • The elementapi.php file you have to create
  • The code in the file that defines the endpoints and the exposed data

To use the Element API plugin you need to meet these requirements:

  • Craft CMS installed and populated with data you want to expose via the API
  • PHP 5.4 or later (different than the current requirement for Craft CMS)

Installing the Element API plugin is like installing any other Craft plugin: drag the plugin file to the plugins directory and then install the plugin via the Craft Control Panel.

Watch the Free Lesson

How to Create an API with Craft CMS

by Ryan Irelan

In a recent lesson, I walked through how to use the Element API Plugin from Pixel & Tonic to create a JSON API that shares your website’s data (only that data which you choose, of course) for consumption by another website or service.

The free lesson is a fundamental approach to building a read-only API using the default ElementTypes (entry, category, asset, etc) in Craft. As long as you follow my steps, you can get an API up and running quickly.

Toward the end of the lesson, we also learn how to expose your Craft Commerce order data via an API so you can have an outside tool (like a Goole Spreadsheet or reporting tool) ingest it and use it create some sort of report.

Watch the Lesson

Learn Craft Commerce

by Ryan Irelan

It used to be that doing e-commerce work was something I would talk a client out of or offload to another company or a hosted platform. I didn’t want to touch it. At all. Too much risk. But this caused me to lose business and it usually meant a less-than-ideal solution for my clients or customers. Thankfully, the e-commerce solutions have gotten a lot better.

One those solutions is Craft Commerce, a first party plugin for the Craft CMS.

With tools like Craft Commerce, most web developers can put together a powerful and flexible e-commerce system for any website. And the store is hosted right on the website, not on some third party platform you can’t control.

In my full-length course Fundamentals of Craft Commerce I teach you everything you need to know to get started using Craft Commerce.

 

This new course follows the same proven learning process you expect from my Mijingo courses. By the end of the course you will be ready to implement your first e-commerce website!

Start the Course for Free

New Course: Flexible Twig Templates in Craft

by Ryan Irelan

A new course is now available for the Craft CMS series: Flexible Twig Templates in Craft.

In this course Ryan teaches the Flexible Template Stack, an approach put together by developer Anthony Colangelo. The Flexible Template Stack in Twig and Craft allows you to have reusable templates that can render content from any section of the site. This is a setup you can use over and over again on your Craft-powered projects.

Start the Course for Free

New Lesson: Installing Craft

by Ryan Irelan

I posted a new lesson on installing the Craft CMS. This lesson is an excerpt from my Up and Running with Craft course.

Watch the Lesson

New Course: Up and Running with Craft

by Ryan Irelan

Today I released a brand new course: Up and Running with Craft. This is a complete redo of its predecessor: Learning Craft.

The new course has the same goal: to help you learn the skills you need to start building websites with the Craft CMS. It does this over the course of nearly 4 hours and 21 videos.

Get Started Learning Craft

Craft Plugin Development Workbook

by Ryan Irelan

Ben Croker, the author of Craft Plugin Development, created a follow-up to his video course in the form of a workbook.

The digital workbook that builds on the plugin development course by gently guiding you along as you build another plugin on your own. Ben set up this workbook to build on and reinforce what you learned with him in the video course.

Let me take a moment to explain why a follow-up like this is important (for those of you who’d rather skip the explanation, you can go right to the workbook page).

When you learn something new, like plugin development for Craft, there are three stages that help the information you learn stay stored in your long term memory.

The first stage is watching and taking in the new material, like you would with a video course.

The second stage is watching again and engaging with the new material by, for example, coding along with the video and applying what’s being taught.

The final stage, and the one so many people skip, is applying the material you just learned again but on your own, using your own information and research to work around problems or challenges. It’s in this third and final step that real mastery starts and your brain stores the information in long term memory.

It’s the difference between understanding how Craft plugins are developed and knowing how to do it without hesitation.

Ben’s new workbook is the third step. He guides you a bit but the workbook nudges you toward solving problems on your own (with helpful links off to documentation) so you can loosen the training wheels and let them fall to the side.

The workbook is available now. Watch Ben’s introduction video to learn more.

 

Get the Workbook

Special Sale: Craft Starter Pack 50% off

by Ryan Irelan

This sale has ended. But you can still get both courses in the Starter Pack for 10% off!

In conjunction with my friends at Pixel & Tonic, I am celebrating the release of Craft 2.5 by temporarily marking down the price of the Craft CMS Starter Pack by 50%.

Yes, you heard that right. 50% off. Get started learning Craft for only $49.99.

I like to call this Starter Pack the one-two punch for learning Craft. Now you get more punch for your money.

Wait, maybe I should put it another way.

Regardless, the Craft Starter Pack is on sale starting now.

Here’s what you’ll get:

  • About 5 ½ hours of professional training videos
  • 21 separate videos
  • Code downloads so you can follow along
  • Streaming or download access to all videos (forever)
  • The knowledge you need to get started building websites with Craft.

Important Note: The next update to the Learning Craft course (the first course in the Starter Pack) will be free for everyone. What I am saying is you should get this now because it’s a helluva deal.

I want to save $50

New Lesson: Craft 2.5 Quick Look

by Ryan Irelan

Today the new version of Craft came out and I recorded a short lesson to run through the 3 major features of the latest release from Pixel & Tonic. There’s lots more to Craft 2.5 than what I covered but this is certainly the highlights, especially for content authors. Watch the Lesson

New Lesson: Creating a Contact Form in Craft

by Ryan Irelan

There’s a new free lesson available over in Lessons area that covers how to build a contact form in Craft.

In the lesson, we add the form to our Crafty Brewery sample site so customers can contact us with questions about our brew products and recipes.

We’ve been building the Crafty Brewery site over the course of several videos in the Learning Craft video course. If you want to learn more about Craft, I encourage you to check out that series of videos.

During this lesson, here’s what we’ll learn:

  • How to install and configure the Craft first party Contact Form plugin.
  • How to code the Contact form template
  • How to add a honeypot CAPTCHA to the form.

Watch the Free Lesson

Filters in Twig and Craft

by Ryan Irelan

Filters in Twig and Craft allow you to alter the contents of a variable.

This could be a variable you set right in the template or one that is part of the data output provided by Craft (like when retrieving and looping through section entries).

Filters are applied right in the output tag, like this:


{{ variable | filter }}

and separated using the pipe character.

Here’s an example where we want to title case the string that is assigned to the variable.


{% set page_title = "an important news story" %}
{{ page_title | title }}

When outputting the contents of the page_title variable, we are running it through the title filter in Twig. This filter adjusts the string to title case, so every word starts with a capital letter.

It will output:

An Important News Story

Another very practical filter that you might use frequently is trim. This filter strips out whitespace at the beginning and end of a string.


{% set page_title = " an important news story " %}
{{ page_title | trim }}

That will remove the whitespace at the beginning and end of the string.

You can also trim specific characters by specifying them in parentheses.


{{ page_title | trim('.') }}

The previous example outputs:

an important news story

which is missing the title casing we did before.

Let’s add in both filters together. We do that by chaining together them with pipes.


{{ page_title | trim | title }}

That outputs:

An Important News Story

Craft-specific Filters

Pixel & Tonic created some special filters just to use in Craft. These filters won’t be listed in the Twig documentation, and, similarly, the Craft documentation won’t list all of the Twig filters. This is a situation where you’l need to refer to two different sets of documentation.

Here are a couple Craft filters that I find interesting:

  • markdown - processes the string passed to it using the Markdown library.
  • group - allows you to group array items together based on a common property that you define. The Craft docs have a great example of sorting the entries returned from a Craft section by the year of the entry.

Ready to learn more about the Craft CMS?

My Craft Starter Pack is 4 ½ hours of premium learning that will get you started building sites with Craft for yourself, your company, or your clients.

Get Immediate Access

Learning Craft: New Video on Categories Added

by Ryan Irelan

Today I added a new video to the Learning Craft course. The new video covers how to use categories in Craft and it’s a free update for everyone that has the Learning Craft course in their library.

In the Matrix videos I added to the course earlier this year, I started using the Crafty Brewery sample site. The categories video adds to this sample site.

During the 21 minute video we add the ability to organize beer brewing recipes by beer style, using Craft categories to manage the styles.

If you already purchased the course the new video is waiting for you in your Course Library. If not, you can grab the course now or the Craft Starter Pack.

Next Page

What are our customers saying?


"Just purchased your Flexible Twig course. Love it!"
Tyler Morrison
"Been enjoying @mijingo 's Learning Craft video tutorials. Feeling like I've got a good basic understanding of #craftcms Very impressive"
Laura Montgomery
"I bought your Craft Starter Pack a year and a half ago. Worth every dollar. In fact, I would've paid twice as much for it, because you saved me so much time."
Timothy Ingram
"Ben's knowledge of Craft combined with his relaxed and informal teaching style makes for a great learning experience."
Steve Abraham
"Ben puts a lot of thought into his teaching approach and has the ability to explain complex concepts in a way that just make sense"
Gareth Redfern
"Ben is great at taking a complex subject and breaking it down in a way that you can wrap your mind around. I thought that plugin development was something I would never understand, and happily Ben proved me wrong!"
Jonathan Melville
"I really appreciate all the videos and writing you have done. Your work has given me a jump start on my front end development business."
Shan Ricciardi

Perfect for Small Teams & Companies


Mijingo's courses are perfect as the training curriculum for both small teams and entire companies.

Our courses are offered in Team Packs (up to 5 people) and Company Packs (up to 25 people), so you can make one simple, fast purchase to train your entire staff.

Prices are listed with each course. Need more than 25 or something custom?

Send Your Requirements
Team Pack2-5 People
Company Pack6-25 People
Custom Pack25+ People