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

Difane Contentpart Bundle Laravel Package

difane/difane-contentpart-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the bundle via Composer:

    composer require difane/difane-contentpart-bundle
    

    Enable it in config/bundles.php:

    Difane\ContentPartBundle\DifaneContentPartBundle::class => ['all' => true],
    
  2. Database Migration Run migrations to create the required tables:

    php bin/console doctrine:migrations:diff
    php bin/console doctrine:migrations:migrate
    
  3. First Content Part Create a basic content part class (e.g., src/ContentPart/MyFirstPart.php):

    namespace App\ContentPart;
    
    use Difane\ContentPartBundle\Model\ContentPartInterface;
    
    class MyFirstPart implements ContentPartInterface
    {
        private $title;
        private $content;
    
        // Getters, setters, and validation logic
    }
    
  4. Register the Content Part Add it to the service configuration in config/packages/difane_content_part.yaml:

    difane_content_part:
        parts:
            my_first_part:
                class: App\ContentPart\MyFirstPart
                label: 'My First Part'
    
  5. Admin Integration Access the admin interface at /admin/content-parts to manage instances of your part.


First Use Case: Adding a Content Part to a Page

  1. Create a Page Entity Extend Difane\ContentPartBundle\Model\PageInterface in your page entity (e.g., src/Entity/Page.php):

    namespace App\Entity;
    
    use Difane\ContentPartBundle\Model\PageInterface;
    use Doctrine\Common\Collections\ArrayCollection;
    use Doctrine\Common\Collections\Collection;
    
    class Page implements PageInterface
    {
        private $contentParts;
    
        public function __construct()
        {
            $this->contentParts = new ArrayCollection();
        }
    
        // Implement PageInterface methods (addContentPart, removeContentPart, etc.)
    }
    
  2. Inject Content Parts in Twig Use the content_part Twig function in your template:

    {% for part in page.contentParts %}
        {{ content_part(part) }}
    {% endfor %}
    

Implementation Patterns

Workflow: Building Reusable Content Parts

  1. Define Part Structure Create a base class for shared functionality (e.g., src/ContentPart/BasePart.php):

    namespace App\ContentPart;
    
    use Difane\ContentPartBundle\Model\ContentPartInterface;
    use Symfony\Component\Validator\Constraints as Assert;
    
    abstract class BasePart implements ContentPartInterface
    {
        /**
         * @Assert\NotBlank
         */
        protected $title;
    
        // Common fields and validation
    }
    
  2. Extend for Specific Use Cases Example: A HeroSection part:

    namespace App\ContentPart;
    
    use App\ContentPart\BasePart;
    
    class HeroSection extends BasePart
    {
        /**
         * @Assert\NotBlank
         */
        private $subtitle;
    
        /**
         * @Assert\NotBlank
         */
        private $imageUrl;
    
        // Custom getters/setters
    }
    
  3. Register in Configuration Update config/packages/difane_content_part.yaml:

    difane_content_part:
        parts:
            hero_section:
                class: App\ContentPart\HeroSection
                label: 'Hero Section'
                form_type: App\Form\HeroSectionType  # Optional: Custom form
    

Integration Tips

  1. Twig Integration

    • Use content_part(part) to render a part in templates.
    • Access part fields directly (e.g., {{ part.title }}).
    • Override rendering with a custom Twig template:
      {% block hero_section_content %}
          <div class="hero">
              <h1>{{ part.title }}</h1>
              <p>{{ part.subtitle }}</p>
              <img src="{{ part.imageUrl }}">
          </div>
      {% endblock %}
      
  2. Form Customization

    • Extend the default form type:
      namespace App\Form;
      
      use Symfony\Component\Form\AbstractType;
      use Symfony\Component\Form\FormBuilderInterface;
      
      class HeroSectionType extends AbstractType
      {
          public function buildForm(FormBuilderInterface $builder, array $options)
          {
              $builder
                  ->add('title')
                  ->add('subtitle')
                  ->add('imageUrl', TextType::class, [
                      'attr' => ['placeholder' => 'https://example.com/image.jpg']
                  ]);
          }
      }
      
    • Reference it in difane_content_part.yaml under form_type.
  3. Page-Level Configuration

    • Restrict content parts to specific pages via metadata:
      difane_content_part:
          parts:
              hero_section:
                  allowed_pages: ['homepage', 'landing_page']  # Custom logic in service
      
  4. Event Listeners

    • Hook into lifecycle events (e.g., ContentPartPrePersist):
      namespace App\EventListener;
      
      use Difane\ContentPartBundle\Event\ContentPartEvent;
      use Symfony\Component\EventDispatcher\EventSubscriberInterface;
      
      class ContentPartSubscriber implements EventSubscriberInterface
      {
          public static function getSubscribedEvents()
          {
              return [
                  ContentPartEvent::PRE_PERSIST => 'onPrePersist',
              ];
          }
      
          public function onPrePersist(ContentPartEvent $event)
          {
              $part = $event->getContentPart();
              if ($part instanceof \App\ContentPart\HeroSection) {
                  $part->setCreatedAt(new \DateTime());
              }
          }
      }
      

Advanced: Dynamic Content Part Loading

  1. Lazy-Load Parts Use a service to dynamically register parts (e.g., from a database):

    namespace App\Service;
    
    use Difane\ContentPartBundle\Manager\ContentPartManagerInterface;
    use Doctrine\ORM\EntityManagerInterface;
    
    class DynamicContentPartLoader
    {
        public function __construct(
            private ContentPartManagerInterface $manager,
            private EntityManagerInterface $em
        ) {}
    
        public function loadPartsFromDatabase()
        {
            $parts = $this->em->getRepository(\App\Entity\DynamicPart::class)->findAll();
            foreach ($parts as $partConfig) {
                $this->manager->registerPart(
                    $partConfig->getName(),
                    $partConfig->getClass(),
                    $partConfig->getLabel()
                );
            }
        }
    }
    
  2. Conditional Rendering Use Twig tests to conditionally render parts:

    {% if part is renderable %}
        {{ content_part(part) }}
    {% endif %}
    

    Define renderable in a Twig extension:

    namespace App\Twig;
    
    use Twig\Extension\AbstractExtension;
    use Twig\TwigFunction;
    
    class ContentPartExtension extends AbstractExtension
    {
        public function getFunctions()
        {
            return [
                new TwigFunction('renderable', [$this, 'isRenderable']),
            ];
        }
    
        public function isRenderable($part)
        {
            return $part->isActive() && $part->getTitle() !== null;
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Circular Dependencies

    • Avoid circular references between content parts (e.g., Part A includes Part B, which includes Part A).
    • Fix: Use lazy loading or validate part inclusion logic in ContentPartManager.
  2. Validation Errors

    • If a part fails validation, the admin interface may silently ignore changes.
    • Fix: Override the default form handler to display validation errors:
      namespace App\Form\Handler;
      
      use Difane\ContentPartBundle\Form\ContentPartHandlerInterface;
      use Symfony\Component\Form\FormInterface;
      
      class CustomContentPartHandler implements ContentPartHandlerInterface
      {
          public function handle(FormInterface $form, $contentPart)
          {
              if ($form->isSubmitted() && !$form->isValid()) {
                  // Log errors or flash a message
                  $this->addFlash('error', 'Validation failed');
              }
              return parent::handle($form, $contentPart);
          }
      }
      
    • Register it in services.yaml:
      Difane\ContentPartBundle\Form\ContentPartHandler: '@App\Form\Handler\CustomContentPartHandler'
      
  3. Performance with Many Parts

    • Loading all content parts for a page with many instances can be slow.
    • Fix: Use DQL to fetch only active/visible parts:
      $qb = $this->em->createQueryBuilder()
          ->select('p')
          ->from(\App\Entity\Page::class, 'p')
          ->join('p.contentParts', 'cp')
          ->where('cp.active = :active')
          ->setParameter('active', true);
      
  4. Twig Caching Issues

    • Twig templates for parts may not update after changes.
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui