agence-adeliom/easy-page-bundle
Easy Page Bundle adds a lightweight CMS for Symfony EasyAdmin. Manage hierarchical pages in the admin dashboard and render them via simple slug-based routes like /{slug} or /{parentSlug}/{slug}, with Doctrine migrations/schema setup support.
Installation
composer require agence-adeliom/easy-page-bundle
Ensure your config/packages/easy_page.yaml exists (created automatically by Flex).
Configure EasyAdmin
Add EasyPageCrudController to your EasyAdmin config (config/packages/easy_admin.yaml):
easy_admin:
cruds:
- entity: App\Entity\Page
controller: AgenceAdeliom\EasyPageBundle\Controller\EasyPageCrudController
Create a Page Entity
Extend AgenceAdeliom\EasyPageBundle\Entity\Page in your app:
namespace App\Entity;
use AgenceAdeliom\EasyPageBundle\Entity\Page as BasePage;
class Page extends BasePage { }
First Use Case
Access the admin panel (/admin/pages) to create a page. Use the slug field for URLs (e.g., /pages/my-slug).
Page Creation
ckeditor or raw HTML)template field)meta_title, meta_description).Dynamic Routing
Add a route in config/routes.yaml:
easy_page:
resource: "@EasyPageBundle/Resources/config/routing.yaml"
prefix: /pages
Access pages via /pages/{slug}.
Twig Integration Fetch pages in templates:
{% set page = app.service('easy_page.page_manager').findOneBySlug('my-slug') %}
{{ page.title }}
{{ page.content|raw }} {# For HTML content #}
Custom Fields
Extend the Page entity to add fields:
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
class Page extends BasePage {
#[ORM\Column(type: 'string', length: 255, nullable: true)]
private ?string $customField = null;
// Getters/setters...
}
Update EasyAdmin config to include the new field.
Page Hierarchy
Use the parent field to create nested pages (e.g., /pages/parent/child).
EasyAdmin Customization Override the CRUD controller to add actions or filters:
# config/packages/easy_admin.yaml
easy_admin:
cruds:
- entity: App\Entity\Page
controller: App\Controller\CustomPageCrudController
Extend EasyPageCrudController in CustomPageCrudController.
Event Listeners
Subscribe to EasyPageEvents (e.g., PageCreatedEvent) for post-save logic:
use AgenceAdeliom\EasyPageBundle\Event\PageCreatedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class PageSubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [
PageCreatedEvent::NAME => 'onPageCreated',
];
}
public function onPageCreated(PageCreatedEvent $event) {
// Logic here
}
}
API Access
Use the PageManager service to fetch pages in APIs:
$pages = $this->get('easy_page.page_manager')->findAll();
Localization
Enable translations for fields in config/packages/easy_page.yaml:
easy_page:
translations: true
Slug Conflicts
Page entity:
public function setSlug(?string $slug): self {
if ($slug && $this->getSlug() !== $slug) {
$existing = $this->getRepository()->findOneBy(['slug' => $slug]);
if ($existing && $existing->getId() !== $this->getId()) {
throw new \RuntimeException('Slug already exists.');
}
}
$this->slug = $slug;
return $this;
}
Template Overrides
EasyPageBundle::default.html.twig or include the required blocks (easy_page_content).Caching Issues
php bin/console cache:clear
Doctrine Migrations
CKEditor Configuration
ckeditor bundle is installed and configured. The bundle expects it by default.Missing Routes
easy_page routes are loaded in config/routes.yaml and no typos exist in the prefix.Page Not Found
slug exists in the database./pages/{slug}).Field Not Displayed in Admin
#[ORM\Column].Permission Issues
easy_admin:
design:
menu:
- { label: 'Pages', entity: 'App\Entity\Page', icon: 'fas fa-file-alt', role: 'ROLE_ADMIN' }
Custom Page Types
Create a trait to extend Page for reusable logic:
trait CustomPageTrait {
#[ORM\Column(type: 'boolean')]
private bool $isFeatured = false;
// ...
}
Dynamic Templates Override the template resolver:
use AgenceAdeliom\EasyPageBundle\Resolver\TemplateResolverInterface;
class CustomTemplateResolver implements TemplateResolverInterface {
public function resolve(Page $page): string {
return $page->getTemplate() ?: '@EasyPage/default.html.twig';
}
}
Register it in services.yaml:
services:
App\Resolver\CustomTemplateResolver:
tags: ['easy_page.template_resolver']
Content Parsing
Extend the ContentParser service to modify content before rendering:
use AgenceAdeliom\EasyPageBundle\Parser\ContentParserInterface;
class CustomContentParser implements ContentParserInterface {
public function parse(string $content, Page $page): string {
// Modify content (e.g., replace placeholders)
return str_replace('{{user}}', $page->getUser()->getName(), $content);
}
}
Tag it in services.yaml:
services:
App\Parser\CustomContentParser:
tags: ['easy_page.content_parser']
Event Dispatching Dispatch custom events for page actions:
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class PageManager {
public function save(Page $page) {
$event = new PagePreSaveEvent($page);
$this->dispatcher->dispatch($event, PagePreSaveEvent::NAME);
// ...
}
}
Default Template
The bundle defaults to @EasyPage/default.html.twig. Override it globally in config/packages/easy_page.yaml:
easy_page:
template: '@App/templates/page.html.twig'
Content Field Type
The content field expects HTML. For Markdown, extend the entity and use a parser:
use Parsedown;
class Page extends BasePage {
public function getRenderedContent(): string {
return (new Parsedown())->text($this->content);
}
}
Slug Generation
Customize slug generation in config/packages/easy_page.yaml:
easy_page:
slug:
separator: '-'
max_length: 100
Soft Deletes Enable soft deletes for pages:
easy_page:
soft_deletes: true
Requires gedmo/doctrine-extensions and proper entity setup.
How can I help you explore Laravel packages today?