This is the documentation for concrete5 version 5.6 and earlier. View Current Documentation

Blocks are the Concrete way of embedding bits of content and functionality into your pages. Learn more about how the end user adds blocks to pages here.

Out the box, Concrete5 comes with a number of blocks. However, while these are enough to get a lot of sites up and running, the first thing many Concrete5 developers will do is to play around with the blocks architecture. This might just be a change to a block's presentation layer; or you might need to create something completely new, like an event, calendar or product block. Fortunately, working with blocks in Concrete5 is a pretty simple process.

Basic Block Template

Here is a simple block you can download and install into your own environment. It's used in the developer tutorials. Note: you will need to upgrade to Concrete5.5 or later to use this.

Introduction

A block is a collection of files within a particular directory, which itself resides in the "blocks/" directory at the root of your website. (Another blocks directory, located within the concrete/ directory, includes blocks packaged with the CMS. To preserve the system for eventual upgrading, it's probably best not to touch these files - although their presentation layers can be overridden by including templates in your root web directory. More on this later.)

Before you install the block, let's take a look at what's included inside the basic_test/ directory.

Contents of a Block Directory

add.php

Required (Optional in 5.5+). This file is the template displayed when “adding” this block through the content management system.

edit.php

Optional, although may ultimately be required. This file is displayed when the block is in edit mode.

Both add.php and edit.php are just simple forms that are wrapped in Concrete. Typically, these form elements have the same names as their database tables columns.

controller.php

Required. This file contains some vital parameters about this particular block (its name, a description, its interface dimensions, etc…), as well as any programmatical items necessary. The block's class is also responsible for saving the block, although many simpler blocks don't even need to specify how they are saved, as long as the post variables are mapped to the block's database table columns.

db.xml

This file is required for any block that needs to save its data in the database-- which is 99% of them. (Additionally, it's required for any block if you intend to install it on a concrete5.4.x or earlier site.) This file contains statements necessary to create your block's database tables in the database, specified in the ADOXMLS format. For more information, see Creating and Working with db.xml Files

auto.js

Optional. If this file exists it is automatically included when the blocks is in add or edit mode.

icon.png

Optional. This graphic displayed in Concrete's interface whenever the block is listed.

tools/

Optional. Items in this directory can be used by the block for whatever purposes they see fit. The AutoNav block makes use of this type of functionality.

templates/

Optional. Contained within this directory are alternate views for instances of this block, which can be set as custom templates through the CMS. For example, the typical autonav block formats its entry as an unordered list, but the "Header Menu" template can be applied to the autonav block, which then restructures the menu with DIVs.

Installing a Block

Before creating a block, it helps to use an existing block from scratch, hopefully the simpler the better. For this, we've provided a very simple sample block for download in our developer downloads section.

To install this block:

  • Unzip the block.
  • Drag it to your concrete5 blocks/ folder, which will likely be empty.
  • Login to your concrete5 installation, and go to Dashboard > Stacks & Blocks > Block Types.
  • You should see the new block listed as available for installation at the top of the page, under Custom Block Types > Awaiting Installation. (Core block types will be listed below.)
  • Click install, and your block should now appear under Custom Block Types > Currently Installed.

(Please note that these instructions refer to installing blocks, not packages. If a block is wrapped up in the package format, it should be copied into the /packages folder instead, then installed from Dashboard > Extend concrtete5).

That should be all there is to it. The block will automatically have its database table created and its record added to concrete5, at which point you'll be able to add it throughout your site.

But how does our block know that it should be named "Basic Test"? And how does it create it's database during installation? To get the answer to these questions we head to "controller.php"

Installation Information 1: Properties in Controller.php

Controller.php contains data about our block, as well as methods that automatically get run when different things happen to our block. We start by extending the generic concrete5 BlockController class from the core:

class BasicTestBlockController extends BlockController {
    ....
}

Our block's folder name is basic_test. This naming convention determines the "handle" of our block. concrete5 uses this value to refer to the block. Each block in your site must have a unique handle.

Note that when we define our custom block controller class, we append the handle of our block onto the name of the core class, using camel case and omitting the underscore: BasicTestBlockController. The block folder and controller class names must follow these formats in order to install and work properly.

Required Properties

btDescription: This is the description of what the block does. It's displayed in the dashboard and in the add block interface.

btName: The name of the block.

Optional Properties

btTable: The block's primary database table. If specified, and if the block only uses this one database table, then the block will be able to automatically save its information to this table, provided the block's form fields map directly to the columns in the database.

btInterfaceWidth: The width of the modal popup dialog box that holds this block when it is added or edited.

btInterfaceHeight: The height of the modal popup dialog box that holds this block when it is added or edited.

So you see, this is how our block knew that it was supposed to be named "Basic Test": it's contained within our block's class file. As you can see, that's the extent of our test block's controller. More information could be in this controller, however (there are more examples of valid controller methods below.)

Installation Information 2: db.xml

Now that we know how our block gets its description and name during installation, let's check out how it builds its database table. In our basic test block, we've defined our database table as "btBasicTest." Now, open up db.xml in the block's directory. Inside, you'll find our btBasicTest database table defined as XML:

<?xml version="1.0"?>
<schema version="0.3">
    <table name="btBasicTest">
        <field name="bID" type="I">
            <key ></key>
            <unsigned ></unsigned>
        </field>
        <field name="content" type="X2">
        </field>
    </table>
</schema>

This should be relatively easy to read: first, we define the table as named btBasicTest. Next we define our first field, which is named bID, and is an integer type. It is also defined as unsigned, and the table's primary key. Next, we have a column named "content," which is a longtext type (that's what "X2" means.)

The schema for this file is AXMLS. You can learn more about it here, including how to specify different types of columns.

One last thing: every table specified by the controller's btTable property must have bID as its primary key. This is an integer (and not set to auto_increment.) This key maps to an entry in Concrete5's core Blocks table, and is used to join your block-specific data to Concrete5 data about the block (metadata, its positioning, versions, etc...)

Now let's take a look at how our block works. Try adding it to a page. You should see a simple form. To learn how that form is built, check out add.php

add.php

Open the sample block and check out add.php. The first thing you'll notice is that there isn't much here.

<p>Introductory paragraph text....</p>

<?php echo $form->label('content', 'Name');?>
<?php echo $form->text('content', array(
    'style' => 'width: 320px'
));?>

This code is pretty easy to read. First we have our introductory paragraph. Then, we have a label for our one form field, as output by the HTML helper. Next, the HTML helper outputs a text field with the name "content." To style the text input field, we pass through an associative array as the second option with some style information.

When a block of this type is added through the CMS, this entire block of PHP and HTML will be wrapped in a form which will control submitting the contents to Concrete. To make sure that the contents of the form are routed correctly to the blocks database table, you should name your form fields the same as your database table's columns. (Note: This is a guideline, but at the end of the day this is just a form. You can name it however you want. You don't have to use Concrete's form helper items either - although they may not be optional one day.)

Submitting the "Add Block" Form

When your block is added through the CMS, you'll see an "Add" button beneath the main content area of your add template. When you click this button, Concrete routes the request to the controller for your block, and automatically invokes the save() method.

If your block is a simple one, and doesn't need to do anything but saved the submitted fields in the database as they are, you don't even need to implement your own save() method - Concrete5's block controller will do when for you. That's why, when you check out the controller for the test block, you won't see a save() method at all.

Editing a block with edit.php

Edit.php is the PHP file automatically displayed when a block is placed in edit mode. Most of the time it's going to be very, very similar to add.php, with some slight additions to allow passing the existing values of block fields to the form elements.

Here are the contents of our basic test block edit template:

This is the edit template for the basic test block.

<?php echo $form->label('content', 'Name');?>
<?php echo $form->text('content', $content, 
    array('style' => 'width: 320px')
);?>

This looks almost identical to the add template, but make sure that you notice the $content parameter. In our typical block controller, the value of the database columns are automatically extracted and placed in the local scope. We then pass that data to the form helper so that it can be displayed in edit mode.

What does that mean, exactly? That means that, by default, any columns in your database will, for the current bID, be available as PHP variables in your edit and view templates.

Viewing your block

The view template for your block is much like your edit template, but even simpler. It prints out the current saved values for a block, along with any specific block presentation. For an HTML content block, this might just be printing out the exact $content variable of a block. For an autonav, it might involve parsing the settings saved and building a tree based on them. For an event you might be parsing saved dates into a calendar interface.

Setting Up Custom Presentation Layers for Existing Blocks

For many sites, the blocks included with Concrete will be enough. And for others, you'll need to create your own completely customized. However, if you find yourself wanting to use a block that's built-in with Concrete, but with a custom template just for your site, this is the section for you.

Updating the global template for a built-in block

Say you want your autonav block to always use DIVs instead of list elements. Instead of updating blocks/content/autonav/view.php (which would then be overwritten when an upgrade occurs), create blocks/autonav.php in your root web directory. This template will then automatically be used by your autonav block.

Creating extra custom templates for blocks

To create a custom template for a block that's then available in the "Choose Custom Template" dialog box, Create a "templates/" directory within a directory corresponding to your block in your local blocks directory. Whew. What a mouthful. How about an example?

Let's say you want to create a new template for your autonav block. The built-in autonav template is mostly fine, but you want a "breadcrumb" template as well. In your local blocks/ directory (which is typically empty when you install Concrete5), create

autonav/templates/breadcrumb.php

Paste the code from concrete/blocks/autonav/view.php into this file, and then modify as necessary. Then, when you wish to use this template, click on the block you'd like to modify, and select "Choose Custom Template" from the menu. Your "Breadcrumb" template should appear in the select menu.

Additional optional methods in your block's controller

With most blocks, there will be no need to override these in your controller. However, if your block is more complex, you'll have to. The following methods are using by your blocks in certain situations:

install()

This automatically runs when a block is installed. Typically it parses the block's db.xml file, but if you need to setup new directories or write some other items into the database, this is where to do it

save($args)

This method is automatically called with an associative array of keys and values when a block is added or edited.

duplicate($newBlockID)

This method is called on an existing block and given a new block ID, and is then responsible for taking all the data about the current instance and making sure that data maps to the new instance of the block.

delete()

This method is responsible for clearing out all information about a block when it's deleted.

getSearchableContent()

This method should return a string value of all the relevant text from your block that users might search the site for, concatenated together. So if your block has a title and description value, concatenate those together and return that string. Don't forget about child table content if your block has any.

IMPORTANT NOTE: Make sure to call parent::__methodname(); when you're done with your custom code.

Loading Conversation