Sometimes there is a block that you always want to appear on every page in your site. Rather than creating an area for it and then manually adding the block to every area, why not just hardcode the block into the page type?
For this example, we'll be hardcoding the Auto-Nav block. This code can go anywhere within the page type file that you would like.
Step 1: Create the block type object
Creating the block type takes just a single line of code. If you're not using autonav, you can determine the block type handle by looking in /concrete/blocks.
$navBT = BlockType::getByHandle('autonav');
You should see a directory that matches up to the name of the block you want to use. The directory name is the block type's handle.
Step 2: Set block properties
Depending on the block, you may need to set some custom properties. This part can be a little bit tricky, and you might have to dig into the block's code to determine exactly what you need to set.
In this example, I want the autonav block to display pages at the second level in ascending order, so I need to know the property names that I need to set, and then what I need to set them to. The best place to look for this is in the edit.php file for the block type you want to display.
In the edit.php file you should see form fields, and values for the options (if it's anything other than text input). Here are the properties and values I had to set for the autonav to display how I want it to:
$navBT->controller->displayPages = 'second_level';
$navBT->controller->orderBy = 'display_asc';
$navBT->controller->displaySubPages = 'all';
$navBT->controller->displaySubPageLevels = 'all';
Step 3: Render the block
Rendering the block only requires a single line of code:
$navBT->render('view');
The parameter passed to the render function should be the block template you want to display. By default, you should set this to view, unless you are using a custom block template.
Header Item
Hardcoding a block into a page type can save a lot of time in the long run, but there are a couple of possible downsides. The biggest is that if the block you are using adds any items to the HTML head, there's not a way to include those items, since the block doesn't start the setup process until the HTML head has already been generated.
Interactive Blocks won't work - Embed them a different way
Another gotcha: most interactive blocks (like survey, form, guestbook, etc...) will not work with this method. These blocks require a real instance of a block to function. You can get around this by adding these blocks to a scrapbook, naming the block a certain way, and embedding the block by using this code
$b = Block::getByName('my_survey_block');
$b->display();
Exceptions to the Rule
Another possible downside is that there might be instance when you don't actually want to display the block on a particular page. I've found that the best way to do this is using a page attribute. Simply create a new page attribute (checkbox type is best) and call it something like "hide_nav_block". In this case, your final code would end up looking like this:
if(!$c->getAttribute('hide_nav_block')) {
$navBT = BlockType::getByHandle('autonav');
$navBT->controller->displayPages = 'second_level';
$navBT->controller->orderBy = 'display_asc';
$navBT->controller->displaySubPages = 'all';
$navBT->controller->displaySubPageLevels = 'all';
$navBT->render('view');
}
And there you have it...a block hardcoded into a page type with the option to remove it using a page attribute!