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

Content Forms Laravel Package

ibexa/content-forms

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install Ibexa DXP (prerequisite): Follow the official Ibexa DXP installation guide to set up the core system. Ensure you’re using PHP 8.3+ and Symfony 7.4+ (as of v5.0.x).

  2. Enable the Package: Add ibexa/content-forms to your composer.json:

    composer require ibexa/content-forms
    

    Register the bundle in config/bundles.php:

    return [
        // ...
        Ibexa\ContentForms\IbexaContentFormsBundle::class => ['all' => true],
    ];
    
  3. First Use Case: Basic Content Form Create a form type for a content type (e.g., Article):

    use Ibexa\ContentForms\FieldType\FieldTypeFormFactory;
    use Symfony\Component\Form\AbstractType;
    
    class ArticleFormType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('title', TextType::class)
                ->add('body', TextareaType::class)
                ->add('save', SubmitType::class);
        }
    }
    

    Register the form in your content type definition (YAML/JSON) under form:

    form:
        name: article_form
        class: App\Form\ArticleFormType
    
  4. Access the Form in a Controller: Use the ContentFormFactory to generate and handle the form:

    use Ibexa\ContentForms\ContentFormFactory;
    
    class ArticleController
    {
        public function edit(ContentFormFactory $formFactory, Content $content)
        {
            $form = $formFactory->create($content);
            $form->handleRequest($request);
    
            if ($form->isSubmitted() && $form->isValid()) {
                $form->save();
                return $this->redirectToRoute('article_show', ['id' => $content->id]);
            }
    
            return $this->render('article/edit.html.twig', ['form' => $form->createView()]);
        }
    }
    

Implementation Patterns

1. Form Integration with Ibexa Content

  • Content Forms as a Bridge: The package bridges Symfony Forms with Ibexa’s Content and User objects. Use it to:

    • Edit content (create/update).
    • Manage user profiles (e.g., avatars, metadata).
    • Handle complex field types (e.g., ezimage, ezrichtext).
  • Field Type Transformers: Ibexa provides built-in transformers for common field types (e.g., ezstring, ezdate). Extend FieldTypeTransformerInterface for custom fields:

    use Ibexa\ContentForms\FieldType\FieldTypeTransformerInterface;
    
    class CustomFieldTransformer implements FieldTypeTransformerInterface
    {
        public function transformToFormData($value): ?string
        {
            return json_encode($value);
        }
    
        public function transformFromFormData($data): array
        {
            return json_decode($data, true);
        }
    }
    

    Register it in services.yaml:

    services:
        Ibexa\ContentForms\FieldType\FieldTypeTransformerInterface:
            class: App\FieldType\CustomFieldTransformer
            tags: { name: ibexa.content_forms.field_type_transformer, fieldType: 'custom' }
    

2. Workflow: Content Creation/Editing

  1. Create a Draft:
    $content = $contentService->newContentCreateStruct('article');
    $form = $formFactory->create($content);
    
  2. Handle Submission:
    $form->handleRequest($request);
    if ($form->isSubmitted() && $form->isValid()) {
        $content = $form->getContent();
        $contentService->publishVersion($content->versionInfo);
    }
    
  3. Autosave (Optional): Enable via config (config/packages/ibexa_content_forms.yaml):
    ibexa_content_forms:
        autosave:
            enabled: true
            interval: 300 # seconds
    

3. User Profile Forms

  • Extend UserFormType for custom user fields:
    class UserProfileFormType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('avatar', FileType::class, ['label' => 'Profile Image'])
                ->add('bio', TextareaType::class);
        }
    }
    
  • Use UserFormFactory in a controller:
    $userForm = $userFormFactory->create($user);
    $userForm->handleRequest($request);
    if ($userForm->isSubmitted() && $userForm->isValid()) {
        $userForm->save();
    }
    

4. Events and Extensibility

  • Form Actions: Dispatch custom actions (e.g., send email on save):
    use Ibexa\ContentForms\Event\FormActionEvent;
    
    $eventDispatcher->dispatch(new FormActionEvent($form, 'post_save', function (FormActionEvent $event) {
        // Send email logic
    }));
    
  • Listen to Events:
    use Ibexa\ContentForms\Event\FormSubmitEvent;
    
    $eventDispatcher->addListener(FormSubmitEvent::class, function (FormSubmitEvent $event) {
        if (!$event->getForm()->isValid()) {
            $event->stopPropagation();
        }
    });
    

5. Validation and Constraints

  • Add constraints to form fields:
    $builder->add('title', TextType::class, [
        'constraints' => [
            new NotBlank(),
            new Length(['min' => 10]),
        ],
    ]);
    
  • Override default validation via field type definitions (YAML):
    fieldDefinitions:
        title:
            fieldType: ezstring
            constraints:
                - Ibexa\Contracts\Core\FieldType\Constraint\NotEmpty
    

Gotchas and Tips

Pitfalls

  1. Field Type Mismatches:

    • Issue: Custom field types may not have transformers, causing RuntimeException.
    • Fix: Implement FieldTypeTransformerInterface and tag the service correctly.
    • Debug: Check ibexa.content_forms.field_type_transformer tags in services.yaml.
  2. Autosave Conflicts:

    • Issue: Concurrent edits may overwrite changes if autosave is enabled.
    • Fix: Disable autosave for specific forms via event:
      $eventDispatcher->addListener(FormActionEvent::class, function (FormActionEvent $event) {
          if ($event->getForm()->getContent()->contentInfo->contentId === 123) {
              $event->setAutosave(false);
          }
      });
      
  3. Draft Ownership:

    • Issue: Drafts may default to the wrong user (e.g., system_user instead of the logged-in user).
    • Fix: Use the FormActionEvent to set the owner:
      $event->setDraftOwner($this->getUser());
      
  4. Non-Translatable Fields:

    • Issue: Fields marked as non-translatable may not save correctly.
    • Fix: Ensure the field is included in the form without language context:
      $builder->add('non_translatable_field', null, [
          'mapped' => false,
          'data' => $content->getFieldValue('non_translatable_field'),
      ]);
      
  5. File Uploads:

    • Issue: Large file uploads may fail silently.
    • Fix: Configure ezimage field type constraints in YAML:
      fieldDefinitions:
          image:
              fieldType: ezimage
              constraints:
                  - Ibexa\Contracts\Core\FieldType\Constraint\MaxFileSize:
                      maxSize: 5M
      

Debugging Tips

  1. Enable Form Debugging: Add this to config/packages/dev/ibexa_content_forms.yaml:

    ibexa_content_forms:
        debug: true
    

    This logs form data and events to var/log/dev.log.

  2. Check Event Dispatching: Use Symfony’s event profiler (_profiler) to verify events are fired:

    $eventDispatcher->addListener(FormSubmitEvent::class, function (FormSubmitEvent $event) {
        $this->logger->debug('Form submitted', ['content_id' => $event->getContent()->id]);
    });
    
  3. Validate Field Transformers: Test transformers in isolation:

    $transformer = $container->get
    
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
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
spatie/mailcoach-vapor