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 Json Odm Laravel Package

dunglas/doctrine-json-odm

Doctrine JSON ODM maps JSON documents to PHP objects using Doctrine-style metadata, enabling persistence and querying of JSON data through a familiar ORM-like API. Useful for working with JSON stored in files or other backends while keeping domain models clean.

View on GitHub
Deep Wiki
Context7

Getting Started

First Steps

  1. Installation Update Composer to ensure compatibility with newer dependencies:

    composer require dunglas/doctrine-json-odm:^1.5.0
    

    Verify your config/app.php includes the service provider:

    'providers' => [
        // ...
        Dunglas\DoctrineJsonOdm\DoctrineJsonOdmServiceProvider::class,
    ],
    
  2. Database Setup Ensure your RDBMS supports JSONB (PostgreSQL recommended) or JSON (MySQL 5.7+, SQLite 3.9+). Run migrations to create tables with JSON/JSONB columns. For PostgreSQL, leverage the new jsonb_document type for optimized storage/retrieval.

  3. First Model Define a model with a JSON field (e.g., settings) or use the new jsonb_document type:

    use Dunglas\DoctrineJsonOdm\Mapping\Annotations as Json;
    
    #[Json\Document(collection: "users")]
    class User {
        #[Json\Id]
        private ?string $id;
    
        // Standard JSON field
        #[Json\Field(type: "json")]
        private array $settings = [];
    
        // NEW: jsonb_document type (PostgreSQL optimized)
        #[Json\Field(type: "jsonb_document")]
        private array $metadata = [];
    }
    
  4. Basic CRUD Use Eloquent-like syntax. The package now supports Symfony 8 and DBAL 4.3+:

    $user = new User();
    $user->settings = ['theme' => 'dark'];
    $user->metadata = ['created_at' => now()->toDateTimeString()]; // JSONB-optimized
    $user->save(); // Automatically serializes to JSON/JSONB
    

Implementation Patterns

Common Workflows

  1. Nested JSON Structures Leverage the new jsonb_document type for complex nested data (PostgreSQL):

    #[Json\Field(type: "jsonb_document")]
    private array $profile = [
        'address' => [
            'street' => '',
            'city' => ''
        ],
        'preferences' => ['notifications' => true]
    ];
    
  2. Querying JSON/JSONB Fields Use Doctrine’s query builder with JSONB-specific operators (PostgreSQL):

    $users = $entityManager->createQueryBuilder()
        ->select('u')
        ->from(User::class, 'u')
        ->where('u.metadata @> :value') // JSONB contains operator
        ->setParameter('value', '{"created_at": "2023-01-01"}')
        ->getQuery()
        ->getResult();
    
  3. Hybrid ORM/ODM Combine with Eloquent for relational data. Ensure jsonb_document fields are used where performance is critical:

    #[Json\Document(collection: "posts")]
    class Post {
        #[Json\Id]
        private ?int $id;
    
        #[Json\Field(type: "jsonb_document")] // Optimized for large metadata
        private array $metadata;
    
        #[Json\ReferenceOne(targetDocument: User::class)]
        private ?User $author;
    }
    
  4. Event Listeners Hook into lifecycle events for pre/post-processing (now compatible with Symfony 8):

    $entityManager->getEventManager()->addEventListener(
        \Doctrine\ODM\MongoDB\Events::prePersist,
        function ($event) {
            $user = $event->getDocument();
            $user->metadata['last_updated'] = now()->toDateTimeString();
        }
    );
    
  5. Custom Types Extend JsonType or JsonbDocumentType (new) for domain-specific logic:

    use Dunglas\DoctrineJsonOdm\Types\JsonbDocumentType;
    
    class TagsType extends JsonbDocumentType {
        public function convertToPHPValue($value) {
            return explode(',', $value['tags'] ?? '');
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Schema Migrations

    • JSONB vs. JSON: JSONB columns cannot be altered in-place (PostgreSQL). Use migrations:
      Schema::table('users', function (Blueprint $table) {
          $table->jsonb('metadata')->nullable()->change(); // Explicit JSONB
      });
      
    • Downgrading: Avoid downgrading from JSONB to JSON if using jsonb_document type.
  2. Case Sensitivity

    • JSONB keys are case-sensitive. Use PostgreSQL’s jsonb_path_ops for case-insensitive queries:
      $query->where('u.metadata ? :value')->setParameter('value', '{"Theme": "dark"}');
      
  3. Circular References

    • Avoid circular references in JSON/JSONB fields. Use @Json\ReferenceOne for relationships.
  4. Performance

    • JSONB > JSON: Prefer jsonb_document for large datasets or frequent queries (PostgreSQL).
    • Indexing: Add functional indexes for JSONB fields:
      #[Json\Index(name: "metadata_created_idx", fields: ["metadata->>'created_at'"])]
      

Debugging

  • Query Logging: Enable logging to inspect generated SQL (works with DBAL 4.3+):
    $entityManager->getConnection()->getConfiguration()->setSQLLogger(
        new \Doctrine\DBAL\Logging\EchoSQLLogger()
    );
    
  • Symfony 8 Compatibility: Ensure symfony/dependency-injection and symfony/http-client are updated:
    composer require symfony/dependency-injection:^6.3 symfony/http-client:^6.3
    

Extension Points

  1. Custom Hydration Override JsonbDocumentType::convertToPHPValue() for domain objects:

    public function convertToPHPValue($value) {
        return new SettingsCollection(json_decode($value, true));
    }
    
  2. Indexing Use PostgreSQL’s GIN indexes for JSONB fields:

    #[Json\Index(name: "metadata_gin_idx", type: "gin")]
    private array $metadata;
    
  3. Validation Combine with Symfony’s Validator (tested with Symfony 8):

    use Symfony\Component\Validator\Constraints as Assert;
    
    #[Json\Field(type: "jsonb_document")]
    #[Assert\All({
        new Assert\Type('string'),
        new Assert\Length(max: 50)
    })]
    private array $tags;
    
  4. Caching Cache queries with Doctrine\Common\Cache\CacheProvider (works with Symfony 8):

    $query->useResultCache(true, 3600, 'app_jsonb_odm_cache');
    
  5. Symfony 8 Integration

    • Use autowire: true in config/services.yaml for dependency injection:
      services:
          Dunglas\DoctrineJsonOdm\DoctrineJsonOdmServiceProvider:
              autowire: true
      
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.
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
spatie/laravel-javascript-views