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 Block Bundle Laravel Package

agence-adeliom/easy-block-bundle

Symfony bundle adding a basic block component for EasyAdmin: manage blocks via a CRUD interface and render them in Twig. Supports Symfony 6.4/7.x (PHP 8.2+), with older branches for Symfony 5.4/6.x and 4.4/5.x.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require agence-adeliom/easy-block-bundle
    

    Ensure your composer.json includes the GitHub recipes endpoint for Symfony Flex:

    "extra": {
      "symfony": {
        "endpoint": [
          "https://api.github.com/repos/agence-adeliom/symfony-recipes/contents/index.json?ref=flex/main",
          "flex://defaults"
        ],
        "allow-contrib": true
      }
    }
    
  2. Database Migration: Run Doctrine migrations to create the required tables:

    php bin/console doctrine:migration:diff
    php bin/console doctrine:migration:migrate
    
  3. Register the Bundle: Add AgenceAdeliom\EasyBlockBundle\EasyBlockBundle to your bundles.php (Symfony 5+).

  4. First Use Case: Create a block via EasyAdmin CRUD:

    • Navigate to /admin/block (or your configured EasyAdmin route).
    • Add a new block with content (e.g., HTML, Twig, or plain text).
    • Render it in a Twig template:
      {{ render_block('block-slug') }}
      

Implementation Patterns

Core Workflows

  1. Block Management via EasyAdmin:

    • Extend the default Block CRUD to customize fields or validation:
      # config/easyadmin.yaml
      easy_admin:
        entities:
          AgenceAdeliom\EasyBlockBundle\Entity\Block:
            class: AgenceAdeliom\EasyBlockBundle\Entity\Block
            list:
              fields: ['title', 'slug', 'isPublished', 'createdAt']
            form:
              fields: ['title', 'slug', 'content', 'isPublished']
      
    • Use the BlockRepository to fetch blocks programmatically:
      $block = $blockRepository->findOneBy(['slug' => 'hero-banner']);
      
  2. Rendering Blocks in Twig:

    • Basic Rendering:
      {{ render_block('hero-banner') }}
      
    • Conditional Rendering:
      {% if block is defined %}
        {{ render_block(block.slug) }}
      {% endif %}
      
    • Passing Context:
      {{ render_block('dynamic-block', {'user': app.user}) }}
      
  3. Dynamic Block Assignment:

    • Store block slugs in entity properties (e.g., Page entity):
      // src/Entity/Page.php
      #[ORM\Column]
      private ?string $heroBlockSlug;
      
    • Render dynamically in Twig:
      {% if page.heroBlockSlug %}
        {{ render_block(page.heroBlockSlug) }}
      {% endif %}
      
  4. Integration with EasyAdmin Dashboard:

    • Embed blocks directly in EasyAdmin layouts:
      {# templates/easyadmin/layout.html.twig #}
      <div class="dashboard-block">
        {{ render_block('admin-dashboard-hero') }}
      </div>
      

Advanced Patterns

  • Block Types: Extend the Block entity to support custom types (e.g., ImageBlock, VideoBlock):

    // src/Entity/CustomBlock.php
    class CustomBlock extends Block
    {
        #[ORM\Column]
        private ?string $customField;
    
        // Add getters/setters
    }
    

    Register the new entity in EasyAdmin.

  • Caching: Cache rendered blocks for performance:

    $renderedBlock = $this->get('easy_block.renderer')->render('block-slug');
    $this->get('cache')->save('block:block-slug', $renderedBlock, 'blocks', 3600);
    
  • Event Listeners: Hook into block lifecycle events (e.g., BlockEvents::PRE_RENDER):

    // src/EventListener/BlockListener.php
    class BlockListener
    {
        public function onPreRender(PreRenderEvent $event): void
        {
            $event->setContent($this->modifyContent($event->getContent()));
        }
    }
    

    Register the listener in services.yaml:

    services:
      App\EventListener\BlockListener:
        tags:
          - { name: kernel.event_listener, event: easy_block.pre_render }
    

Gotchas and Tips

Common Pitfalls

  1. Slug Uniqueness:

    • Ensure slugs are unique. Override the Block entity validation if needed:
      #[Assert\Unique(entityClass: Block::class, message: 'Slug already exists')]
      private ?string $slug;
      
  2. Twig Function Not Found:

    • Verify the Twig extension is registered. Check config/packages/easy_block.yaml for:
      twig:
          twig:
              extensions:
                  - AgenceAdeliom\EasyBlockBundle\Twig\EasyBlockExtension
      
  3. Permission Issues:

    • Restrict block access in EasyAdmin:
      # config/easyadmin.yaml
      AgenceAdeliom\EasyBlockBundle\Entity\Block:
          permissions: ['ROLE_ADMIN']
      
  4. Content Security:

    • Sanitize block content if rendered in untrusted contexts:
      {{ render_block('user-generated', {'sanitize': true}) }}
      

Debugging Tips

  • Check Block Existence:

    $block = $blockRepository->findOneBy(['slug' => 'missing-slug']);
    if (!$block) {
        throw new \RuntimeException("Block 'missing-slug' not found");
    }
    
  • Enable Debug Mode: Set EASY_BLOCK_DEBUG: true in .env to log Twig rendering errors.

  • Clear Cache: After extending the bundle, clear the cache:

    php bin/console cache:clear
    

Extension Points

  1. Custom Renderers: Override the default renderer by implementing BlockRendererInterface:

    class CustomRenderer implements BlockRendererInterface
    {
        public function render(Block $block, array $context = []): string
        {
            // Custom logic
            return $this->twig->render('custom_block.html.twig', [
                'block' => $block,
                'context' => $context,
            ]);
        }
    }
    

    Register it in services.yaml:

    services:
        App\Renderer\CustomRenderer:
            tags:
                - { name: easy_block.renderer }
    
  2. Block Storage: Extend the BlockStorageInterface to support non-Doctrine storage (e.g., Redis):

    class RedisBlockStorage implements BlockStorageInterface
    {
        public function find(string $slug): ?Block
        {
            // Custom Redis logic
        }
    }
    

    Bind it in services.yaml:

    services:
        AgenceAdeliom\EasyBlockBundle\Storage\BlockStorageInterface: '@App\Storage\RedisBlockStorage'
    
  3. Twig Filters: Add custom Twig filters for block content:

    // src/Twig/BlockFilterExtension.php
    class BlockFilterExtension extends \Twig\Extension\AbstractExtension
    {
        public function getFilters(): array
        {
            return [
                new \Twig\TwigFilter('markdown', [$this, 'convertToMarkdown']),
            ];
        }
    
        public function convertToMarkdown(string $content): string
        {
            return (new Parser())->parse($content);
        }
    }
    

    Register the extension in services.yaml:

    services:
        App\Twig\BlockFilterExtension:
            tags: ['twig.extension']
    
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.
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky