Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Easy Page Bundle Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require agence-adeliom/easy-page-bundle
    

    Ensure your config/packages/easy_page.yaml exists (created automatically by Flex).

  2. 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
    
  3. 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 { }
    
  4. First Use Case Access the admin panel (/admin/pages) to create a page. Use the slug field for URLs (e.g., /pages/my-slug).


Implementation Patterns

Workflows

  1. Page Creation

    • Use the EasyAdmin CRUD interface to create pages with:
      • Title (required)
      • Slug (auto-generated from title or manual)
      • Content (WYSIWYG via ckeditor or raw HTML)
      • Template (optional; override default via template field)
      • Meta tags (SEO fields like meta_title, meta_description).
  2. Dynamic Routing Add a route in config/routes.yaml:

    easy_page:
        resource: "@EasyPageBundle/Resources/config/routing.yaml"
        prefix: /pages
    

    Access pages via /pages/{slug}.

  3. 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 #}
    
  4. 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.

  5. Page Hierarchy Use the parent field to create nested pages (e.g., /pages/parent/child).


Integration Tips

  • 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
    

Gotchas and Tips

Pitfalls

  1. Slug Conflicts

    • Slugs must be unique. Handle conflicts in your 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;
      }
      
  2. Template Overrides

    • If using custom templates, ensure they extend EasyPageBundle::default.html.twig or include the required blocks (easy_page_content).
  3. Caching Issues

    • Clear the cache after adding new fields or routes:
      php bin/console cache:clear
      
  4. Doctrine Migrations

    • Always run migrations after updating the bundle version to avoid schema conflicts.
  5. CKEditor Configuration

    • If using CKEditor, ensure the ckeditor bundle is installed and configured. The bundle expects it by default.

Debugging

  1. Missing Routes

    • Verify easy_page routes are loaded in config/routes.yaml and no typos exist in the prefix.
  2. Page Not Found

    • Check:
      • The slug exists in the database.
      • The route is correctly mapped (/pages/{slug}).
      • No typos in the slug when accessing the page.
  3. Field Not Displayed in Admin

    • Ensure the field is:
      • Annotated with #[ORM\Column].
      • Included in the EasyAdmin CRUD config.
      • Public with getters/setters.
  4. Permission Issues

    • Use EasyAdmin’s security to restrict access:
      easy_admin:
          design:
              menu:
                  - { label: 'Pages', entity: 'App\Entity\Page', icon: 'fas fa-file-alt', role: 'ROLE_ADMIN' }
      

Extension Points

  1. Custom Page Types Create a trait to extend Page for reusable logic:

    trait CustomPageTrait {
        #[ORM\Column(type: 'boolean')]
        private bool $isFeatured = false;
    
        // ...
    }
    
  2. 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']
    
  3. 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']
    
  4. 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);
            // ...
        }
    }
    

Configuration Quirks

  1. 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'
    
  2. 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);
        }
    }
    
  3. Slug Generation Customize slug generation in config/packages/easy_page.yaml:

    easy_page:
        slug:
            separator: '-'
            max_length: 100
    
  4. Soft Deletes Enable soft deletes for pages:

    easy_page:
        soft_deletes: true
    

    Requires gedmo/doctrine-extensions and proper entity setup.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware