Install Dependencies Run:
composer require arzzzen/cms-bundle sonata-project/doctrine-orm-admin-bundle friendsofsymfony/user-bundle sonata-project/media-bundle sonata-project/easy-extends-bundle
Ensure dev-master is replaced with a stable version if available.
Register the Bundle
Add to app/AppKernel.php:
new Arzzzen\CmsBundle\ArzzzenCmsBundle(),
new Sonata\BlockBundle\SonataBlockBundle(),
new Sonata\jQueryBundle\SonatajQueryBundle(),
Configure Routing
Add to app/config/routing.yml:
arzzzen_cms:
resource: "@ArzzzenCmsBundle/Resources/config/routing.yml"
prefix: /
Basic Configuration
Update app/config/config.yml:
arzzzen_cms:
layout: "AcmeDemoBundle:layout:layout.html.twig"
First Use Case
Create a page entity (e.g., src/Acme/DemoBundle/Entity/Page.php) and register it with SonataAdmin. Example:
// src/Acme/DemoBundle/Admin/PageAdmin.php
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
class PageAdmin extends Admin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('title', 'text')
->add('content', 'sonata_media_type', [
'provider_list' => 'sonata.media.provider.image'
]);
}
}
Page Management
Arzzzen\CmsBundle\Entity\Page or create custom entities.// src/Acme/DemoBundle/Resources/config/admin.yml
sonata_admin:
options:
group: 'Content'
label: 'Pages'
label_catalog: 'AcmeDemoBundle'
show_in_dashboard: true
templates:
list: ArzzzenCmsBundle:Default:admin_list.html.twig
edit: ArzzzenCmsBundle:Default:admin_edit.html.twig
Layout Customization
Override the default layout (ArzzzenCmsBundle:Default:sonata_admin_base_layout.html.twig) by extending it in your bundle:
{# src/Acme/DemoBundle/Resources/views/layout.html.twig #}
{% extends 'ArzzzenCmsBundle:Default:sonata_admin_base_layout.html.twig' %}
{% block sonata_body %}
{{ parent() }}
<div class="custom-footer">Your custom content</div>
{% endblock %}
Media Integration
Use SonataMediaBundle for assets. Configure contexts (e.g., news, publication) in config.yml and attach media to pages:
$page->setMedia($media); // In a controller or admin service
Block-Based UI Leverage SonataBlockBundle to add reusable components (e.g., sliders, sidebars):
# config.yml
sonata_block:
blocks:
sonata.block.service.text:
contexts: [cms]
Routing for Pages Dynamically route pages via a custom controller:
// src/Acme/DemoBundle/Controller/PageController.php
class PageController extends Controller
{
public function showAction($slug)
{
$page = $this->getDoctrine()->getRepository('AcmeDemoBundle:Page')->findOneBy(['slug' => $slug]);
return $this->render('AcmeDemoBundle:Page:show.html.twig', ['page' => $page]);
}
}
Arzzzen\CmsBundle\Entity\Page for domain-specific fields.sonata.admin.post_persist or sonata.admin.post_update to automate workflows (e.g., slug generation).{{ page_menu() }}).sonata.media providers to handle images, videos, and files uniformly.Dependency Conflicts
dev-master. Pin versions to avoid breaking changes:
sonata-project/admin-bundle: 2.3.*
friendsofsymfony/user-bundle: 2.0.*
composer require vendor/package:version explicitly.Layout Overrides
sonata_admin_base_layout.html.twig may break if the bundle updates its template structure.{% block sonata_body %} sparingly and document overrides.Media Contexts
news) in sonata_media will cause errors when uploading assets.sonata_media:
contexts:
news:
providers: [sonata.media.provider.image] # Must match entity field type
Routing Conflicts
/admin).routing.yml:
arzzzen_cms:
resource: "@ArzzzenCmsBundle/Resources/config/routing.yml"
prefix: /cms
Entity Inheritance
Arzzzen\CmsBundle\Entity\Page requires proper mapping in config.yml:
doctrine:
orm:
mappings:
acmedemobundle:
type: annotation
dir: "%kernel.root_dir%/../src/Acme/DemoBundle/Entity"
prefix: "Acme\DemoBundle\Entity"
alias: AcmeDemoBundle
web_profiler to inspect SonataAdmin queries and media uploads.// config.yml
sonata_media:
providers:
image:
service: sonata.media.provider.image
# Add debug logging
logger: true
php bin/console cache:clear --env=prod
Custom Admin Classes
Extend Arzzzen\CmsBundle\Admin\PageAdmin to add fields or logic:
class CustomPageAdmin extends Arzzzen\CmsBundle\Admin\PageAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
parent::configureFormFields($formMapper);
$formMapper->add('customField', 'text');
}
}
Twig Globals Add CMS-specific data to Twig:
// src/Acme/DemoBundle/Twig/CmsExtension.php
class CmsExtension extends \Twig_Extension
{
public function getFunctions()
{
return [
new \Twig_SimpleFunction('get_page_menu', [$this, 'getPageMenu']),
];
}
}
Register in services.yml:
services:
acme_demo.twig.cms_extension:
class: Acme\DemoBundle\Twig\CmsExtension
tags:
- { name: twig.extension }
Event Subscribers
Listen to sonata.admin.post_persist to auto-generate slugs:
// src/Acme/DemoBundle/EventListener/PageSlugListener.php
class PageSlugListener
{
public function onPostPersist(GetResponseEvent $event)
{
$page = $event->getSubject();
if ($page instanceof Page) {
$page->setSlug(StringUtil::slugify($page->getTitle()));
$this->em->persist($page);
$this->em->flush();
}
}
}
Register in services.yml:
services:
acme_demo.listener.page_slug:
class: Acme\DemoBundle\EventListener\PageSlugListener
arguments: ["@doctrine.orm.entity_manager"]
tags:
- { name: kernel.event_subscriber }
Custom Block Types Create reusable blocks (e.g., a "Latest News" block):
How can I help you explore Laravel packages today?