Concrete CMS 5.7 Add PageList Block Programmatically to Page

This tutorial is over a year old and may not apply to your version of Concrete CMS.
Mar 16, 2015

In this tutorial for Concrete CMS 5.7 we will programmatically add a PageBlock to a C5 Page. We find this useful for packages where we have a SinglePage and we want to load an Area with a PageList block. The page can also be a regular C5 Page based on a PageType. If you're building a Concrete Package that creates a new PageType such as "Property Listing" adding a SinglePage with a PageList block would enable you to install a page that shows all the properties.

Overview of Adding a PageList Block to a C5 Page

Let's start with a quick overview of the process we'll use to load the C5 Page, load the PageList BlockType and then add it to the Page.

First we need to load the Page where we want to add the PageList. This tutorial is from our C5 Razor Commerce addon and we're adding the PageList block to a SinglePage. We load the SinglePage using the Page::getByPath() function. Other options are Page::getByID() or Page::getCurrentPage().

Next we need to load the BlockType using BlockType::getByHandle(). The handle for PageList is 'page_list'. If you're adapting this tutorial to use with other block types one way to get a list of all the block type handles is to look in the BlockTypes DB table, column btHandle. A simpler way is too look into the folder /concrete/blocks/ the folder name for each block usually (not sure if this is mandatory) matches the handle. We need to create a $data array with required data for the Page List block. This is the most challenging part of the process and really the reason for making this tutorial because all the other steps are standard for any block. What is unique is that PageList has specific data fields required to add a new block.

We add the PageList Block to the Page using the Page->addBlock() function. We'll need a valid Area Name within our page to add the block. We've already loaded our BlockType and setup our array of required data so this function should run cleanly.

Step 1) Load the Page

// Add PageList Block
$shop_page = Page::getByPath('/shop');

Step 2) Get the PageList BlockType

$page_list_block = BlockType::getByHandle('page_list');

Step 3) Create the Data Params for the PageList Block

The easiest way we know of to find the PageList Block options is to use the C5 interface to add or edit a PageList block and use your browser inspector to view the "name" of the edit form elements. You'll find the name of the form elements matches, and this is because those options are automatically stored in the database by the parent BlockType Controller. This method has not been tested on every option available, but it works for the basic options we will start with below which are "num" and "includeName". Interestingly enough if you pass no options at all PageList Block will still be created without errors, but your pages shown will default to 0. And even if you add pages shown alone, no fields will be output. You need to output something, even if you don't want the page names in your PageList you will need to output description or other available fields.

$block_data = array(
  'num' => 25, // number of results
  'includeName' => true, // include page name
);

Step 4) Add the PageList Block to the Page

$shop_page->addBlock($page_list_block, 'Shop Content', $block_data);

Setting the PageType Option

Any of the PageList options found in the interface for adding PageList Blocks can be set by passing the $block_data to the Page::addBlock() function. In our programmatically created PageList Block we want to be able to filter by PageType. This is a common setting to use and will set the PageList to only return pages of a specific type.

The code to achieve this is simple notice the "ptID" param in the $block_data.

$block_data = array( 'num' => 14, // number of results 'includeName' => true, // include page name 'ptID' => 27, // show pages only of product type (ptID 27) );

The trick is we need to get that ptID (PageType ID) and usually we don't know it. If we have the PageType loaded already we could use $pt->getPageTypeID().

$block_data = array( 'num' => 14, // number of results 'includeName' => true, // include page name 'ptID' => $pt->getPageTypeID(), // show pages only of the PageType loaded into $pt );

If we don't already have the PageType we want loaded into $pt we can use PageType::getByHandle to load it.

use PageType;

$pt = PageType::getByHandle( 'product' );

$block_data = array( 'num' => 14, // number of results 'includeName' => true, // include page name 'ptID' => $pt->getPageTypeID(), // show pages only of the PageType loaded into $pt );

Adding Sort Options to the C5 PageList Block

We set the "orderBy" param in our $block_data array to set sorting options. The settings available to us include:

  • display_asc (Sitemap Order)
  • chrono_desc (Most Recent First)
  • chrono_asc (Earliest First) alpha_asc (Alphabetical order)
  • alpha_desc (Reverse alphabetical order)
  • random (Random)

$block_data = array( 'num'=> 25, // number of results 'includeName' => true, // include page name 'ptID' => $pt->getPageTypeID(), // show pages only of product type 'orderBy' => 'alpha_asc' // sort in alphabetical order );

Where to Run the Code to Programmatically Create PageList Blocks

If you're fairly new to coding or Concrete you may wonder where do I put this code and how might we have to adapt it for different contexts. In the use case this tutorial is based on this code is bundled into a function which is called by the Package installer PackageController::install function. This ensures that the code is only run once on the package install.

The code in this tutorial was actually tested in a SinglePage view! Probably not the best place to put it in any production site but for testing it allows us to experiment without having to uninstall/reinstall the Package it's being designed for. This allows us to refresh the single page and see the new block being instantly added. We can quickly delete old testing blocks in the interface.

Visit the original post at the Concrete Canada blog to see the options cheat sheet that we have there in the sidebar.

Recent Tutorials
Setting addon/theme version compatibility in the marketplace
Jan 9, 2024

For developers worn out with setting the latest addon or theme version manually across too many core versions, here is a JavaScript bookmarklet to do it for you.

How to get the locale of a page
Jan 8, 2024
By mandako.

Now, why don't we just have a getLocale() method on Page objects beats me, but here's how you work around it

Using a Redis Server
Jun 16, 2023
By mlocati.

How to configure Concrete to use one or more Redis servers to persist the cache.

Using the Concrete Migration Tool Addon
Apr 27, 2023

How to use the Concrete CMS Migration Tool

How To Add Page Last Updated To Your Concrete CMS Pages
Mar 7, 2023

Concrete CMS has a page attribute you can add to a global area called "Page Date Modified." Here's how to add it

How To Exclude Subpages from Navigation
Dec 24, 2022

How to exclude subpages from navigation - useful for a news or blog link in your main navigation where you don't want all the subpages to appear in a drop down menu.

Improvements?

Let us know by posting here.