BlockBundle
BlockBundle¶
This bundle provides integration with SonataBlockBundle. It is used to manage fragments of content, so-called blocks, that are persisted in a database and can be incorporated into any page layout.
The Symfony2 CMF BlockBundle also provides a few commonly used standard blocks, including the ability to edit them. See Block Types.
Installation¶
You can install this bundle with composer using the symfony-cmf/block-bundle package.
As the bundle is using the SonataBlockBundle, you need to instantiate some sonata bundles in addition to the CmfBlockBundle:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // app/AppKernel.php
// ...
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = array(
// ...
new Sonata\BlockBundle\SonataBlockBundle(),
new Sonata\CoreBundle\SonataCoreBundle(),
new Symfony\Cmf\Bundle\BlockBundle\CmfBlockBundle(),
);
// ...
}
// ...
}
|
Usage¶
The BlockBundle needs a persistence layer to be configured. This can either be done globally with the Core Bundle or individually as follows:
- YAML
1 2 3 4
cmf_block: persistence: phpcr: block_basepath: /cms/content
- XML
1 2 3 4 5 6 7 8 9 10 11 12
<?xml version="1.0" charset="UTF-8" ?> <container xmlns="http://symfony.com/schema/dic/services"> <config xmlns="http://cmf.symfony.com/schema/dic/block"> <persistence> <phpcr block-basepath="/cms/block" /> </persistence> </config> </container>
- PHP
1 2 3 4 5 6 7
$container->loadFromExtension('cmf_block', array( 'persistence' => array( 'phpcr' => array( 'block_basepath' => '/cms/block', ), ), ));
The default settings of a block are defined in the block service. If you use a
third party block, you might want to alter these for your application. Use the
sonata_block
key for this. You can define default settings for a block
service type or more specific for a block class. The later is useful when you
are using the same block service for multiple block classes but you only want
specific settings for one of the block classes.
- YAML
1 2 3 4 5 6 7 8 9 10
# app/config/config.yml sonata_block: blocks: acme_main.block.news: settings: maxItems: 3 blocks_by_class: Symfony\Cmf\Bundle\BlockBundle\Doctrine\Phpcr\RssBlock: settings: maxItems: 5
- XML
1 2 3 4 5 6 7 8 9 10 11 12 13
<!-- app/config/config.xml --> <?xml version="1.0" encoding="UTF-8" ?> <container xmlns="http://symfony.com/schema/dic/services"> <config xmlns="http://sonata-project.com/schema/dic/block"> <blocks id="acme_main.block.rss"> <setting id="maxItems">3</setting> </blocks> <block-by-class class="Symfony\Cmf\Bundle\BlockBundle\Doctrine\Phpcr\RssBlock"> <setting id="maxItems">5</setting> </block-by-class> </config> </container>
- PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// app/config/config.php $container->loadFromExtension('sonata_block', array( 'blocks' => array( 'acme_main.block.rss' => array( 'settings' => array( 'maxItems' => 3, ), ), ), 'blocks_by_class' => array( 'Symfony\Cmf\Bundle\BlockBundle\Doctrine\Phpcr\RssBlock' => array( 'settings' => array( 'maxItems' => 5, ), ), ), ));
Tip
You can also store settings in the single block objects themselves. This allows to individually configure options per block instance.
If you edit the blocks using the Sonata admin, there is also the
Block Sonata Admin Extension
that adds editing of the BaseBlock
general block options.
Updated SonataBlockBundle Defaults¶
The BlockBundle automatically changes some defaults and adds configuration to the SonataBlockBundle to make it work nicely. This is done using the prepended configuration option of Symfony. The following defaults are updated:
- templates.block_base the CMF base template wraps the block output in
a
div
and slugifies the PHPCR path as id; The base template is kept compatible with the Sonata base template for non-cmf blocks; - RssBlock configuration adds the default RssBlock settings.
Note
Settings are only prepended, meaning the default value is changed. You can still change the values by setting the configuration values in your application configuration file.
Block Document¶
Before you can render a block, you need to create a data object representing your block in the repository. You can do so with the following code snippet:
1 2 3 4 5 6 7 8 9 10 11 12 13 | use Symfony\Cmf\Bundle\BlockBundle\Doctrine\Phpcr\SimpleBlock;
// ...
/** @var $dm \Doctrine\ODM\PHPCR\DocumentManager */
$parentDocument = $dm->find(null, '/cms/content/home');
$myBlock = new SimpleBlock();
$myBlock->setParentDocument($parentDocument);
$myBlock->setName('sidebarBlock');
$myBlock->setTitle('My first block');
$myBlock->setBody('Hello block world!');
$dm->persist($myBlock);
|
Note the sidebarBlock
is the identifier we chose for the block. Together
with the parent document of the block, this defines the unique identifier of
the block. The other properties (title and body) are specific to the
Symfony\Cmf\Bundle\BlockBundle\Doctrine\Phpcr\SimpleBlock
.
The simple block is now ready to be rendered, see Block rendering.
Note
Make sure to always have your blocks implement the interface
Sonata\BlockBundle\Model\BlockInterface
or extend an existing block
document like Symfony\Cmf\Bundle\BlockBundle\Doctrine\Phpcr\AbstractBlock
.
Block Context¶
The BlockContext contains all information and the block document needed to render the block. It aggregates and merges all settings from configuration, the block service, the block document and settings passed to the Twig template helper. Therefore, use the BlockContext to get or alter a setting if needed.
Block Service¶
Internally, the block bundle uses a block service to work with each type
of block. The service is configured to handle a type of block. The
blocks themselves identify their type in the getType
method.
When using the provided blocks, you do not need to worry about the block service. It is only relevant when creating your own blocks.
Block rendering¶
Rendering is handled by the SonataBlockBundle sonata_block_render
Twig
function. The block name is either an absolute PHPCR path or the name of the
block relative to the cmfMainContent
document.
To render the example from the Block Document section, just add the following code to your Twig template:
- Twig
1
{{ sonata_block_render({'name': '/cms/content/blocks/sidebarBlock'}) }}
- PHP
1 2 3
<?php echo $view['blocks']->render(array( 'name' => '/cms/content/blocks/sidebarBlock', )) ?>
In this example, we specify an absolute path. However, if the block is the child of a content document, then you can simply specify the name of the block as follows:
- Twig
1
{{ sonata_block_render({'name': 'sidebarBlock'}) }}
- PHP
1 2 3
<?php echo $view['blocks']->render(array( 'name' => 'sidebarBlock', )) ?>
This will make the BlockBundle render the specified block if the main content
(as per the routing) maps a field named
sidebarBlock
. If different main contents are rendered using different
templates, make sure all that should support this block actually include the
snippet above.
When a block being rendered, the following things happen:
- The block document is loaded based on its name or absolute path;
- If caching is configured, the cache is checked and content is returned if found;
- Otherwise, the
execute
method of the corresponding block service is called.
The execute
method is the equivalent of a normal Symfony controller. It
receives the block object (equivalent to a Request object) and a Response
object. The purpose of the execute
method to set the content of the
response object - typically by rendering a Twig template.
Embedding Blocks in WYSIWYG Content¶
The CmfBlockBundle provides a Twig filter cmf_embed_blocks
that
looks through the content and looks for special tags to render blocks. To use
the tag, you need to apply the cmf_embed_blocks
filter to your output. If
you can, render your blocks directly in the template. This feature is only a
cheap solution for web editors to place blocks anywhere in their HTML content.
A better solution to build composed pages is to build it from blocks (there
might be a CMF bundle at some point for this).
- Twig
1
{{ page.content|cmf_embed_blocks }}
- PHP
1 2 3
<?php echo $view['blocks']->embedBlocks( $page->getContent() ) ?>
Caution
Make sure to only place this filter where you display the content and not where editing it, as otherwise your users would start to edit the rendered output of their blocks. This feature conflicts with the front-end editing provided by CreateBundle, as create.js operates on the rendered content as displayed to the user. There is an ongoing discussion how to fix this.
When you apply the filter, your users can use this tag to embed a block in their content:
1 2 3 | %embed-block|/absolute/path/to/block|end%
%embed-block|local-block|end%
|
The path to the block is either absolute or relative to the current main
content. The prefix and postfix are configurable. The default prefix is
%embed-block|
and the default postfix is |end%
. Say you want
to use %%%block:"/absolute/path"%%%
then you do:
- XML
1 2 3 4 5 6 7 8 9 10 11 12 13
<!-- app/config/config.xml --> <?xml version="1.0" encoding="UTF-8" ?> <container xmlns="http://symfony.com/schema/dic/services"> <config xmlns="http://cmf.symfony.com/schema/dic/block"> <twig> <cmf-embed-blocks prefix="%%%block:"" postfix=""%%%" /> </twig> </config> </container>
- PHP
1 2 3 4 5 6 7 8 9
// app/config/config.php $container->loadFromExtension('cmf_block', array( 'twig' => array( 'cmf_embed_blocks' => array( 'prefix' => '%%%block:"', 'postfix' => '"%%%', ), ), );
See also the the configuration reference.
Caution
Currently there is no security built into this feature. Only enable the filter for content for which you are sure only trusted users may edit it. Restrictions about what block can be where that are built into an admin interface are not respected here.
Note
The block embed filter ignores all errors that might occur when rendering a block and returns an empty string for each failed block instead. The errors are logged at level WARNING.
SonataAdminBundle Integration¶
The BlockBundle also provides Admin classes to enable creating, editing and
removing blocks from the admin panel. To enable the admin, use the
cmf_block.persistence.phpcr.use_sonata_admin
setting. Both the
BlockBundle and
CoreBundle provide several extensions for
SonataAdminBundle.
Examples¶
You can find example usages of this bundle in the Symfony CMF Sandbox (have a look at the BlockBundle). It also shows you how to make blocks editable using the CreateBundle.
This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.