Installation:
composer require sonata-project/block-bundle
Add to config/bundles.php:
return [
// ...
Sonata\BlockBundle\SonataBlockBundle::class => ['all' => true],
];
Database Setup:
Run migrations to create the block and block_position tables:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
First Block:
Create a simple block service (e.g., app/Blocks/HelloBlock.php):
namespace App\Blocks;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Block\BaseBlockService;
use Sonata\BlockBundle\Model\BlockInterface;
class HelloBlock extends BaseBlockService
{
public function execute(BlockContextInterface $blockContext, BlockInterface $block)
{
return ['content' => 'Hello, World!'];
}
public function getName()
{
return 'app.hello_block';
}
}
Register Service:
Add to config/services.yaml:
services:
App\Blocks\HelloBlock:
tags:
- { name: sonata.block }
Enable in Admin:
Add to config/packages/sonata_block.yaml:
sonata_block:
blocks:
app_hello_block: ~
Use the Sonata Admin dashboard to drag-and-drop the Hello Block onto a page. Verify it renders in the frontend.
BaseBlockService for reusable blocks.
class CustomBlock extends BaseBlockService
{
public function execute(BlockContextInterface $blockContext, BlockInterface $block)
{
$settings = $block->getSettings();
return ['data' => $settings['custom_data']];
}
}
BaseBlockService with a Twig template:
class TemplateBlock extends BaseBlockService
{
protected function getTemplate()
{
return '@App/Blocks/template_block.html.twig';
}
}
execute():
public function execute(BlockContextInterface $blockContext, BlockInterface $block)
{
$posts = $this->entityManager->getRepository(Post::class)->findLatest();
return ['posts' => $posts];
}
{% for post in block.posts %}
<h3>{{ post.title }}</h3>
{% endfor %}
configureSettings():
protected function configureSettings(BaseBlockSettings $settings)
{
$settings
->set('title', 'Title')
->set('custom_data', 'Custom Data', 'text');
}
execute():
$title = $block->getSetting('title');
# config/packages/sonata_block.yaml
sonata_block:
cache:
default_lifetime: 3600 # 1 hour
public function execute(BlockContextInterface $blockContext, BlockInterface $block)
{
return $this->renderView(
'@App/Blocks/cache_block.html.twig',
['data' => $data],
$blockContext->getCacheLifetime()
);
}
BlockContextInterface to access:
$blockContext->getPage()).$blockContext->getRequest()).$blockContext->getCache()).{{ render(block) }}
{{ render(block, {'extra_var': 'value'}) }}
sonata_block:
groups:
custom_group:
label: 'Custom Blocks'
blocks:
- app_custom_block
sonata.block.pre_render):
// config/services.yaml
App\EventListener\BlockListener:
tags:
- { name: kernel.event_listener, event: sonata.block.pre_render, method: onPreRender }
Caching Issues:
php bin/console cache:clear
cache:pool:clear for specific pools if needed.Block Settings Persistence:
BlockInterface is properly saved after updating settings:
$block->setSetting('key', 'value');
$this->blockManager->save($block);
Dependency Injection:
Twig Template Paths:
@App/Blocks/block_name.html.twig). Use getTemplate() in BaseBlockService for clarity.Database Schema Changes:
block and block_position tables are required. Always run migrations after updating the bundle.Log Block Execution:
execute():
$this->logger->debug('Block executed', ['block_id' => $block->getId()]);
Check Block Settings:
execute() to verify data:
dump($block->getSettings());
Verify Block Registration:
services.yaml:
tags:
- { name: sonata.block, context: { name: app_custom_block } }
Clear Cache After Changes:
Custom Block Types:
BaseBlockService or create a custom block class for unique functionality.Block Managers:
Sonata\BlockBundle\Manager\BlockManager) for custom logic.Block Storage:
BlockRepository with a custom implementation for advanced storage needs.Block Events:
$event = new BlockEvent($block);
$this->eventDispatcher->dispatch($event, 'sonata.block.custom_event');
Block Security:
execute():
if (!$this->security->isGranted('ROLE_VIEW_BLOCK', $block)) {
throw new AccessDeniedException();
}
Default Block Settings:
configureSettings():
$settings->setDefault('title', 'Default Title');
Block Visibility:
isVisible():
public function isVisible(BlockContextInterface $blockContext, BlockInterface $block)
{
return $blockContext->getRequest()->get('show_block', false);
}
Block Ordering:
getPosition() and setPosition() to manage block order dynamically.Multi-Site Support:
Block entity to include site-specific fields if using multi-site setups.Block Inheritance:
BlockContextInterface to inherit settings from parent blocks in nested layouts.How can I help you explore Laravel packages today?