What is Carrington?
- An elegant, high-end WordPress theme for end-users.
- A developer friendly theme and conventions-based templating system.
- A set of best practices for theme organization.
Basic Theme Concept
Carrington is an attempt to better abstract WordPress theme organization, and simplify commonly needed theme functionality.
Theme functionality is broken up into thoughtfully crafted abstractions to enable customizations at different levels (the loop, the post/page content, comments, etc.) and a context-aware hierarchical template override system that chooses which template to be used for each segment of the theme.
The abstractions and supported template types are designed to easily handle most of the customization scenarios we commonly see.
Theme Organization
WordPress themes generally have a file structure similar to this:
- 404.php
- archive.php
- archives.php
- […]
- sidebar.php
- single.php
- style.css
While this organization works well in many instances, it doesn’t well support the concept of atomic elements that are combined to create a theme. For example, a representation of just a post’s content, or just a comment, is not represented here.
Carrington respects the supported WordPress file naming conventions (for example get_header() will still work), but eschews them in favor of an organizational structure that better suits the abstraction and customization commonly needed for a WordPress theme.
Template files are layered into each other using the following basic approach:
- top level templates that include
- common elements like a header, footer and sidebar along with a
- loop that includes
- atomic post/page content or excerpt templates and, where appropriate, a
- comments area template that includes
- atomic template for comments and a
- template for the comment form
Context
WordPress provides a number of functions to help you determine what type of view a theme is showing. These include:
is_home()
is_single()
is_page()
is_archive()
in_category()
- etc.
Carrington abstracts these to deduce a “context” for a particular page.
Template Override System
At each level, templates are chosen based on a built-in context override system that uses simple file naming conventions to provide default functionality that allows for easy display customization based on various criteria.
For a given directory, a variety of options are available. These vary slightly at each level - here are a couple of examples.
posts/
This directory holds the top level templates for pages that show multiple posts. This includes the home page, date archives, category archives, author archives, search results, etc.
Supported filenames:
- posts-default.php (default.php also supported) - used if no other templates are available or match for the current context.
- author.php - used for author archive pages
- author-{username}.php - used for author archive pages for the “username” user
- category.php - used for category archive pages
- cat-{example}.php - used for category archive pages for the “example” category
- tag.php - used for tag archive pages
- tag-{example}.php - used for tag archive pages for the “example” tag
- search.php - used for search results pages
- single.php - used for a “single post” page
- home.php - used for the home page
content/
This directory holds the templates used for displaying atomic post content.
Supported filenames:
- content-default.php (default.php also supported) - Used when there are no other templates that match for a given post/page.
- author-{username}.php - Used when a user with that username authors a post/page. For example, a template with a file name of author-jsmith.php would be used for a poat/page by user jsmith. Any WordPres username can take the place of {username} in the file name.
- meta-{key}-{value}.php - Used when there is a custom field for the post/page matching the key and value listed in the file name. This is useful if you want to be able to flag posts as “featured” or similar, and give those posts some custom treatment. In this example, you could add a custom field of “featured” with a value of “yes” to a post/page and it would use a template of meta-featured-yes.php if that template exists.
- cat-{slug}.php - Used when a post is in a given category. The category is matched by the “slug” - for example a post in category “General” (with a category slug of “general”) could use a template of cat-general.php.
- role-{role}.php - Used when a post/page is authored by a user with a particular role. The {role} is an all lowercase representation of the role string - for example, an author with an “Administrator” role might use a template of role-administrator.php. This is primarily useful if you have a set of authors that are given a Contributor role; or a Guest Columnist role or similar. Any WordPress role can take the place of {role} in the file name.
- tag-{slug}.php - Used when a post has a certain tag applied to it. The tag is matched by the “slug” - for example a post with tag “Reference” (with a category slug of “reference”) could use a template of tag-reference.php.
- parent-{slug}.php - Used when a page is a sub-page of a certain page. The page is matched by the “slug” - for example a sub-page of a parent page with a slug of “knowledge-base” could use a template of parent-knowledge-base.php.
- author.php - Used when the content is being displayed on an “author” page (a page listing posts by author).
- category.php - Used when the content is being displayed on a “category” page (a page listing posts by category).
- tag.php - Used when the content is being displayed on an “tag” page (a page listing posts by tags).
- page.php - Used when the content is being displayed is a page (not a post).
- single.php - Used when the content is being displayed on an “single” page (a page showing only one post).
- search.php - Used when the content is being displayed are search results (a page listing posts matching a user search).
- home.php - Used when the page being displayed is the home page.
As you can see, this is a little more complex than the template options in Kubrick - the WordPress default theme. However all of these named templates are optional. Carrington includes primarily “default.php” options and enables you to create your own additional templates as needed.
Note: “default.php” is a supported default file name for all directories, however we have found in real world usage that {dirname}-default.php is a preferable naming system. When you have a half-dozen “defaultphp” files open in your favorite text editor, telling them apart in the file list can be more difficult than it should be.
Actions and Filters
Because Carrington is as much a theme framework as a theme itself, it includes a core set of functions that enable the override template hierarchy. These functions include actions and filters where appropriate so that their functionality can be customized and overridden as needed. Thess actions and filters use the same hook and filter system used in the WordPress core.
cfct_settings_form (action) - allows you to add your own fields to the Carrington Settings form.
cfct_settings_form_after (action) - allows you to add your content after the Carrington Settings form. Useful if you want to add a second form to the page, or some other content.
cfct_update_settings (action) - allows you to take action when the Carrington settings are being saved (perhaps to also save fields you’ve added in the cfct_settings_form action).
cfct_context (filter) - allows you to apply filters to the return value of the cfct_context() function; the function that checks to see what posts file, loop file, etc. to show.
cfct_comment (filter) - allows you to change which comment template is used.
cfct_filename (filter) - filter the output of the cfct_filename() function.
cfct_general_match_order (filter) - set the order in which general templates are chosen (make it check for a cat-general template ahead of a cat-news template, etc.).
cfct_choose_general_template (filter) - filter the output of the cfct_choose_general_template() function.
cfct_content_match_order (filter) - set the order in which content templates are chosen (make it check for author templates ahead of meta template, etc.).
cfct_choose_content_template (filter) - filter the output of the cfct_choose_content_template() function.
cfct_comment_match_order (filter) - set the order in which content templates are chosen (make it check for role templates ahead of user templates, etc.).
cfct_choose_comment_template (filter) - filter the output of the cfct_choose_comment_template() function.
cfct_meta_templates (filter) - filter the return value of the cfct_meta_templates() function.
cfct_cat_templates (filter) - filter the return value of the cfct_cat_templates() function.
cfct_tag_templates (filter) - filter the return value of the cfct_tag_templates() function.
cfct_author_templates (filter) - filter the return value of the cfct_author_templates() function.
cfct_role_templates (filter) - filter the return value of the cfct_role_templates() function.
cfct_comment_templates (filter) - filter the return value of the cfct_comment_templates() function.
Plugins
Any .php files in the plugins/ directory will be automatically loaded by Carrington. This is a great way to bundle in custom functions or to hook into Carrington’s actions or filters.
File Structure
content/
Overview
This directory holds the templates for displaying a post. Typically this will be the full post with title, meta information (date, categories, tags, author, etc.) and the full output of the_content().
Commonly these templates are included by templates in the loop/; but are also useful for bringing in an atomic post representation via AJAX or placing one within another template.
A “default” template is required, and will be used when there are no other templates that match a given comment. This could be because no other templates have been created, or because the comment in question doesn’t match the templates that are available.
You can create templates to be used with posts/pages given various conditions. For example, you might want to give all posts in a certain category some specific styling rules. Or perhaps posts with a certain custom field or by a specific author. This is accomplished by creating templates with file names that match these conditions, then placing them in the content/ directory. All templates other than default.php are optional.
The order in which these conditions are checked defaults to the following:
- author
- meta
- category
- role
- tag
- page types (author, category, tag, single, search, etc.)
- default
however this order can be overridden with a plugin using the cfct_content_match_order hook.
Once a template match has been found, no other processing is done.
If you want to apply styling/custom HTML to the_excerpt(), create/customize templates in the excerpt/ directory rather than adding conditional logic to these templates.
Supported Override Filenames
- content-default.php (or default.php)
- archive.php
- author.php
- author-{username}.php
- category.php
- cat-{slug}.php
- home.php
- meta-{key}-{value}.php
- meta-{key}.php
- page.php
- parent-{slug}.php
- role-{rolename}.php
- search.php
- single.php
- tag.php
- tag-{slug}.php
File Descriptions
- content-default.php - Used when there are no other templates that match for a given post/page.
- author-{username}.php - Used when a user with that username authors a post/page. For example, a template with a file name of author-jsmith.php would be used for a poat/page by user jsmith. Any WordPres username can take the place of {username} in the file name.
- meta-{key}-{value}.php - Used when there is a custom field for the post/page matching the key and value listed in the file name. This is useful if you want to be able to flag posts as “featured” or similar, and give those posts some custom treatment. In this example, you could add a custom field of “featured” with a value of “yes” to a post/page and it would use a template of meta-featured-yes.php if that template exists.
- meta-{key}.php - Used when there is a custom field for the post/page matching the key listed in the file name. This is useful if you want to be able to flag posts as “photo” or similar, and give those posts some custom treatment. In this example, you could add a custom field of “photo” with a value of the URL of the image to a post/page and it would use a template of meta-photo.php if that template exists. The value does not matter in this match.
- cat-{slug}.php - Used when a post is in a given category. The category is matched by the “slug” - for example a post in category “General” (with a category slug of “general”) could use a template of cat-general.php.
- parent-{slug}.php - Used when a page is a child page of a specific parent page. The page is matched by the “slug” - for example a page under a parent page with slug of “example” could use a template of parent-example.php.
- role-{role}.php - Used when a post/page is authored by a user with a particular role. The {role} is an all lowercase representation of the role string - for example, an author with an “Administrator” role might use a template of role-administrator.php. This is primarily useful if you have a set of authors that are given a Contributor role; or a Guest Columnist role or similar. Any WordPress role can take the place of {role} in the file name.
- tag-{slug}.php - Used when a post has a certain tag applied to it. The tag is matched by the “slug” - for example a post with tag “Reference” (with a tag slug of “reference”) could use a template of tag-reference.php.
- author.php - Used when the content is being displayed on an “author” page (a page listing posts by author).
- category.php - Used when the content is being displayed on a “category” page (a page listing posts by category).
- tag.php - Used when the content is being displayed on an “tag” page (a page listing posts by tags).
- page.php - Used when the content is being displayed is a page (not a post).
- single.php - Used when the content is being displayed on an “single” page (a page showing only one post).
- search.php - Used when the content is being displayed are search results (a page listing posts matching a user search).
- home.php - Used when the page being displayed is the home page.
Close content/
css/
Overview
This directory is used to organize your CSS files. You can reference these files using the built-in WordPress bloginfo() function like so:
<link rel="stylesheet" type="text/css"
href="<?php bloginfo('template_directory'); ?>/css/base.css" />
Close css/
error/
Overview
This directory holds templates for error conditions. WordPress supports the 404 error out of the box, but you may want to create additional error templates for other conditions (not authorized, etc.).
You can load an error template by using the following code:
cfct_error('not-authorized.php');
Supported Override Filenames
File Descriptions
- 404.php - used for “File not Found” errors.
- exit.php - used to display a message when exiting on some error condition.
Close error/
excerpt/
Overview
(This information is very similar to the content/)
This directory holds the templates for displaying a the excerpt for a post. Typically this will include the title and some sub-set of meta information (date, categories, tags, author, etc.) and the full output of the_content().
Commonly these templates are included by templates in the loop/; but are also useful for bringing in an atomic post representation via AJAX or placing one within another template.
A “default” template is required, and will be used when there are no other templates that match a given comment. This could be because no other templates have been created, or because the comment in question doesn’t match the templates that are available.
You can create templates to be used with posts/pages given various conditions. For example, you might want to give all posts in a certain category some specific styling rules. Or perhaps posts with a certain custom field or by a specific author. This is accomplished by creating templates with file names that match these conditions, then placing them in the content/ directory. All templates other than default.php are optional.
The order in which these conditions are checked defaults to the following:
- author
- meta
- category
- role
- tag
- page types (author, category, tag, single, search, etc.)
- default
however this order can be overridden with a plugin using the cfct_content_match_order hook.
Once a template match has been found, no other processing is done.
Supported Override Filenames
- excerpt-default.php (or default.php)
- archive.php
- author.php
- author-{username}.php
- category.php
- cat-{slug}.php
- home.php
- meta-{key}-{value}.php
- page.php
- role-{rolename}.php
- search.php
- single.php
- tag.php
- tag-{slug}.php
File Descriptions
(This information is the same as the content/)
- excerpt-default.php - Used when there are no other templates that match for a given post/page.
- author-{username}.php - Used when a user with that username authors a post/page. For example, a template with a file name of author-jsmith.php would be used for a poat/page by user jsmith. Any WordPres username can take the place of {username} in the file name.
- meta-{key}-{value}.php - Used when there is a custom field for the post/page matching the key and value listed in the file name. This is useful if you want to be able to flag posts as “featured” or similar, and give those posts some custom treatment. In this example, you could add a custom field of “featured” with a value of “yes” to a post/page and it would use a template of meta-featured-yes.php if that template exists.
- cat-{slug}.php - Used when a post is in a given category. The category is matched by the “slug” - for example a post in category “General” (with a category slug of “general”) could use a template of cat-general.php.
- role-{role}.php - Used when a post/page is authored by a user with a particular role. The {role} is an all lowercase representation of the role string - for example, an author with an “Administrator” role might use a template of role-administrator.php. This is primarily useful if you have a set of authors that are given a Contributor role; or a Guest Columnist role or similar. Any WordPress role can take the place of {role} in the file name.
- tag-{slug}.php - Used when a post has a certain tag applied to it. The tag is matched by the “slug” - for example a post with tag “Reference” (with a category slug of “reference”) could use a template of tag-reference.php.
- author.php - Used when the content is being displayed on an “author” page (a page listing posts by author).
- category.php - Used when the content is being displayed on a “category” page (a page listing posts by category).
- tag.php - Used when the content is being displayed on an “tag” page (a page listing posts by tags).
- page.php - Used when the content is being displayed is a page (not a post).
- single.php - Used when the content is being displayed on an “single” page (a page showing only one post).
- search.php - Used when the content is being displayed are search results (a page listing posts matching a user search).
- home.php - Used when the page being displayed is the home page.
Close excerpt/
forms/
Overview
This directory holds forms that may be used in various places throughout the theme.
These forms can be included in other theme files using the following code:
<?php cfct_form('comment'); ?>
Where comment.php is the name of the file in the forms/ directory that you want to include.
Supported Override Filenames
File Descriptions
Included by default are the “post comment” form (comment.php) and the “search” form (search.php). Create as many forms as you like and store them here to keep them organized.
Close forms/
functions/
Overview
This directory contains Carrington’s custom features and functionality.
Supported Override Filenames
File Descriptions
You do not need to do anything with files in this folder; they should remain as-is.
- admin.php - Handles custom admin pages for Carrington features.
- *classnames.php - Includes semantic CSS classname functions for Carrington
- sandbox.php - Includes further useful semantic CSS classname functions - from the Sandbox theme.
- templates.php - Carrington template functions.
- utility.php - Carrington utility functions.
Close functions/
loop/
Overview
This directory contains files that do “the loop”. Generally the files in this directory will be included in a file from the posts/ or pages/ directory, and they will in turn include templates from the content/ or excerpt/ directories.
For example, you might want posts on a search results page to display differently that posts on an archive page. Here is how that page would be built:
- A page is identified as a search page - Carrington looks for a posts/search.php file and will fall back on a posts/default.php file if none is found.
- The posts/search.php file will include the header, footer and sidebar - and will also include a call to
cfct_loop() to include a loop.
- Since we don’t want to show the full posts in search results, the posts/search.php explicitly asks for a file from the excerpt/ directory to display the posts in the search results. It will use excerpt/search.php if that file exists, or fall back on excerpt/default.php if the custom file does not exist.
Supported Override Filenames
- loop-default.php (or default.php)
- archive.php
- author.php
- author-{username}.php
- category.php
- cat-{slug}.php
- home.php
- page.php
- role-{rolename}.php
- search.php
- single.php
- tag.php
- tag-{slug}.php
File Descriptions
Standard context file naming will work for files in this directory. Here are some specific examples.
Included is the “default” loop (default.php) and the “search” loop (search.php). Create as many loops as you like to create custom displays for various pages.
Close loop/
misc/
Overview
This directory holds page fragments and snippets that you may want to use across multiple template files.
These files can be included in other theme files using the following code:
<?php cfct_misc('nav-posts'); ?>
Where nav-posts.php is the name of the file in the misc/ directory that you want to include.
Supported Override Filenames
File Descriptions
- banner.php - This is used by Carrington to display a message that is passed to it.
- nav-posts.php - This is standard paging for posts pages.
Close misc/
pages/
Overview
WP doesn’t support page templates in nested folders like this one, so page organization isn’t as clean as we’d like.
Create a page in the theme root:
File name: page-example.php
Note: We recommend prefixing all of your page files with ‘page-’ so that they are easily sorted together in your theme directory.
File contents:
<?php
/*
Template Name: Example Template
*/
if (__FILE__ == $_SERVER['SCRIPT_FILENAME']) { die(); }
if (CFCT_DEBUG) { cfct_banner(__FILE__); }
cfct_page('example');
?>
This will then load ‘example.php’ from the pages/ directory, keeping all of your actual page code nicely organized in one spot.
You can also add your page code to the page-example.php file you create in the theme root, but we’re hoping to get support for pages in a sub-directory in a future version of WordPress so we are starting with what we consider to be a “proper” organization structure now.
Supported Override Filenames
- pages-default.php (or default.php)
File Descriptions
A “default” template is required. You can create other templates as desired.
Close pages/
plugins/
Overview
Carrington supports plugins in the same conceptual manner as WordPress. Carrington includes several hooks and filters so you can customize/override Carrington’s default behavior.
Any .php files placed in this directory will be auto-loaded and processed by Carrington.
This is the recommended way to interact with the hooks and filters provided by Carrington.
Supported Override Filenames
File Descriptions
No files are included here by default, add files to deliver custom functionality as needed.
Close plugins/
posts/
Overview
The files in this directory are “top level” templates for pages in WordPress that show multiple posts at once. These files should call the_header(), the_sidebar(), the_footer() and cfct_loop() to include the other parts of the page.
The file from this directory that will be used is chosen based on the current page context.
You can explicitly decide which loop/ to use from these templates by passing it in as so:
cfct_template_file('loop', 'example');
which would use loop/example.php for the loop.
A “default” template is required, and will be used when there are no other templates that match a given context. This could be because no other templates have been created, or because the context doesn’t match the templates that are available.
Supported Override Filenames
- posts-default.php (or default.php)
- archive.php
- author.php
- author-{username}.php
- category.php
- cat-{slug}.php
- home.php
- page.php
- role-{rolename}.php
- search.php
- single.php
- tag.php
- tag-{slug}.php
File Descriptions
Standard context file naming will work for files in this directory. Here are some specific examples.
- posts-default.php - Used when there are no other templates that match for a given context.
- author-{username}.php - Used to show posts authored by a specific user. For example, a template with a file name of author-jsmith.php would be used posts by user jsmith. Any WordPress username can take the place of {username} in the file name.
- cat-{slug}.php - Used to show posts in a given category. The category is matched by the “slug” - for example posts in category “General” (with a category slug of “general”) could use a template of cat-general.php.
- tag-{slug}.php - Used to show posts for a given tag. The tag is matched by the “slug” - for example a post tagged with “News” (with a tag slug of “news”) could use a template of tag-news.php.
- author.php - Used for showing posts by an author.
- category.php - Used for showing posts by category.
- search.php - Used for showing search results.
- tag.php - Used for showing posts by tag.
Close posts/
single/
Overview
This directory holds top level templates for “single” post pages. These files should call the_header(), the_sidebar(), the_footer(), cfct_loop() and cfct_comments() to include the other parts of the page.
A “default” template is required, and will be used when there are no other templates that match a given comment. This could be because no other templates have been created, or because the context doesn’t match the templates that are available.
Supported Override Filenames
- single-default.php (or default.php)
- author-{username}.php
- cat-{slug}.php
- role-{rolename}.php
- tag-{slug}.php
File Descriptions
Standard context file naming will work for files in this directory. Here are some specific examples.
- default.php - Used when there are no other templates that match for a given context.
- author-{username}.php - Used to show a post authored by a specific user. For example, a template with a file name of author-jsmith.php would be used posts by user jsmith. Any WordPress username can take the place of {username} in the file name.
- cat-{slug}.php - Used to show a post in a given category. The category is matched by the “slug” - for example posts in category “General” (with a category slug of “general”) could use a template of cat-general.php.
- tag-{slug}.php - Used when a post has a given tag. The tag is matched by the “slug” - for example a post tagged with “News” (with a tag slug of “news”) could use a template of tag-news.php.
Close single/
Tips
There is extra processing associated with the file system and context checks that Carrington requires. Because of this, use of a caching plugin is recommended.
Misc.
Thanks to Scott Allan Wallick and the excellent Sandbox theme for code and inspiration.