Installation:
composer require awaresoft/sonata-page-bundle
Note: Due to the package's symlink-based workflow, follow the README's local setup instructions if modifying the bundle.
Enable the Bundle:
Add to config/bundles.php:
return [
// ...
Awaresoft\SonataPageBundle\SonataPageBundle::class => ['all' => true],
];
First Use Case: Create a basic page entity and route:
php bin/console make:sonata-page
This generates:
Page entity (e.g., src/Entity/Page.php).src/Controller/PageController.php).templates/sonata_page/).Configure Routes:
Add to config/routes.yaml:
sonata_page:
resource: "@SonataPageBundle/Resources/config/routing.yml"
prefix: /page
Clear Cache:
php bin/console cache:clear
php bin/console make:sonata-page:fixtures to seed demo pages./admin/page (if using SonataAdminBundle).src/Awaresoft/SonataPageBundle/Twig/ for built-in helpers like page_link() or page_content().Entity Customization:
Extend the default Page entity to add fields (e.g., slug, meta_title):
// src/Entity/Page.php
namespace App\Entity;
use Awaresoft\SonataPageBundle\Entity\Page as BasePage;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
class Page extends BasePage
{
#[ORM\Column(type: 'string', length: 255)]
private string $slug;
// Getters/setters...
}
Tip: Use php bin/console make:entity to scaffold new fields.
Form Types:
Override the default form in src/Form/PageType.php:
use Awaresoft\SonataPageBundle\Form\Type\PageType as BasePageType;
class PageType extends BasePageType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder->add('slug', TextType::class);
}
}
CRUD Operations:
Use the generated PageController or inject the PageRepository:
use Awaresoft\SonataPageBundle\Repository\PageRepository;
public function __construct(PageRepository $pageRepo) {
$this->pageRepo = $pageRepo;
}
public function index()
{
$pages = $this->pageRepo->findAll();
return $this->render('page/index.html.twig', ['pages' => $pages]);
}
Dynamic Routes:
Use the sonata_page router to generate URLs dynamically:
{{ path('sonata_page_page_show', {'slug': page.slug}) }}
Note: Ensure your Page entity has a slug field for SEO-friendly URLs.
Route Annotations: Annotate controllers to integrate with Sonata’s routing:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
#[Route('/custom/{slug}', name: 'custom_page')]
public function show(Page $page)
{
return $this->render('page/show.html.twig', ['page' => $page]);
}
Page Blocks: Use Twig blocks to extend the default layout:
{# templates/sonata_page/page/show.html.twig #}
{% extends 'sonata_page/base.html.twig' %}
{% block content %}
<h1>{{ page.title }}</h1>
{{ page.content|raw }}
{% endblock %}
Embedding Content:
Render pages within other pages using the sonata_page_embed Twig function:
{{ sonata_page_embed(page) }}
Admin Configuration:
Register the Page entity in src/Admin/PageAdmin.php:
use Awaresoft\SonataPageBundle\Admin\PageAdmin as BasePageAdmin;
class PageAdmin extends BasePageAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
parent::configureFormFields($formMapper);
$formMapper->add('slug', 'text');
}
}
Access Control: Secure the admin panel with Symfony’s security system:
# config/packages/security.yaml
access_control:
- { path: ^/admin/page, roles: ROLE_ADMIN }
sonata.page.pre_persist):
use Awaresoft\SonataPageBundle\Event\PageEvent;
class PageSlugSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
PageEvent::PRE_PERSIST => 'setSlug',
];
}
public function setSlug(PageEvent $event)
{
$page = $event->getPage();
$page->setSlug(StringUtil::slugify($page->getTitle()));
}
}
Symlink Dependencies:
/src/Awaresoft is correct. Breakage may occur if the symlink is missing or misconfigured.php bin/console cache:clear after symlink changes.Route Conflicts:
/page/*) may clash with existing routes. Use _controller or custom route namespaces to avoid conflicts.routing.yml:
sonata_page:
resource: "@SonataPageBundle/Resources/config/routing.yml"
prefix: /custom_prefix
Doctrine Proxy Issues:
Page entity, clear the Doctrine cache:
php bin/console doctrine:cache:clear-metadata
php bin/console doctrine:cache:clear-query
Twig Autoloading:
templates directory structure matches the bundle’s expectations (e.g., templates/sonata_page/page/show.html.twig).Enable Debug Mode:
Set APP_DEBUG=true in .env to see detailed errors for template or routing issues.
Check Events: Use Symfony’s event dispatcher to debug listeners:
php bin/console debug:event-dispatcher
Database Migrations:
After modifying the Page entity, generate and run migrations:
php bin/console make:migration
php bin/console doctrine:migrations:migrate
Custom Page Types:
Extend the base Page entity to create specialized page types (e.g., BlogPost, ProductPage):
class BlogPost extends BasePage
{
#[ORM\Column(type: 'datetime')]
private ?\DateTimeInterface $publishedAt;
}
Custom Twig Functions:
Add global Twig functions in src/Twig/AppExtension.php:
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class AppExtension extends AbstractExtension
{
public function getFunctions()
{
return [
new TwigFunction('custom_page_link', [$this, 'linkToPage']),
];
}
public function linkToPage(Page $page)
{
return $this->twig->render('partials/page_link.html.twig', ['page' => $page]);
}
}
API Integration: Expose pages via API using Symfony’s Serializer:
use Symfony\Component\Serializer\Annotation\Groups;
class Page
{
#[Groups(['api'])]
#[ORM\Column(type: 'string')]
private string $title;
}
How can I help you explore Laravel packages today?