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

Doctrine Bridge Laravel Package

symfony/doctrine-bridge

Symfony Doctrine Bridge integrates Doctrine with Symfony components, providing glue code for ORM/DBAL usage across the framework. Part of the main Symfony repository; report issues and submit pull requests there.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require symfony/doctrine-bridge
    

    This package is typically included as a dependency of symfony/framework-bundle, so explicit installation is rare unless extending functionality.

  2. First Use Case:

    • Entity Validation: Use @UniqueEntity or @Assert constraints in your Doctrine entities:
      use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
      use Doctrine\ORM\Mapping as ORM;
      
      #[ORM\Entity]
      #[UniqueEntity(fields: ['email'], message: 'Email already taken')]
      class User {}
      
    • Form Integration: Automatically bind Doctrine entities to Symfony forms:
      use Symfony\Bridge\Doctrine\Form\Type\EntityType;
      
      $builder->add('user', EntityType::class, [
          'class' => User::class,
          'choice_label' => 'email',
      ]);
      
  3. Where to Look First:

    • Symfony Docs: Doctrine Integration
    • Core Classes:
      • Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity
      • Symfony\Bridge\Doctrine\Form\Type\EntityType
      • Symfony\Bridge\Doctrine\Security\User\EntityUserProvider

Implementation Patterns

Common Workflows

1. Validation-Driven Development

  • Pattern: Use Doctrine metadata for validation.
    #[ORM\Entity]
    #[UniqueEntity('username')]
    class User {
        #[Assert\NotBlank]
        #[Assert\Length(min: 3)]
        private string $username;
    }
    
  • Workflow:
    1. Define constraints in entity annotations.
    2. Symfony’s Validator automatically checks these during form submission or manual validation.
    3. Customize error messages via message parameter.

2. Form-Entity Binding

  • Pattern: Bind forms to Doctrine entities with minimal boilerplate.
    $form = $this->createFormBuilder($user)
        ->add('name')
        ->add('email')
        ->getForm();
    
  • Workflow:
    1. Use EntityType for entity selection fields.
    2. Leverage DataTransformer for complex mappings (e.g., JSON fields).
    3. Automatically persist changes via FormEvent::SUBMIT listeners.

3. Security Integration

  • Pattern: Use Doctrine-backed user providers.
    use Symfony\Bridge\Doctrine\Security\User\EntityUserProvider;
    
    $provider = new EntityUserProvider(
        $entityManager,
        User::class
    );
    
  • Workflow:
    1. Implement UserInterface in your entity.
    2. Configure security.yaml to use EntityUserProvider.
    3. Extend with custom role logic via loadUserByIdentifier().

4. Event-Driven Architecture

  • Pattern: Listen to Doctrine lifecycle events.
    use Doctrine\ORM\Event\LifecycleEventArgs;
    
    $eventManager->addEventListener(
        \Doctrine\ORM\Events::prePersist,
        fn(LifecycleEventArgs $args) => $args->getObject()->setCreatedAt(new \DateTime())
    );
    
  • Workflow:
    1. Attach listeners in services.yaml or a bundle.
    2. Use Symfony’s EventDispatcher to trigger custom logic (e.g., logging, notifications).

5. Testing with Doctrine

  • Pattern: Use DatabaseTestCase for database-aware tests.
    use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
    
    class UserTest extends KernelTestCase {
        public function testUserCreation() {
            $user = new User();
            $this->getEntityManager()->persist($user);
            $this->getEntityManager()->flush();
            $this->assertNotNull($user->getId());
        }
    }
    
  • Workflow:
    1. Extend KernelTestCase for full Symfony/Doctrine integration.
    2. Use getEntityManager() to interact with the database.
    3. Leverage transactions for isolated test cases.

Integration Tips

1. Custom Doctrine Types

  • Extend Doctrine\DBAL\Types\Type and register in Symfony:
    # config/packages/doctrine.yaml
    doctrine:
        dbal:
            types:
                json: App\Doctrine\DBAL\Types\JsonType
    

2. Schema Management

  • Use Symfony’s SchemaManager for migrations:
    use Symfony\Bridge\Doctrine\ManagerRegistry;
    
    $schemaManager = $registry->getManager()->getConnection()->createSchemaManager();
    $schemaManager->createTable((new \Doctrine\DBAL\Schema\Table('users'))->addColumn('name', 'string'));
    

3. Messenger with Doctrine

  • Configure Doctrine transports in framework.yaml:
    framework:
        messenger:
            transports:
                doctrine: '%env(MESSENGER_DOCTRINE_DSN)%'
    

4. Deprecation Handling

  • Replace deprecated AbstractDoctrineExtension with standalone services:
    // Before (deprecated)
    class MyExtension extends AbstractDoctrineExtension {}
    
    // After
    class MyExtension {
        public function __construct(private EntityManagerInterface $em) {}
    }
    

Gotchas and Tips

Pitfalls

1. Lazy Loading in Subrequests

  • Issue: Doctrine lazy collections may fail in subrequests (e.g., API platforms).
  • Fix: Use EntityManager::clear() or configure doctrine.orm.enable_lazy_ghost_objects:
    doctrine:
        orm:
            enable_lazy_ghost_objects: false
    

2. Schema Filtering

  • Issue: schema_filter may not apply in custom listeners (pre-v8.0.6).
  • Fix: Explicitly check SchemaListener::getSchemaFilter() in listeners.

3. Oracle Compatibility

  • Issue: Schema subscriber tables may conflict with Oracle’s reserved keywords.
  • Fix: Rename tables (handled automatically in v8.0.7+).

4. UID Custom Types

  • Issue: UidType may fail with custom UID generators.
  • Fix: Ensure UidFactory is properly configured in services.yaml.

5. Form Data Transformers

  • Issue: Manual transformers may break with Symfony 8’s stricter typing.
  • Fix: Use DataTransformerInterface with proper type hints.

Debugging Tips

1. Validation Errors

  • Enable debug mode and check validator.errors in the response:
    $errors = $validator->validate($entity);
    foreach ($errors as $error) {
        echo $error->getPropertyPath() . ': ' . $error->getMessage();
    }
    

2. Query Logging

  • Enable SQL logging in config/packages/dev/doctrine.yaml:
    doctrine:
        dbal:
            logging: true
            profiling: true
    

3. Event Listener Debugging

  • Use EventDispatcher::addListener() with a closure to inspect events:
    $dispatcher->addListener(Events::prePersist, function($event) {
        error_log('PrePersist: ' . $event->getObject()->getId());
    });
    

Extension Points

1. Custom Validators

  • Create a validator that integrates with Doctrine:
    use Symfony\Component\Validator\Constraint;
    use Symfony\Component\Validator\ConstraintValidator;
    use Doctrine\ORM\EntityManagerInterface;
    
    class CustomValidator extends ConstraintValidator {
        public function __construct(private EntityManagerInterface $em) {}
    
        public function validate($value, Constraint $constraint) {
            $query = $this->em->createQuery('SELECT COUNT(u) FROM App\Entity\User u WHERE u.email = :email');
            $query->setParameter('email', $value);
            if ($query->getSingleScalarResult() > 0) {
                $this->context->buildViolation($constraint->message)
                    ->addViolation();
            }
        }
    }
    

2. Dynamic Entity Forms

  • Build forms dynamically based on Doctrine metadata:
    use Symfony\Bridge\Doctrine\Form\Type\EntityType;
    use Doctrine\ORM\Mapping\ClassMetadata;
    
    $metadata = $em->getClassMetadata(User::class);
    $form = $this->createFormBuilder($user)
        ->add('dynamicField', EntityType::class, [
            'class' => $metadata->getAssociationMappings()['role']['targetEntity'],
        ]);
    

3. Doctrine Event Subscribers

  • Extend Doctrine\Common\EventSubscriber for cross-cutting concerns:
    use Doctrine\
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport