effiana / doctrine-json-odm

使用现代关系型数据库管理系统(RDBMS)的JSON类型,为Doctrine ORM提供对象文档映射器。

dev-master 2019-01-17 12:04 UTC

This package is auto-updated.

Last update: 2024-09-18 02:47:05 UTC


README

Doctrine ORM的对象文档映射器(ODM),利用现代关系型数据库管理系统(RDBMS)的新JSON类型。

Build Status Scrutinizer Code Quality SensioLabsInsight StyleCI

你是否曾经梦想过一款工具,可以将传统高效的数据库映射与现代无模式和无SQL风格的数据库映射结合起来创建强大的数据模型?

使用Doctrine JSON ODM,现在可以轻松创建和查询这种混合数据模型。得益于现代关系型数据库管理系统的JSON类型,查询无模式文档变得容易、强大且非常快速(性能与MongoDB数据库相似)!您甚至可以为这些文档定义索引

Doctrine JSON ODM允许将PHP对象以JSON文档的形式存储在关系型数据库管理系统的动态列中。它与PostgreSQL(>= 9.4)的JSON和JSONB列以及MySQL(>= 5.7.8)的JSON列兼容。

有关Doctrine JSON ODM背后的概念更多信息,请参阅Benjamin Eberlei在Symfony Catalunya 2016上给出的演示

安装

要安装此库,请使用Composer,PHP包管理器

composer require dunglas/doctrine-json-odm

如果您使用Symfony 4+API Platform,您无需做任何操作!如果您直接使用Doctrine,请使用类似以下的自启动代码

<?php

require_once __DIR__.'/../vendor/autoload.php'; // Adapt to your path

use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\Setup;
use Effiana\DoctrineJsonOdm\Normalizer\ObjectNormalizer;
use Effiana\DoctrineJsonOdm\Type\JsonDocumentType;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer as BaseObjectNormalizer;

if (!Type::hasType('json_document')) {
    Type::addType('json_document', JsonDocumentType::class);
    Type::getType('json_document')->setSerializer(
        new Serializer([new ObjectNormalizer(new BaseObjectNormalizer())], [new JsonEncoder()])
    );
}

// Sample bootstrapping code here, adapt to fit your needs
$isDevMode = true;
$config = Setup::createAnnotationMetadataConfiguration([__DIR__ . '/../src'], $_ENV['DEBUG'] ?? false); // Adapt to your path

$conn = [
    'dbname' => $_ENV['DATABASE_NAME'],
    'user' => $_ENV['DATABASE_USER'],
    'password' => $_ENV['DATABASE_PASSWORD'],
    'host' => $_ENV['DATABASE_HOST'],
    'driver' => 'pdo_mysql' // or pdo_pgsql
];

return EntityManager::create($conn, $config);

使用Symfony 2和3安装

此库为Symfony框架提供了一个包。如果您使用Symfony 4+,它会自动注册。对于Symfony 2和3,您必须自行注册

// ...

use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
use Effiana\DoctrineJsonOdm\Bundle\DunglasDoctrineJsonOdmBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Component\HttpKernel\Kernel;

class AppKernel extends Kernel
{
    public function registerBundles()
    {
        return [
            new FrameworkBundle(),
            new DoctrineBundle(),
            new DunglasDoctrineJsonOdmBundle(),

            // ...
        ];
    }

    // ...
}

使用方法

Doctrine JSON ODM为Doctrine实体的属性提供了json_document列类型。

使用此类型映射的属性的 内容使用Symfony Serializer序列化,然后存储在数据库的动态JSON列中。

当对象将被活化时,该列的JSON内容将再次转换回原始值,再次得益于Symfony Serializer。所有PHP对象和结构都将被保留(如果您使用Symfony >= 3.1,请参阅常见问题解答)。

您可以使用json_document类型将任何类型的(可序列化的)PHP数据结构存储在映射的属性中。

示例

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * This is a typical Doctrine ORM entity.
 *
 * @ORM\Entity
 */
class Foo
{
  /**
   * @ORM\Column(type="integer")
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  public $id;

  /**
   * @ORM\Column(type="string")
   */
  public $name;

  /**
   * Can contain anything (array, objects, nested objects...).
   *
   * @ORM\Column(type="json_document", options={"jsonb": true})
   */
  public $misc;

  // Works with private and protected methods with getters and setters too.
}
namespace AppBundle\Entity;

/**
 * This is NOT an entity! It's a POPO (Plain Old PHP Object). It can contain anything.
 */
class Bar
{
    public $title;
    public $weight;
}
namespace AppBundle\Entity;

/**
 * This is NOT an entity. It's another POPO and it can contain anything.
 */
class Baz
{
    public $name;
    public $size;
}

将随机对象图存储在数据库的JSON类型中

// $entityManager = $this->get('doctrine')->getManagerForClass(AppBundle\Entity\Foo::class);

$bar = new Bar();
$bar->title = 'Bar';
$bar->weight = 12;

$baz = new Baz();
$baz->name = 'Baz';
$baz->size = 7;

$foo = new Foo();
$foo->name = 'Foo';
$foo->misc = [$bar, $baz]

$entityManager->persist($foo);
$entityManager->flush();

检索对象图

$foo = $entityManager->find(Foo::class, $foo->getId());
var_dump($foo->misc); // Same as what we set earlier

您可以使用原生查询执行复杂查询。请参阅PostgreSQL文档MySQL文档了解如何查询存储的JSON文档。

常见问题解答

支持哪些数据库管理系统(DBMS)?

支持PostgreSQL 9.4+和MySQL 5.7+。

支持Doctrine的哪些版本?

支持 Doctrine ORM 2.6+ 和 DBAL 2.6+。

如何使用PostgreSQL 的 JSONB 类型

然后,您需要在列映射中设置一个选项

// ...

    /**
     * @ORM\Column(type="json_document", options={"jsonb": true})
     */
    public $foo;

// ...

ODM 支持嵌套对象和对象图吗?

是的。

如何添加额外的规范器?

Symfony 序列化器易于扩展。此包注册并使用 ID 为 effiana_doctrine_json_odm.serializer 的服务作为 JSON 类型的序列化器。这意味着我们可以轻松地在我们的 services.yaml 中覆盖它以使用额外的规范器。例如,我们使用 Symfony 的 DateTimeNormalizer 服务,因此我们支持任何是 \DateTimeInterface 实例的属性。请注意,规范器的顺序可能与您使用的规范器相关。

    # Add DateTime Normalizer to Dunglas' Doctrine JSON ODM Bundle
    effiana_doctrine_json_odm.serializer:
        class: Symfony\Component\Serializer\Serializer
        arguments:
          - ['@serializer.normalizer.datetime', '@effiana_doctrine_json_odm.normalizer.object']
          - ['@serializer.encoder.json']
        public: true

作为旁注:如果您在 services.yaml 中使用自动注入,您可能还需要设置 autowire: false

运行测试

要执行测试套件,您需要运行 PostgreSQL 和 MySQL 服务器。在您的 shell 中运行以下命令以设置必需的环境变量

export POSTGRESQL_HOST=127.0.0.1
export POSTGRESQL_USER=dunglas
export POSTGRESQL_PASSWORD=
export POSTGRESQL_DBNAME=my_test_db

export MYSQL_HOST=127.0.0.1
export MYSQL_USER=dunglas
export MYSQL_PASSWORD=
export MYSQL_DBNAME="my_test_db

数据库必须存在。请注意,其内容可能会被删除。

运行测试套件,执行 PHPUnit

phpunit

鸣谢

此包由 Kévin DunglasYanick Witschi杰出的贡献者 提供。由 Les-Tilleuls.coop 赞助。