Developer Introduction: Part Two

This section focuses on what happens when we sent a request to your site, and how concrete5 handles the request. In concrete5, your reuests are handled through the dispatcher. If you'd like to take a look at the file for yourself, go ahead-- it's located at concrete/dispatcher.php. You'll notice there's a lot going on in there! As we step through each part of this file, we'll gain some insight into everything that happens behind the scenes before a page is rendered.

The Dispatcher

Key concepts:

The dispatcher controls and routes requests. The dispatcher is called by the index.php file that that lives in the root of your site. Requests are routed to the dispatcher, and the dispatcher performs a number of tasks / checks before rendering the page.

All requests are routed through the concrete5 dispatcher. Checking out your site's index.php, you'll notice that it consists of a single line:


What does the dispatcher do? In order:

It sets up the C5_EXECUTE constant with a value of true.

if (!defined("C5_EXECUTE")) {
define('C5_EXECUTE', true);

It performs several startup checks to load configuration files and makes sure the dispatcher is not being called directly.

We load the call the database loader:

## Load the database ##

Load the cache library and start the cache.

We load the core libraries, then the core models.

We load theme paths, session handlers, etc.

Finally we're ready for the good stuff. We take the request to the dispatcher and get the matching collection object:

$req = Request::get();

If the collection cannot be found, the user is sent to /page_not_found:

switch($c->getError()) {
    $v = View::getInstance();

We check for maintenance mode, then create a new permissions object for the current collection:
$cp = new Permissions($c);

Now we check to make sure there's nothing wrong with the collection's permissions. If an error is returned, we render /page_forbidden:

switch($cp->getError()) {
$v = View::getInstance();

We then load the appropriate version based on the permissions object, record the page view in the site statistics table, and fire the on_page_view event:

## Fire the on_page_view Event
Events::fire('on_page_view', $c, $u)

And finally, we render the page:

$v = View::getInstance();


At first glance you may notice that there is no separate template engine or theme compiler in concrete5. Logic responsible for displaying block content is handled behind-the-scenes, giving designers and developers only a few things to learn before becoming proficient at creating their own site designs. You'll soon notice that the files that comprise a concrete5 site are made up of primarily HTML and CSS with a few concrete5-specific tags If you're familliar with chopping a static HTML website, you're almost there!

In this section we'll dissect all the components of a concrete5 theme and tell you about their roles in rendering a page.

Where are theme files located?

Themes can be found in a number of different locations on your concrete5 site.

Default themes
concrete5 ships with a number of default themes, all of which are located in:


You'll also notice a directory named core/ in there; this is the concrete5 Dashboard theme itself. This is not typically altered.

Custom themes you've created
One-off themes should be placed in the override directory at:


Themes downloaded from the Marketplace
Anything you purchase from the Marketplace will arrive in a packaged format. Packaged themes from the concrete5 Marketplace will install into their respective directories


A rule of thumb: if you'd like to modify an existing theme, copy it into your_site_root/themes before making modifications. This ensures you won't lose any work if you upgrade your concrete5 core (and its default theme) or a packaged Marketplace theme.

To learn more about how to modify an existing theme, check out the following how-to articles: Customize a core theme and Modify a packaged theme.

Theme Anatomy

Page Types

A page type defines each of the various options our theme provides for page's overall appearance. You can switch Page Types by clicking "Design" while a page is in edit mode. Names like Right Sidebar, Full Width, Blog Entry, etc might sound very familiar to you. Taking a look at Greek Yogurt, we'll see that these correspond to individual files in your theme's root folder:





Open any of these in a text editor. Inside each, we see a mix of HTML and PHP-- there's no special logic, syntax or laundry list of short codes to learn.


Page types are where we create concrete5's editable Areas. You may recall this snippet of code from earlier in our discussion of collections and areas:

$a = new Area('Sidebar');

Every time this code runs on a page, it renders an area. By simply replacing static HTML content-- text, images, anything you want to replace with concrete5 blocks-- with this code, you've made it editable.

Each area must have a unique name-- so if we wanted to create a second area on this page, we'll need to come up with a title other than Sidebar. Something like 'Another Sidebar' would do the trick-- just as long as it's unique to the Page Type we're trying to render.

Theme Elements

Most sites will be at least somewhat similar from one page to the next. Because of this, re-using portions of the page code is often a good idea. The most common example of this would be a header or footer that is displayed sitewide. In concrete5, themes, we call these elements.

A typical theme design would would load the header and footer elements from a subdirectory in the theme root, called elements/. While this is the most widely used standard, a different path can be used if you wish, as long as it's somewhere in your theme's folder.
Now let's take a look at a concrete5 include in action. In a text editor, open any of the page types in our Greek Yogurt theme. All begin with a call to include the header element:


Similarly, all end by calling the theme's footer element:


Now we've learned how to refer to other elements in a theme. You can use this to pull in whatever elements you've created, such as a sidebar or anything else.

Special page types

Each theme in concrete5 is required to have both of the following files present:

Because concrete5 themes are allowed to define their own page types, it's entirely possible that the next theme you activate might not include all the page types your last theme did. When this happens, concrete5 renders default.php as a fallback.

The concept of single pages in concrete5 might not be one that you're very familiar with. For the moment, all you need to know is that single pages are one-off pages that occupy a static path in your site, and often exist to display results or render special components of your site. Nevertheless, view.php is an integral part of any theme and is required for a theme to install and work properly.

view.php also has the distinction of containing its own special snippet of php, not found in regular page types. Between the usual page type header / footer includes and whatever HTML is needed to produce a basic page on your site, view.php includes this:

print $innerContent;

This line prints out the special single page content.

Creating a new page type

Let's say one of these page types-- Left Sidebar, for instance-- is almost perfect for our site, but just needs a few modifications. A good way to approach this would be to copy the left_sidebar.php file, giving it a new name-- let's call it custom_sidebar.php.

So now we've got it copied and renamed. Good! But there's one last thing we need to do: install the page type on our site.

Go back to your Dashboard and select Pages & Themes > Page Types. Click the button labeled "Add a Page Type." In the Name field, let's enter Custom Sidebar. In the handle field, give it the same name as your actual page type-- in this case custom_sidebar.

Click "Add Page Type" and you're all set.

Recent Discussions on this Topic

The actual tools urls are inverted?

I am using the latest ( version of C5 and it looks like the documentation on the tools directory scripts urls is wrong. I can access the upgrade script by typing concrete5/index.php/tools/upgrade/ while the documentation says that I should use …