Guide 03 · Developer docs

The theme repo and the asset pipeline

Everything a developer changes on a Core dna site lives in its theme repository. This guide covers the repository and its build, printing records in templates, stylesheets and client-side code, and the parts of a site around the main content.

L1–L2
Unit 02 · Records in templates

What the controller hands the template

A template does not fetch its record: the platform's controller assigns it, under the record type's own name and as record, wrapped in a response model. The variable names by module, what the wrapping changes, and what each engine does with a call the model does not allow or a relation that is empty.

Who this is for. The theme developer writing or reading a template for a page, a post, a product or a custom entity record. Afterwards you know which variables your template receives, which of a record's methods a template can call, and how to tell the two common access errors apart in either engine. Reading a record's layout areas is The area getters and what each costs; this unit is about the record itself.

The variables a controller assigns

The URL selects a module's controller, the controller loads the record and assigns it, and the record's layout names the template. A show controller assigns the record twice: under the lower-camel-case name of its type, and as record. A listing controller assigns the records under the plural name, with _pagination beside them.

What rendersVariables
A pagepage, record
A blog postpost, record
A blog's list of postsblog and record (the blog), posts, _pagination
A productproductDescription, record
A custom entity recordthe type's identifier, such as testimonial, and record
A custom entity listingthe type's plural identifier, such as testimonials, and _pagination

Use the specific name in a template written for one record type; use record in a partial shared by several. Every template also receives the common variables, _request, _currentSite, _query and the rest: Global template variables.

What arrives is a response model

The variable does not hold the record. It holds the record's response model, a wrapper that lets a template call only the get, has and is methods its class lists with @method. Response models explains the mechanism; three consequences matter when you render a record:

  • Its callable surface is the list, not the record's class. A method that exists on the platform's model but is missing from the list cannot be called. The list for each record type is the Templates section of its page in the generated Reference.
  • It is read-only. Setting a property fails with Setting values is not allowed in response models.
  • Dates arrive in the site's time zone. Every date a getter returns has been converted from storage to the zone in the site's settings. Format it; do not convert it again.

A call the list does not allow

In Smarty, {$page->getNmae()} stops the render with Method getNmae does not exist in Pages\Models\Frontend\Response\Page. On a development environment you see that message; on production the visitor gets the site's errors/fatal-error.html (or the platform's, if the site has none) with status 500. In Twig the same call prints nothing and raises nothing. The message means the method is not on the list: check the Reference before you suspect the spelling, and when the list lacks a method you need, the change is the platform's to make, not the site's. Ask for it with the record type, the method and what the page needs it for.

A relation that is empty

A getter that returns another record returns that record's response model, so calls chain: $post->getBlog()->getName(). Any link in the chain can be empty, and the engines part ways again. Smarty stops with the PHP error Call to a member function getName() on null; Twig prints nothing. Guard every relation that can be empty:

Template code
{$blog = $post->getBlog()}
{if $blog}
  <a href="{$blog->getFullPath()}">{$blog->getName()|escape}</a>
{/if}
{% set blog = post.getBlog() %}
{% if blog %}
  <a href="{{ blog.getFullPath() }}">{{ blog.getName()|e }}</a>
{% endif %}

The guard matters in Twig too, where nothing breaks: without it the page shows an empty link instead of no link.

You seeEngineCause
Method X does not exist in …SmartyThe method is not on the response model's list, or is misspelt
Call to a member function X() on nullSmartyA relation earlier in the chain is empty
Nothing where a value should beTwigEither of the above, or an empty value: check the list first
Go deeper

Was this page helpful?

Your answer goes to the docs team.