In this chapter we will cover the following topics:
Getting the current Page object
Getting a Page object by its ID
Getting a Page object by its path
Getting a Page type by its ID
Getting a Page type by its handle
Getting a page type's ID
Getting a page type's name
Getting a page type's handle
Getting the icon for a page type
Getting a list of pages that belong to a page type
Creating a page type
Updating a page type
Deleting a page type
Creating a page type
Updating an existing page
Setting page attributes
Getting a page attribute
Getting a page's ID
Getting a page's path
Getting a page's handle
Getting a page's name
Getting a page's description
Getting a page's page type ID
Getting a page's page type handle
Getting a page's theme object
Getting the children below a page
Moving a page
Deleting a page (and its children)
Getting a list of pages
Adding a page selector field to a form
At the center of almost any content management system is the concept of pages. concrete5 pages contain reusable portions of content called
blocks. Blocks can contain anything from formatted text content that you enter yourself, to photo slideshows, to videos, to custom forms that you have developed that contain special functionality. concrete5 pages are extensions of the internal Collection
object, which gets its name from the fact that it contains a collection of blocks that make up the page.
Since pages on a website usually contain repeating areas of information (perhaps a sidebar with some persistent widgets), concrete5 includes the concept of page types. Page types allow you to define different templates for creating new pages in concrete5. They are used to specify a default set of blocks, content, and special attributes that are added to new pages of that type, as well as to create different visual layouts through the concrete5 website.
A common page type would be
Left Sidebar, which contains a list of links in the sidebar with an area to add blocks of content on the right. A normal concrete5 installation comes with a few default page types out of the box, including Left Sidebar and Full Width. In code, page types are referred to either by their unique numerical ID in the database, or more commonly, a human readable identifier called a handle. The Left Sidebar page type, for example, would have a handle of left_sidebar
.

When adding pages to a concrete5 website through the user interface, you will likely notice that the first step is choosing a page type. Page types are also used by the Composer feature of concrete5, which can assist in creating several pages of the same type (such as blog posts).
There are two types of pages in concrete5, the first being a standard page that gets added to the sitemap and gets assigned a page type, and the second a single page, which is handled a bit differently and does not get assigned a page type. This chapter will deal with pages of the first type.
Typically, you will write code that interacts with pages and page types in a block, a controller, or a model in your concrete5 application. For the purpose of these demonstrations, you can place the code anywhere where concrete5 lets you execute arbitrary PHP code.
A great place for this is to add a site_process.php
or site_post.php
file to your site's root /config
directory. concrete5 will execute all of the code in that file once all of the core classes and libraries have been loaded (site_post
gets executed before the current page has been loaded, site_process
gets executed after the current page has been set). We will use classic PHP debugging techniques to verify that our code is working. Typically, we will dump the contents of a variable using PHP's var_dump
or print_r
functions followed by an exit
command.
Because the debugging techniques used in this book can interrupt the regular functionality of a concrete5 website, it is recommended that you perform these exercises on a development copy of concrete5.
Be sure to comment out or remove the debugging code once you are finished, to resume the normal functionality of your concrete5 website.
To aid in the dumping of variables, we can create a simple debugging function that will wrap our output in <pre>
tags and automatically exit
for us.
Place the following code at the top of /config/site_post.php
(create the file if it does not exist):
function my_debug($var) { echo '<pre>'; print_r($var); echo '</pre>'; exit; }
Tip
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
Now, when we wish to inspect the contents of a variable or other object, we can simply call my_debug($variable)
, and get a nicely formatted, easy to read response.
Of course, you are more than welcome to use your own techniques for debugging variables.
A very common task for concrete5 developers is to retrieve information from the page that is currently displayed. You will encounter this situation quite often, whether you need to update some information about the current page (such as a page title), check the current user's permissions on this page, or just display the page title. Fortunately, this is quite simple.
The steps for getting the current Page
objects are as follows:
Create
/config/site_process.php
if it does not exist.Open
/config/site_process.php
in your preferred text editor.We can get the current
Page
object by calling the getCurrentPage static function of the Page class.$currentPage = Page::getCurrentPage();
If we inspect the contents of the
$currentPage
variable, we can see that it is aPage
object, and now we are ready to perform further operations on it. In this example we are using our custom debugging function that was created in the chapter introduction.my_debug($currentPage);
Calling the static
getCurrentPage
function on the Page
class will look in the concrete5 Request
object to get the current page. If that is not set, concrete5 will use the global $c
variable. Note the use of site_process.php
to dump the current page variable. We used this file because it is read after concrete5 has set the current Page
object. Using site_post.php
would have resulted in a null object.
In many situations, you will need to load a Page
object using its unique numerical ID from the database. As mentioned earlier, pages are actually extensions of the Collection
object, so you will actually be loading the page by its collection ID.
We will need to know the numerical ID of the page that you are attempting to load. Often this will be stored in other objects, perhaps even a custom entity that you have stored in the database. For example, say you have a recipes table in the database, and each recipe has its own page in the concrete5 website. You store the page ID for each recipe, so you can load the relevant Page
object whenever necessary.
First you will have to get the page ID for the Page
object that you are trying to load. For this example, we will just hard-code the ID of the page that we are loading. The steps are as follows:
Open
/config/site_post.php
in your favorite code editor.First, let's store the ID of the page we are loading into a variable. In real-world use, you will likely have this ID stored in a database table, or available from some other code that you have run. The ID of the home page in concrete5 defaults to
1
, so we will use that for our page's ID:$pageId = 1; // load the home page
Now that we have the ID of the page that we need to load, use the
getByID
function to get thePage
object that we need:$page = Page::getByID($pageId);
We can inspect the
$page
variable and verify that it contains aPage
object.my_debug($page);
concrete5 also supports the loading of Page
objects by the path that is displayed in the web browser. This is a convenient way to load pages without knowing their numerical ID. In this exercise, we will load an About Us page by its path.
We will be loading a page with the path of /about-us
. If this page does not exist in your concrete5 site, please add it to the sitemap before attempting this exercise.
Using a static function called getByPath
, we can easily get a Page
object without knowing the ID. The steps are as follows:
Open the
/config/site-post.php
file in your code editor.Declare the path of the page that you wish to load.
$path = '/about-us';
We can load the page located at
http://example.com/about-us
by passing the path string to thegetByPath
function.$aboutPage = Page::getByPath($path);
To make sure we grabbed the correct page, dump the
$aboutPage
variable to verify that we have a fully loadedPage
object. We will use the custom debug function that we created in the chapter introduction.my_debug($aboutPage);
concrete5 will query the database for the page that has the specified path assigned to it. You will want to use good judgment when loading pages by their paths, as that data can change easily through the concrete5 interface. Imagine that you are working on a site with 15 editors, and any one of them has the ability to edit the path of a page. concrete5 by default will save old page paths whenever a new one is changed, but it is not required. Hard coding page paths in your custom applications should be used only when appropriate. It is a much better idea to load pages by their ID whenever possible, as that ID does not change.
You can load any page on the site using this technique. To load a Careers
page that exists below the About
page that we just loaded, you would write the following:
$careersPage = Page::getByPath('/about-us/careers');
You should know that concrete5 will cache the page IDs related to each path, so if you are experiencing unexpected results while using this function, make sure to clear your site cache by visiting /dashboard/system/optimization/clear_cache/
on your concrete5 website.
When creating and editing pages in concrete5 development, you will inevitably need to load the desired page type object that will be assigned to a page. Note that page types are actually instances of the CollectionType
object in code. For consistency, we will continue to refer to them as page types outside of code.
We will continue performing these examples in the /config/site-post.php
file, as that is a quick and easy place to run the arbitrary code. We will also continue making use of our custom my_debug
function that was defined in the chapter introduction.
In this recipe, we will be loading a page type with the ID of 4
. Please make sure that this page type exists in your instance of concrete5, otherwise change the ID to something appropriate to your environment.
Much like loading pages, you will need to call a static function on the CollectionType
class. The steps are as follows:
Open
/config/site_post.php
in your text editor.First, we will need to know the numerical ID of the page type. In this case, we are going to assume that a page type called "Left Sidebar" exists, and that it has the numerical ID of
4
.$leftSidebarId = 4;
Now that we have the ID of the page type that we wish to load, we can call the
getByID
function of theCollectionType
class.$leftSidebarPageType = CollectionType::getByID($leftSidebarId);
We can verify that we loaded the correct page type by inspecting the
$leftSidebarPageType
variable and verifying that it is an instance of theCollectionType
class.my_debug($leftSidebarPageType);
As mentioned in the chapter introduction, page types also have human readable handles, which offer a convenient way of loading page types without knowing their numerical IDs. Handles are always alphanumerical strings with underscores between words, and do not contain any file extensions such as .php
. For example, the handle for a page type called "Left Sidebar" would most likely be left_sidebar
, but concrete5 lets users specify any alphanumeric string for a handle, so it's possible that the handle for Left Sidebar would also just be left
.

You can find the handles of page types by visiting the Page Types area of the concrete5 dashboard, located at /dashboard/pages/types/
on your concrete5 website.
In this recipe, we will be loading a page type with the handle of left_sidebar
. Please make sure that page type exists in your concrete5 installation, otherwise you can add a new page type with that handle, or adapt the recipe to work for your situation.
Here's how we would load the page type with a handle of left_sidebar
. This is similar to loading a page by its path. The steps are as follows:
Open
/config/site_post.php
in your preferred code editor.Declare the handle of the page type that you wish to load.
$handle = 'left_sidebar';
Load the page type using the handle that we just defined.
$pageType = CollectionType::getByHandle($handle);
You can verify that you have loaded the page type by dumping the
$pageType
variable.my_debug($pageType);
A simple database query is performed, which will return a CollectionType
object if it is successful.
Just like the warning for loading pages by their paths, you will want to exercise the same good judgment when loading page types by their handles. Since these handles are just strings that can be edited through the concrete5 interface, you will need to make sure that you aren't writing code that could break if one of the site editors changes the handle of a page type.
Once a page type has been loaded, we can get different information from it. Sometimes, if a page type is loaded by its handle, or if it was provided from another function call, developers will need to get the page type's ID from an existing page type object. In this exercise, we will load a page type by its handle, and then find out the ID of the page type.
We will be loading a page type with a handle of right_sidebar
in this example. If that page type does not exist in your concrete5 system, feel free to adapt this recipe to suit your specific situation.
The steps for getting a page type's ID are as follows:
Open
/config/site_post.php
in your code editor.Load the page type by its path:
$pageType = CollectionType::getByHandle('right_sidebar');
Get the ID from the page type.
$id = $pageType->getCollectionTypeId();
Dump the page type ID (we are using the custom debugger explained in this chapter's introduction).
my_debug($id);
Page type objects also contain methods to retrieve the name of the page type. In this exercise, we will load a page type by its handle, and then retrieve the name of the page type.
We will be loading a page type with the handle of right_sidebar
, so if that page type does not exist in your instance of concrete5, please adapt this recipe to suit your needs.
The steps for getting a page type's name are as follows:
Open
/config/site_post.php
in your preferred code editor.Load the page type by its handle:
$pageType = CollectionType::getByHandle('right_sidebar');
Get the name of the page type.
$name = $pageType->getCollectionTypeName();
Dump the name using our custom debugger.
my_debug($name);
If a page type has been loaded by its ID or has been provided in a different manner, developers may want to retrieve the handle of the page type. In this example, we will load a page type with an ID of 4
and use the concrete5 API to get its handle.
We will be loading a page type with an ID of 4, so please ensure that this exists in your concrete5 website. Feel free to change the ID in this recipe to something appropriate for your instance of concrete5.
The steps for getting a page type's handle are as follows:
Open
/config/site_post.php
in your preferred code editor.Load the page type by its ID.
$pageType = CollectionType::getByID(4);
Get the handle of the page type.
$handle = $pageType->getCollectionTypeHandle();
Dump the handle using our custom debugger function.
my_debug($handle);
In the concrete5 dashboard interface, page types have icons associated with them. In some advanced applications, you may want to retrieve the icon for the page type. In this recipe, we will load a page type by its handle and get its icon.
We will be loading a page type with a handle of right_sidebar
. Feel free to change this handle to something appropriate for your concrete5 instance if right_sidebar
does not exist.
The steps for getting the icon for a page are as follows:
Open
/config/site_post.php
in your favorite code editor, as this is a good place to try out random code.Load the page type by its path.
$pageType = CollectionType::getByHandle('right_sidebar');
Get the icon image.
$icon = $pageType->getCollectionTypeIconImage();
Output the image. You should see the icon's image appear.
echo $icon; exit;
If you would like to get the numeric ID of the file containing the page type icon, you can simply call this function:
$iconId = $pageType->getCollectionTypeIcon();
The numeric ID is useful when working with the file manager in concrete5, which is discussed in detail in Chapter 3, Files and File Sets of this book.
In many advanced concrete5 applications, developers may need to find a list of all of the pages that belong to a given page type. In this example, we will get an array of pages that have a page type with the handle of right_sidebar
.
If your instance of concrete5 does not have a page type with the handle of right_sidebar
, feel free to adapt the recipe to suit your needs. We will continue using /config/site_post.php
as our sandbox to run random code snippets, as well as our custom debugging function that we created in this chapter's introduction.
The steps for getting a list of pages belonging to a page type are as follows:
Open
/config/site_post.php
in your code editor to try out the following code.Load the page type by its handle.
$pageType = CollectionType::getByHandle('right_sidebar');
Get the array of
Page
objects.$pages = $pageType->getPages();
Dump the array to see its contents.
foreach ($pages as $page) { echo $page->getCollectionTitle().'<br />'; } exit;
concrete5 simply uses the relational MySQL database to find all of the pages that are related to the page type. Be aware that concrete5 ignores permissions settings when this function is called, so this should really only be used for internal purposes.
You can easily add new page types through the concrete5 user interface, but there are some situations that can require you to create page types dynamically using PHP code.
First, you will need to create an associative array that contains the data of the page type that you are creating.
The array can contain the following fields:
We will create a page type using only the required fields: ctHandle
and ctName
. The steps are as follows:
Open
/config/site_post.php
in your preferred code editor.Declare the handle of the new page type to be created.
$handle = 'page_type_handle';
Declare the array that contains the data for the
ctHandle
andctName
fields.$data = array( 'ctHandle' => $handle, 'ctName' => 'Page Type Name' );
Check to see if the page type already exists by loading it by the new handle.
$pageType = CollectionType::getByHandle($handle);
If the page type does not exist, create it.
if (!$pageType) { $newPageType = CollectionType::add($data); }
If it does exist, assign the existing page type to the new page type variable.
else { $newPageType = $pageType; }
Dump the new page type variable to ensure that it worked.
my_debug($newPageType);
concrete5 will take the data array that you pass in and use it to create a new CollectionType
record in the database. concrete5 will also automatically generate a Master Collection page in the database. The Master Collection is a template page that concrete5 will use as base for all pages of that type. Any blocks, attributes, or other data assigned to the Master Collection will automatically be added to any new pages created with that page type.
If you are creating this page type in a custom package, you will need to pass in your package object to the add()
function, so concrete5 knows that this page type belongs to your package. That way, when users uninstall your package, they will have the option of removing all of the page types that it created.
Assuming that you know the handle of your package, use the following code to create a page type with it:
$data = array( 'ctHandle' => $handle, 'ctName' => 'Page Type Name' ); $pkg = Package::getByHandle('my_package'); $newPageType = CollectionType::add($data, $pkg);
Updating page types is very similar to creating a page type as discussed in the previous recipe.
First you will need to load an existing page type. You will need to pass in the same data array when updating page types as you would when creating them. The steps are as follows:
Open
/config/site_post.php
in your code editor.Declare the old handle and the new handle variables.
$handle = 'page_type_handle'; $newHandle = 'new_handle';
Define the new
$data
array with the new handle and new name.$data = array( 'ctHandle' => $newHandle, 'ctName' => 'New Name' );
If the page type exists, update it.
$pageType = CollectionType::getByHandle($handle); if ($pageType) { $pageType->update($data); }
Verify that the page type was updated by visiting
/dashboard/pages/types
in your concrete5 website.
In addition to adding and editing page types, you can also delete them.
Since deleting page types is a destructive action that is irreversible, it's a good idea to create a dummy page type with the handle of delete_me
for this exercise. We will also continue using site_post.php
to execute arbitrary code.
The steps for deleting a page type are as follows:
Open
/config/site_post.php
in your preferred code editor.Define the handle of the page to be deleted.
$handle = 'delete_me';
Load the page type by its handle.
$pageType = CollectionType::getByHandle($handle);
Now, delete the page type.
$pageType->delete();
The delete()
function deletes the page type, the Master Collection, and all of the pages that use it. Use this function very cautiously, as once the data has been deleted, it cannot be recovered (unless you have a backup copy of the site's database).
Creating pages dynamically is a central concept of concrete5 development and can unlock a lot of powerful features in custom applications. Imagine a concrete5 website that has a recipes database. You could make it so, that every time a recipe is added to the database, a new page for that recipe is added to the sitemap, immediately improving the depth of content on your website, its usability, and even search engine performance.
In this example, we will create an "About Us" page and add it to the sitemap.
We are continuing the practice of putting our code in /config/site_post.php
for the purposes of demonstration and testing. In real-world use, your dynamic page creation would happen in controller files or in add-on packages.
We will be assigning the new page a page type with the handle of right_sidebar
. If this doesn't exist in your own concrete5 installation, please adapt the recipe to suit your needs.
The steps for creating a page are as follows:
Open
/config/site_post.php
in your code editor.Load the page type that the new page will use. We will load the page type using its handle (
right_sidebar
, in this case).$pageType = CollectionType::getByHandle('right_sidebar');
Create an associative array that contains the fields that you wish to specify for the new page. In this example, we will only specify the page's name and handle.
$data = array( 'cName' => 'About Us', 'cHandle' => 'about' );
Load the parent page that the new page will be placed under. In this case, we are loading the home page, since the new page will be available at the top level.
$parent = Page::getByID(1);
Add the page by passing the
$pageType
object and$data
array to the add function of the parentPage
class.$newPage = $parent->add($pageType, $data);
Output a message and exit the process.
echo 'done!'; exit;
Visit your site's homepage to execute the code in
site_post.php
.If you see the success message, comment out the code in
site_post.php
so you can visit the newly created page. Otherwise, concrete5 will create a new page every time the site is loaded into a browser.Visit the newly created page at
http://example.com/about
.
The add()
function is a wrapper for the Collection
class's add()
function. Calling it will create a new Collection
record in the database, and a new pending CollectionVersion
record (which will be approved if the cvIsApproved
variable is set to true
or left blank). Then the new page will inherit the necessary permissions and get all of the blocks and other attributes from the Master Collection of the related page type.
You will need to provide two parameters to the add()
function, a CollectionType
object (which we worked with earlier in this chapter), and an associative array containing all of the data needed to create the page. The associative array can contain the following fields.
Updating pages is similar to creating them in that you must first pass in an associative array containing all of the data that you wish to update on the page.
In this recipe, we will be modifying a page with the path of /about
. We created that page in the previous recipe, but if it does not exist on your system, please adapt the code to your needs.
In this example, we will update the name of the About
page. The steps are as follows:
First, we need to load the
Page
object by its path.$page = Page::getByPath('/about');
Create an associative array with the data that you wish to update.
$data = array( 'cName' => 'About Our Company' );
Pass the data array into the
$page
object's update function.$page->update($data);
Output a success message and exit the process.
echo 'done!'; exit;
The update
function updates the necessary tables in the database with the newly specified information. concrete5 will also rescan all permissions for this page and all of the related page paths. When the function is complete, the on_page_update
event is fired, which you can write custom code to listen to and perform custom actions when a page is updated. Listening to system events is covered in a later chapter.
Just like creating a page, you will need to pass an associative array to the update()
function in order to update an existing page. You can use all of the fields specified in the previous recipe for adding a page, in addition to these other optional fields.
Pages, like most objects in concrete5, can have any type of custom attribute attached to them. This allows for immense flexibility, but it can be difficult to read and write these attributes using raw SQL. The concrete5 API makes setting and reading page attributes easy.
You will need to know at least the handle of the attribute key that you wish to assign to the page. A common attribute to set is the Meta Title
attribute, which updates the text that appears in the HTML <title>
tag.
We will set the Meta Title
attribute to the About Us page in this example. The steps are as follows:
Open
/config/site_post.php
in your preferred code editor.Load the
Page
object that you wish to set the attribute on.$page = Page::getByPath('/about');
Call the
setAttribute
function on the$page
object, passing in two parameters: the attribute handle (key), and the value.$page->setAttribute('meta_title', 'New Page Meta Title');
Output a success message and exit the process.
echo 'done!'; exit;
The setAttribute
function is a member of the Collection
class, which the Page
class extends. It requires that you provide two parameters, an attribute key (which can either be a string representing the attribute key handle (which we provided here), or an actual AttributeKey
object), and the value.
The setAttribute
function is very handy for setting the data of any kind of page attribute. One can update a page's meta information (such as description, keywords, and title) and also give the page various options, such as, excluding it from the navigation (as seen previously) or from the sitemap.xml
file that search engines look for.
You can update any attribute that has been installed in the concrete5 system. To see all available page attributes, or to create new ones, visit the Page Attributes area of your site's dashboard (located at /dashboard/pages/attributes/
).
In addition to being able to set page attributes, developers can also retrieve attributes just as easily. In this exercise, we will get the Meta Title
attribute for the About page.
We are assuming the presence of a page with the path of /about
in this recipe. If that page does not exist, you can create it, or adapt the code in this recipe to fit your circumstances.
The steps for getting a page attribute are as follows:
Open
/config/site_post.php
in your preferred editor. This is a good place to run some arbitrary code.Load the
Page
object.$page = Page::getByPath('/about');
Get the
meta_title
attribute.$title = $page->getAttribute('meta_title');
Dump the variable using the custom debugging function that we created in the chapter's introduction.
my_debug($title);
concrete5 uses the attribute handle string to find the appropriate record in the database and return its value. concrete5 stores attributes in the EAV format (entity, attribute, value), and this makes it difficult to read these values directly with SQL queries. The concrete5 API simplifies this for developers.
Developers will often need to know a page's ID, especially when relating pages to other database objects (such as a blog post or calendar event). In this example, we will load the /about
page that we've been working with and get its ID.
Please make sure the /about
page exists in your instance of concrete5. Feel free to modify the code in this recipe if that page does not exist.
The steps for getting a page's ID are as follows:
Open
/config/site_post.php
in your code editor.Load the
Page
object by its path.$page = Page::getByPath('/about');
Get the page's ID.
$id = $page->getCollectionId();
Dump the contents of the
$id
variable to see what the ID is.my_debug($id);
In addition to being able to get a page's ID, developers can also retrieve the path for a page. In this recipe, we will load a page by its ID and then retrieve its path.
The steps for getting a page's path are as follows:
Open
/config/site_post.php
in your preferred code editor.Load the page by its ID. We will use the ID of
4
here, which should belong to a page on the dashboard.$page = Page::getByID(4);
Get the page's path.
$path = $page->getCollectionPath();
Use the custom debugging function to output the path.
my_debug($path);
Pages, like page types and other objects in concrete5, have handles in addition to paths. The handle is similar to a slug in other content management systems. In this exercise, we will load a page by its ID and then retrieve its handle.
The steps for getting a page's handle are as follows:
Open
/config/site_post.php
in your code editor.Load the page by its ID.
$page = Page::getByID(4);
Get the page's handle.
$handle = $page->getCollectionHandle();
Dump the handle variable to see its contents.
my_debug($handle);
Page names are often used as the de facto titles in concrete5. In this exercise, we will load a page by its path, and then get its name.
The steps for getting a page's name are as follows:
Open
/config/site_post.php
in your editor.Load the page by its path.
$page = Page::getByPath('/about');
Get the page's title.
$name = $page->getCollectionName();
Dump the contents of the title variable.
my_debug($name);
Page descriptions are not used very widely used in concrete5. Some themes will treat them as content excerpts, while other add-ons will use descriptions as a generic attribute storage area. Regardless, they are still built into concrete5, and in this recipe we will load a page by its path and retrieve its description.
Many pages in concrete5 do not have descriptions. If you wish, you can edit a page to add a description as shown in the following screenshot:

The steps for getting a page's description are as follows:
Open the
/config/site_post.php
file in your code editor.Load the page by its path.
$page = Page::getByPath('/about');
Get the page's description.
$description = $page->getCollectionDescription();
Dump the contents of the description variable.
my_debug($description);
As we discussed earlier in the chapter, pages are assigned a page type. In this recipe, we will get the page type ID from a Page
object.
The steps for getting a page's page type ID are as follows:
Open
/config/site_post.php
in your code editor, so we can run some arbitrary code.Load the page by its path.
$page = Page::getByPath('/about');
Get the page type ID for this page.
$pageTypeId = $page->getCollectionTypeID();
Dump the page type ID using our custom debugging function.
my_debug($pageTypeId);
In addition to being able to retrieve the ID of a page's page type, developers can also get the handle.
The steps for getting a page's page type handle are as follows:
Open
/config/site_post.php
in your code editor, since we will just be running some arbitrary code.Load the page by its path.
$page = Page::getByPath('/about');
Get the page type handle.
$handle = $page->getCollectionTypeHandle();
Dump the handle variable to see its contents.
my_debug($handle);
Every page can have its own individual theme in concrete5. While it's typical for most sites to only use one global theme, concrete5 does allow developers to set individual themes for each page. In this recipe, we will get the page's theme object, which can be used to see what theme is active on a given page.
The steps for getting a page's theme object are as follows:
Open
/config/site_post.php
in your preferred code editor.Load the page by its path.
$page = Page::getByPath('/about');
Get the theme object.
$theme = $page->getCollectionThemeObject();
Dump the theme object to inspect the class.
my_debug($theme);
If you need to access the children of a page, you can have concrete5 return an array of numerical IDs. These IDs can then be used to load each of the Page
objects individually.
The steps for getting the children below a page are as follows:
Open
/config/site_post.php
in your preferred code editor.Load the parent page by its ID.
$page = Page::getByID(1);
Get the array of child IDs.
$children = $page->getCollectionChildrenArray();
Loop through the child ID array and output the name of each page.
foreach ($children as $childId) { $child = Page::getByID($childId); echo $child->getCollectionName().'<br />'; }
Exit the process.
exit;
concrete5 will return an array of numeric IDs for each of the pages beneath the parent page. In this example, we loaded the home page, so the result should be a list of every page on the website. This function ignores permissions, and can be taxing on the database if there are a lot of pages to load. It is a better idea to use the PageList
class to loop through pages, and that class is described later on in this chapter.
The concrete5 sitemap is a great tool for managing the page hierarchy of your website. It lets you arrange the order of pages, and even drag-and-drop pages to different areas of the site. Thankfully, you aren't limited to using the graphical interface to move pages around the site. You can also rearrange pages dynamically in your custom concrete5 applications.
In this example, we are going to move a Careers page underneath the About Us page. Before we can move a page, we need to have the Page
object of the new parent page that we are moving the current page to.
This exercise assumes that pages exist at both /about
and /careers
in your concrete5 site. You can create those pages through the concrete5 interface, or adapt the code in this recipe to work with pages that exist on your own site.
The steps for moving a page are as follows:
Open
/config/site_post.php
, as that is a safe place to play with some random code.First, load the About Us page, which is where the Careers page will be moved to.
$newParent = Page::getByPath('/about');
Now, we need to load the careers page that we are moving.
$careersPage = Page::getByPath('/careers');
Finally, call the
move
function on the careers page, passing it the new parent page and an optional Boolean which tells concrete5 if we want to save the old page path as well as the new one.$careersPage->move($newParent, true);
The move function is very easy to use. You only need to provide one parameter, which is a Page
object of the new parent that you are moving the page under. There is an optional second parameter to indicate if you wish to retain the old page path in addition to the current one. That parameter defaults to false.
Once the page is moved, it will inherit the permissions of the new parent page (if the page does not have its own permissions set explicitly).
Once the page is moved, the event on_page_move
is fired.
Listening to system events in Chapter 9, System Events and Advanced Configuration
The Getting a Page object by its path recipe
concrete5 also makes it easy to delete pages from the sitemap.
Deleting pages is a permanent destructive action. When experimenting with this code, it would be a good idea to create a dummy page with a path of /delete-me
.
We will permanently delete the about us page and all of its child pages. The steps are as follows:
First, load the page that you wish to delete. We will delete a dummy page.
$page = Page::getByPath('/delete-me');
Call the
delete()
function on thePage
object.$page->delete();
concrete5 will fire the on_page_delete
event before any actual deleting occurs. After the event fires, the page (and all of its children) are deleted from the database. This operation is permanent, so it is important to make sure that you only delete pages when you are certain that they are no longer needed.
If you don't want to permanently delete a page, you can move it to the Trash. As of concrete5 version 5.5, pages can be "temporarily" deleted and moved under a special internal page called the Trash.
$page->moveToTrash();
Many applications will have a need to get a list of pages and perform various filter and sorting functions on the list. For this, there is the PageList
class, which exposes many convenient helper functions to assist in working with large lists of pages.
In this example, we are going to find all of the pages under the /blog
page. This is a common use of the page list model. The PageList
class is not automatically loaded by concrete5, so we will need to use the Loader
class to have it available to us.
If your site does not have a page located at /blog
, it would be helpful to create that page, as well as a few child pages below it. Otherwise, feel free to adapt the code in this recipe to suit your needs.
In this recipe, we will get a list of 20 pages that exist under /blog
in the sitemap. The steps are as follows:
First, we must make the
PageList
class available for us to use.Loader::model('page_list');
Create a new instance of the
PageList
class. We will assign it to a variable called$list
.$list = new PageList();
Filter the list to only include pages underneath the
/blog
page.$list->filterByPath('/blog');
Limit the list of pages to only include the first 20 results.
$list->setItemsPerPage(20);
Run the database query and get the first "page" of results, which will return an array of 20
Page
objects.$pages = $list->getPage();
Dump the contents of the pages variable to see the array.
foreach ($pages as $page) { echo $page->getCollectionTitle().'<br />'; } exit;
The PageList
class extends the core DatabaseItemList
class, which has a number of useful functions itself. The
get()
function accepts two parameters, the number of records to retrieve, and the offset.
The page list class implements "magic methods," which allow allow us to filter the list by any page attribute. We simply need to create a function name based off of the camel cased version of the attribute handle, preceded by "filterBy". So to filter all pages that have the exclude_nav
attribute, we would write the following function:
$list->filterByExcludeNav(true);
Alternatively, if you want to just get an array of the first 99 Page
objects and ignore pagination, use the
get()
function.
$pages = $list->get(99);
Since version 5.5, concrete5 uses Twitter's open source Bootstrap CSS framework for many of their internal styles. You can get the pagination controls in nicely formatted HTML (with relevant Bootstrap CSS classes) by printing/echoing the results of the following function (preferably you'd use this function in a view or template file of a block or single page):
echo $list->displayPagingV2();
The DatabaseItemList
class and
PageList
class have several functions that make working with a collection of pages easier. You can filter by keywords, by collection type, parent page, and by any attribute using magic methods. We will cover the DatabaseItemList
class further in Chapter 5, Working with Databases and Models.
It is easy to add a page selector field to a form. When clicked on, the sitemap will appear in a modal window, allowing for easy browsing and selecting of a page. This allows for user friendly custom applications that can allow users to attach pages to any type of custom object, like a blog post or cooking recipe, for example.
We will need to use the FormPageSelectorHelper
class, which we will need to load using the Loader
library.
This recipe will need to be written inside of an HTML form somewhere in your site. We have created a basic single page for this purpose, which can be downloaded with the code from the website for this book. To install the single page, copy the code for this recipe to your concrete5 site directory and visit /dashboard/pages/single
. Add a new single page with a path of /example
.
concrete5 includes a helper to generate the necessary JavaScript and HTML text needed to show the sitemap selector widget. We will use the Loader
class to include and return the PageSelectorHelper
class, which will then return the entire HTML that we need. The steps are as follows:
Make the
pageSelector
helper class available for us to use. TheLoader
class will automatically instantiate and return the instantiated helper object when the helper gets loaded.$pageSelector = Loader::helper('form/page_selector');
Output the HTML and JavaScript required allowing users to select a page.
echo $pageSelector->selectPage('page_id');
The selectPage
function returns the HTML and JavaScript necessary to produce a page selector field. There is only one parameter required, and that is a string indicating the name of the field. concrete5 will add a hidden <input>
element to the form, which will allow the selected page ID to be read from a POST request.
In this example, once the form is submitted, you could retrieve the selected page ID by looking in the $_POST
super variable.
$pageId = $_POST['page_id'];
You can specify a page ID in the optional second parameter, which will populate the page selector with an existing page.
$page = Page::getByCollectionPath('/about-us'); echo $pageSelector->selectPage('page_id', $page->getCollectionID());
The pageSelector
helper also has a function to display a sitemap in a modal window.
$args = array( 'display_mode' => 'full' ); $pageSelector->sitemap($args);
Note that the sitemap()
function loads an element, which is automatically printed to the screen, so there is no need to echo or print the result.