Download EE 2 Docs Download EE 1 Docs
ExpressionEngine

2.9.0 User Guide

Relationships Field

Introduction

Relationships are an extremely powerful tool that allow you to connect Entries in one channel to those in another one, or even to other entries in the same channel. This ability allows you to store very complex content in your channel entries.

To create a Relationship field that connects one channel’s entries to another, go to the fieldgroup you wish to add the relationship to and hit “Create New Field”. Once on the field editing page, select “Relationship”. In the “Relationship Field Options” area, below the usual field settings, you will be presented with a choice of which channel or channels you want to relate to. Select the channel or channels you wish.

You may, also, choose to filter entries by category, author, status, whether they are expired or future. The most important setting to notice is the checkbox just above the submit button. This one asks whether you want to allow multiple relations. If you check yes, you will be able to relate more than one entry to the parent entry. If you leave it unchecked, you will only be able to relate one.

Once you have built your relationship fields, building the templates is surprisingly straightforward. Building templates using your related entries is the primary focus of this page. So if you’re ready to tackle it, read on.

Changed in version 2.6: Relationships was completely rewritten for this version, adding the ability to create multiple relationships for each entry and introducing a friendly new tag syntax. The template tags described here are not compatible with previous versions.

Examples

The Pizza Shop

Let’s start with a very simple example. You’ve been tasked with building a website for a small chain of local pizza joints. These pizza places share a menu of specialty pizzas, but each individual store manager gets to decide which pizzas will be available on any particular week. You need to make a website for the whole chain with store pages for each store to display that store’s menu for the week.

Since this is a template writing tutorial, we’ll go ahead and layout the channels for you:

Stores
        title                           Text Input
        url_title                       Text Input
        address                         Textarea
        phone                           Text Input
        specialty_pizzas        Relationship (to Pizzas, multiple)

Pizzas
        title                           Text Input
        url_title                       Text Input
        description                     Textarea
        ingredients                     Checkbox

Child Entries: Displaying the Stores and their Menus

First things first. We need to write a page to list each Store and which pizzas they have to offer. We do that with this template:

{exp:channel:entries channel="stores"}
        <h1>{title}</h1>
        <p>Phone: {phone}</p>
        <p>Address: {address}</p>
        <h2>Specialty Pizzas</h2>
        {specialty_pizzas}
                <h3>{specialty_pizzas:title}</h3>
                <p>{specialty_pizzas:description}</p>
                <p>{specialty_pizzas:ingredients}</p>
        {/specialty_pizzas}
{/exp:channel:entries}

We start with the standard {exp:channel:entries} tag, pulling from the Stores channel. For each Store entry we display the Store name, the Store’s phone number and its address. Then we display which specialty pizzas are available:

<h2>Specialty Pizzas</h2>
{specialty_pizzas}
        <h3>{specialty_pizzas:title}</h3>
        <p>{specialty_pizzas:description}</p>
        <p>{specialty_pizzas:ingredients}</p>
{/specialty_pizzas}

The {specialty_pizzas} tag is a Relationship variable tag. Since it is a relationship that can take multiple entries, it is a looping tag pair. So these three lines, contained in the pair, will be looped over:

<h3>{specialty_pizzas:title}</h3>
<p>{specialty_pizzas:description}</p>
<p>{specialty_pizzas:ingredients}</p>

The variables will be replaced for each Pizza entry that is attached to the current Store entry. In those lines {specialty_pizzas:title} will be replaced by the title of the current Pizza entry, {specialty_pizzas:description} will be replaced by its description and so on.

Notice that what we’re doing here is prefixing the names of the variables in the Pizza channel with the name of the Relationship field that relates the Store channel to the Pizza channel. We call this namespacing and it’s a very powerful tool. This is what allows us to access the variables of the related entries, even though they may be the same as those of the parent entries.

Inside the {specialty_pizzas} tag pair, you can use {title} to display the title of the current Store entry and {specialty_pizzas:title} to display the title of the current Pizza entry. This means we can nest relationships as deeply as we want to with out having to worry too much about naming collisions.

Parent Entries: Which Stores have Which Pizza?

Another template you might want to make is a page for each pizza where you give a description of the pizza, list its ingredients and show which stores currently have the pizza available. You can do this with the {parents} tag. Like so:

{exp:channel:entries channel="pizzas"}
        <h2>{title}</h2>
        <p>{description}</p>
        <p>{ingredients}</p>
        <h3>Where can I find this pizza?</h3>
        {parents field="specialty_pizzas"}
                <strong>{parents:title}</strong>: <br />
                {parents:phone} <br />
                <p>{parents:address}</p>
        {/parents}
{/exp:channel:entries}

In this template we list the Pizza channel’s variables – {title}, {description} and {ingredients}. Then we have a section to show in which stores this pizza is currently available. To accomplish this, we use the {parents} tag.

The {parents} tag will pull entries that have the current Entry from the {exp:channel:entries} tag as a child through the field that you specify. If you use the same field group in multiple channels, you may want to also specify the channel. In this case, we’re passing it the specialty_pizzas field. It will look for all entries attached to any channel through the specialty_pizzas field that have the current Pizza entry as a child. In our case, specialty_pizzas is only used in the Stores channel and this will have the result of finding all Stores that currently have this Pizza available.

The {parents} tag is a looping tag pair. So for each Store it finds, it will loop over the section of template contained in the pair:

<strong>{parents:title}</strong>: <br />
{parents:phone} <br />
<p>{parents:address}</p>

It will replace that section’s variables and append it to the final output. Here, we use namespacing again to access the parent Store’s variables. We access its title, phone and address using parents:title, parents:phone, and parents:address.

The Music Venue

Another case in which Relationships can be handy is the Music Venue website. We’ll assume this is a small venue that plays a lot of local bands. These bands return for many shows. They also change pretty frequently. And it is often the same musicians moving between the bands as they breakup, reform or trade musicians. So we’ll want three channels, Bands, Musicians, and Shows. Here’s the layout:

Musicians
        title                   Text
        url_title               Text
        first_name              Text
        last_name               Text
        biography               Text
        instruments             Text

Bands
        title                   Text
        url_title               Text
        history                 Text
        style                   Text
        members                 Relationship (to Musicians, multiple)

Shows
        title                   Text
        url_title               Text
        what                    Text
        when                    Date
        bands                   Relationship (to Bands, multiple)

Child Entries: Upcoming Shows

The first thing we tackle is creating a listing of upcoming shows and the bands that are playing in them. We assume the Show entry is set to expire the day after the show, so we don’t have to worry about any date stuff for now. Here’s what that template might look like:

{exp:channel:entries channel="shows"}
        <div class="show">
                <h2><a href="{path="shows/index"}/{url_title}">{title}</a></h2>
                <div class="show-body">
                        <div class="what"><label>What</label>{what}</div>
                        <div class="when"><label>When</label>{when}</div>
                        <div class="who">
                                <label>Who's playing?</label>
                                {bands}
                                        <div class="band"><strong>{bands:title}</strong> {bands:style}</div>
                                {/bands}
                        </div>
                </div>
        </div>
{/exp:channel:entries}

Most of this should look pretty familiar to you if you’re familiar with the channel:entries tag. But notice this section:

<div class="who">
        <label>Who's playing?</label>
        {bands}
                <div class="band"><strong>{bands:title}</strong> {bands:style}</div>
        {/bands}
</div>

This section uses the Relationships field. On the publish page, we attached the Bands that are going to playing this Show to the Show’s entry. With the {bands} tag, we are now looping over those bands. For each Band entry attached to the Show entry, we append this line of the template with the variables replaced:

<div class="band"><strong>{bands:title}</strong> {bands:style}</div>

In each loop, we replace the Band’s name {bands:title} and what style of music they play {bands:style}. Again, the namespacing of relationships with the relationship tag name allows us to specify which title we want, in this case, the Band’s and not the Show’s.

Parent Entries: A Band’s Recent Shows

Now we want to build a page for each Band. And on that page, we want to display all the Shows that Band has played. To do this, we need a parent tag:

{exp:channel:entries channel="bands" limit="1"}
        <div class="band">
                <h2>{title}</h2>
                <span class="style">{style}</span>
                <p>{history}</p>
                <div class="members">
                        {members}
                                <div class="member">
                                        <a href="{path="musicians/index"}/{members:url_title}">{members:first_name} {members:last_name}</a>
                                </div>
                        {/members}
                </div>
                <div class="shows">
                        <h3>Recent Shows</h3>
                        {parents channel="shows" field="bands"}
                                <div class="show">
                                        <strong>{parents:title}</strong>
                                        <div class="what">{parents:what}</div>
                                        <div class="when">{parents:when}</div>
                                </div>
                        {/parents}
                </div>
        </div>
{/exp:channel:entries}

The part to notice is this bit:

<div class="shows">
<h3>Recent Shows</h3>
{parents channel="shows" field="bands"}
        <div class="show">
                <strong>{parents:title}</strong>
                <div class="what">{parents:what}</div>
                <div class="when">{parents:when}</div>
        </div>
{/parents}
</div>

Here, we use the {parents} tag to access this Band’s parent entries in the Shows channel. It will cycle through each Show that has this particular Band entry as a child through the bands field and display this part of the template for that Show entry:

<div class="show">
        <strong>{parents:title}</strong>
        <div class="what">{parents:what}</div>
        <div class="when">{parents:when}</div>
</div>

Parent Entries: A Musician’s Bands

On the musician page, we want to be able to display the bands a musican currently plays with. To do that, we use the {parents} tag again. Here is the template:

{exp:channel:entries channel="musicians" limit="1"}
        <div class="musician">
                <h2>{first_name} {last_name}<h2>
                <div class="instruments">
                        {instruments}
                </div>
                <div class="biography">
                        {biography}
                </div>
                <div class="past-bands">
                        <ul>
                        {parents field="members"}
                                <li class="band-name"><a href="{path="bands/index"}/{parents:url-title}">{parents:title}</a></li>
                        {/parents}
                        </ul>
                </div>
        </div>
{/exp:channel:entries}

The relevant section is this:

<div class="past-bands">
        <ul>
        {parents field="members"}
                <li class="band-name"><a href="{path="bands/index"}/{parents:url-title}">{parents:title}</a></li>
        {/parents}
        </ul>
</div>

Here we use the {parents} tag to access the Band entries that this Musician is a member of. Since the members field is only used in the Band channel we do not need to specify the channel. It will only pull Bands.

The Community Sports League

Let’s tackle something more complex. We’re building a website for a local community sports league. The league runs multiple seasons every year with different teams and games. The channels might look like this:

Seasons
        title                   Text Input
        url_title               Text Input
        games                   Relationship (pointing to Games channel, multiple Games)
        teams                   Relationship (pointing to Teams channel, multiple Teams)

Games
        title                   Text Input
        url_title               Text Input
        home                    Relationship (pointing to Teams channel, a single Team)
        away                    Relationship (pointing to Teams channel, a single Team)
        home_score              Text Input (Number)
        away_score              Text Input (Number)

Teams
        title                   Text Input
        url_title               Text Input
        players                 Relationship (pointing to Players channel, multiple Players)

Players
        title                   Text Input
        url_title               Text Input
        first_name              Text Input
        last_name               Text Input
        number                  Text Input (Number)

Child Entries: Showing Games and Teams in a Season

The first thing we do is show all games and teams in a particular season. The ‘Spring 2013’ season. While we’re at it, lets list all the players on each team, so that players know which team they’ve been placed on. The template might look something like this:

{exp:channel:entries channel="seasons" title="Spring 2013" limit="1"}
        <div class="season">
                <h2>{title}</h2>
                <h3>Teams</h3>
                <div class="teams">
                        {teams}
                                <div class="team">
                                        <h4>{teams:title}</h4>
                                        {teams:players}
                                                <span class="player">{teams:players:first_name} {teams:players:last_name}</span>
                                        {/teams:players}
                                </div>
                        {/teams}
                </div>
                <h3>Games</h3>
                <div class="games">
                        {games}
                                <div class="game">
                                        <h4>{games:title}</h4>
                                        {games:home:title} vs {games:away:title}
                                </div>
                        {/games}
                </div>
        </div>
{/exp:channel:entries}

Let’s break that down to see what we are doing. The first thing you see is the good old channel entries tag:

{exp:channel:entries channel="seasons" title="Spring 2013" limit="1"}

We pull a single entry from the Seasons channel. The one titled “Spring 2013”. Just inside of that we see our standard {title} tag to pull the title of the entry. After that things get more interesting:

{teams}
        <div class="team">
                <h4>{teams:title}</h4>
                {teams:players}
                        <span class="player"><span class="number">{teams:players:number}{teams:players:first_name} {teams:players:last_name}</span>
                {/teams:players}
        </div>
{/teams}

Notice, the tag name teams is the same as our relationship field name in the Seasons channel. This is a Relationship tag. It works very similarly to the channel:entries tag. It will loop over the entries you have assigned to the teams field on the publish page and use them to replace the variables contained.

Here, things differ a little bit from standard channel entries. We need a way to separate the related entry’s variables from your channel:entries tag’s variables. To accomplish this we prefix the variables of the related entries with the name of the field they belong to. So:

<h4>{teams:title}</h4>

In that bit of code, we’re accessing the title of the entry from the Teams channel related to our current Season through the teams field. This is very powerful. It allows you to relate entries even from the same channel to each other and still access their variables. Say you wanted to add a field for the previous and next seasons to a season’s entry. You could give it a previous and next field. In your channel:entries tag you might access them like this:

{exp:channel:entries channel="seasons" url-title="winter-2013" limit="1"}
        <a href="{path="seasons/index"}/{previous:url_title}">{previous:title}</a>
        <a href="{path="seasons/index"}/{next:url_title}">{next:title}</a>

Even though all the variables would be the same, you can easily access any variable from the current entry or either of the related entries.

Prefixing variables this way also allows us to access nested relationships. Look back up to our previous example. Notice this bit of code:

{teams:players}
        <span class="player">{teams:players:first_name} {teams:players:last_name}</span>
{/teams:players}

In our Teams channel you’ll notice that we have a relationship field to the Players channel that can take multiple entries. We access those entries through the {teams:players} tag. This works exactly the same as the {teams} tag. It’s an entries loop tag. Except in this case, we’re getting the entries that were assigned to our current Team. We can access the Player channel’s variables in the same way as we do our Team channel’s variables, by prefixing them:

<span class="player">{teams:players:first_name} {teams:players:last_name}</span>

You may also have noticed that in some places we wrap our relationship in an open and close tag, like we did above with players:

{teams:players}
        <span class="player">{teams:players:first_name} {teams:players:last_name}</span>
{/teams:players}

In other places, however, we don’t. We just access the relationship’s variables directly using the prefixing, like we did with the home and away fields:

{games}
        <div class="game">
                <h4>{games:title}</h4>
                {games:home:title} vs {games:away:title}
        </div>
{/games}

In the above example, home and away are relationship fields in the Games channel. However, they are limited to a single entry. In that case, you can access the relationship’s variables directly, at any time, by adding the prefix. There’s no need to specify the bit of your template you want to loop over. There can only be one!

Child Entries: Showing Details of a Game

Let’s try another example. Let’s say you need another page on this league website that shows the details of a single game: when, who played and who won. That template might look something like this:

{exp:channel:entries channel="games" limit="1"}
        <h2>{home:title} ({home_score}) vs {away:title} ({away_score})</h2>
        <p>In this game the {home:title} played the {away:title}.</p>
        <p>The final scores were {home:title} with {home_score} and {away:title} with {away_score}.</p>
        <p>Playing for {home:title} were:</p>
        <div class="players">
                {home:players}
                        <span class="player">#{home:players:number} {home:players:first_name} {home:players:last_name}</span>
                {/home:players}
        </div>
        <p>Playing for {away:title} were:</p>
        <div class="players">
                {away:players}
                        <span class="player">#{away:players:number} {away:players:first_name} {away:players:last_name}</span>
                {/away:players}
        </div>
{/exp:channel:entries}

Here, the {exp:channel:entries} tag accesses the Games channel. The first thing we do is display which teams are playing and what the score was. We do that by going through the home and away fields which both point to the Teams channel. We grab the title ({home:title} and {away:title}) and display it.

Further down we list the players on each team using {home:players} and {away:players}. Since the players field is a multiple relationship, we need a tag pair. But notice that we don’t need to be the {home:players} tag itself inside a {home} pair. {home} takes a single entry, and so we can just use it as a prefix to access its custom field variables.

Inside the {home:players} and {away:players} pairs we can access the field variables of the Players channels by prefixing them with home:players or away:players respectively. So, inside {home:players} we can get the Player’s first name, last name and number with {home:players:first_name}, {home:players:last_name} and {home:players:number}.

Parent Entries: Showing A Team’s History

Say you had a Team page where you showed details of a particular team and you wanted to show all Games that team had played in. You could accomplish this like so:

{exp:channel:entries channel="teams"}
        <div class="games"><ul>
                {parents field="home|away"}
                        <li>{parents:home:title} ({parents:home_score}) vs {parents:away:title} ({parents:away_score})</li>
                {/parents}
        </ul></div>
{/exp:channel:entries}

In this case, we have two different fields in the parent channel that relate to the Teams channel: home and away. We want to pull from both of them, so in our {parents} tag field parameter we use field="home|away". Here the channel parameter is unnecessary as neither home or away is used in any channel other than Games.

Sibling Entries: Navigating Between Games

What if you wanted to have a series of pages showing the details of a single game? On these pages, you want to show a navigation section, showing other games from the current season. You could accomplish this by using channel:entries for the Seaons channel and walking down to games. But that would require an if tag to determine whether the game we’re showing in navigation is the current game. An easier way to accomplish this would be to use the siblings tag, like so:

{exp:channel:entries channel="games"}
        <div class="navigation"><ul>
                {siblings channel="seasons" field="games"}
                        <li>{siblings:title}    - {siblings:home:title} vs {siblings:away:title}</li>
                {/siblings}
        </ul></div>
{/exp:channel:entries}

The siblings tag pulls all entries in the Games channel that are related to the Seasons channel through the games field, except for the current one. The current entry in the Games channel that the channel:entries tag has pulled up must be related to the channel through the field given to the siblings tag. Otherwise it won’t work.

Tag Reference

Tag Parameters

The following parameters are available to all looping relationship tags, allowing you to further filter or sort the entries being retrieved. They function the same as they do when used on the {exp:channel:entries} tag. The available parameters are:

  • author_id
  • backspace
  • category
  • channel
  • entry_id
  • group_id
  • offset
  • orderby
  • show_expired
  • show_future_entries
  • sort
  • start_on
  • status
  • stop_before
  • url_title
  • username

Some relationship tags may have additional parameters available. These are included in the usage instructions below.

Accessing Children

Accessing Siblings

Usage

Given the following channel layout:

ParentChannel
        title
        url_title
        field1                                  Text
        field2                                  Text
        relationship_field              Relationship (ChildChannel, Multiple)


ChildChannel
        title
        url_title
        field1                                  Text
        field2                                  Text

You can access siblings of the current entry in {exp:channel:entries} tag using the following syntax:

{exp:channel:entries channel="childChannel"}
        {siblings field="relationship_field"}
                {siblings:title} - {siblings:field1} - {siblings:field2}
        {/siblings}
{/exp:channel:entries}

The {siblings} tag does not need to be a top level tag. It may be used from a nested relationship in order to access that relationship’s siblings. The syntax is:

{exp:channel:entries channel="parentChannel"}
        {relationship_field}
                {relationship_field:siblings field="relationship_field"}
                        {relationship_field:siblings:title}
                {/relationship_field:siblings}
        {/relationship_field}
{/exp:channel:entries}

Parameters

In addition to the standard parameters, the following parameter may be used in this tag:

field

There can be multiple relationship fields in a field group, thus child entries may be related to the same parent via different fields. Use the field parameter to specify which field in the parent entry we should be pulling the siblings from. The syntax is:

{siblings field="relationship_field"}

Accessing Parents

Usage

Given the following channel layout:

ParentChannel
        title
        url_title
        field1                                  Text
        field2                                  Text
        relationship_field              Relationship (ChildChannel, Multiple)


ChildChannel
        title
        url_title
        field1                                  Text
        field2                                  Text

You can access the parents of the current entry in a channel:entries tag using the following syntax:

{exp:channel:entries channel="childChannel"}
        {parents field="relationship_field"}
                {parents:title} - {parents:field1} - {parents:field2}
        {/parents}
{/exp:channel:entries}

The {parents} tag may be accessed through nested relationships tags using the following syntax:

{exp:channel:entries channel="parentChannel"}
        {relationship_field}
                {relationship_field:parents field="relationship_field"}
                        {relationship_field:parents:title}
                {/relationship_field:parents}
        {/relationship_field}
{/exp:channel:entries}

Parameters

In addition to the standard parameters, the following parameter may be used in this tag:

field

There can be multiple relationship fields in a field group, and thus an entry may be selected as a child in multiple fields. Use the field parameter to specify which field in the parent entry we should be checking for our child. The syntax is:

{parents field="relationship_field"}

Namespacing Variables

Any variable available to the channel entries tag can be used inside a relationship tag pair. Use prefixes to specify which entry or set of entries the variable belongs to:

{exp:channel:entries channel="childChannel"}

        {parents}

                {if parents:count == "1"}
                        <h3>Parents</h3>
                {/if}

                {parents:title} - {parents:field1} - {parents:field2}

                {if parents:no_results}
                        No parent entries
                {/if}

                {parents:switch="one|two"}

        {/parents}

{/exp:channel:entries}

Grid Compatibility

The Relationships field can be used as a Grid field column. Currently it is not possible to get the parents of a relationship field that is inside of a Grid field. You can also not use Relationships inside of a Grid field that does not store Channel data.

User Contributed Notes

Posted by: Hop Studios on 18 February 2014 11:37pm
Hop Studios's avatar

Watch out: The status attribute for the relationship tag is case sensitive.  The status attribute of the channel:entries tag is (almost always) case-insensitive. This means that you might have a status attribute that works for channel:entries but doesn’t seem to for a relationship.  See https://support.ellislab.com/bugs/detail/19913 for more details.

Posted by: Triad on 21 November 2013 5:15am
no avatar

Discovered that with a one-line code hack you can make the parents tag accept a category parameter.

The existence of the code even implies that it should always have been there, but there you go.

/system/expressionengine/libraries/relationship_parser/Parser.php 

Look for:

$rows[$entry_id] $data

If you simply move this line to be the last line inside the foreach loop that starts

foreach ($entry_ids as $entry_id

Then it works.

Your script may differ slightly, but my line moved from line #475 to line #520

Posted by: johnniefp on 17 September 2013 6:48am
johnniefp's avatar

Lot’s missing from the 2.6 update to relationships on this page.
Take a look here for some additional stuff that should be here: http://www.blue-dreamer.co.uk/blog/entry/ee2.6-new-relationship-tags. (Thanks bluedreamer)

Posted by: IC360 (Oliver Cannell) on 23 August 2013 9:13am
IC360 (Oliver Cannell)'s avatar

I have also managed to successfully use the “limit” parameter in Relationship variable tag.

{sections:static-subpages limit="1"}<ul class="popout">{/sections:static-subpages}
{sections
:static-subpages}<li><a href="">{sections:static-subpages:title}</a></li>{/sections:static-subpages}
{sections
:static-subpages limit="1"}</ul>{/sections:static-subpages} 

Unless there is a better way to achieve this?

Posted by: Michael Rosario on 27 July 2013 10:04am
Michael Rosario's avatar

Really great!
{parents field="speakers" show_expired="yes" show_future_entries="yes" category="1" status="Open" orderby="" }
{parents:title}
{/parents}

Posted by: Roi Agneta on 14 July 2013 2:49pm
Roi Agneta's avatar

If you are accessing a parent that happens to have a future entry date, you must allow for future entries in the parents tag:

{parents field="speakers" show_future_entries="yes"}
 {parents
:title}
{
/parents} 
Posted by: Hop Studios on 16 May 2013 1:48pm
Hop Studios's avatar

Looking for documentation on

{reverse_related_entries} 
and
{related_entries} 

? That’s no longer available—those tags are for versions of EE previous to 2.6, and the documentation has been removed.

Posted by: Hop Studios on 29 April 2013 5:46pm
Hop Studios's avatar

As of 2.6.0, you access NO_RESULTS and COUNT for relationships, (and probably the other channel loop variables, too, but I didn’t test it) with namespacing.  So for example:

{parents field="my_field"}
  {if parents
:no_results}NOTHING FOUND{/if}
  
(<a href="{comment_url_title_auto_path}">{parents:title}</a{count} {parents:count})
 
{/parents} 

You must have an EllisLab product license and have at least 50 posts to the community forums to contribute notes to the User Guide