PHP Doctrine:在自定义 DBAL 类型中使用相同类如 embbebed 和实体 ID的问题

问题描述

我正在尝试在我的开发中实现 DDD 概念,但我在使用 PHP Doctrine ORM 时遇到了问题。

首先,我想告诉你我的设计。我有一个实体调用 Order,一个 Order 有一个 ProductId 属性。所以,我的班级模型是这样的:

Order.php

<?php
final class Order
{
    protected OrderId $id;
    protected ProductId $product_id;
    protected ProductName $name;

    public function setProductId($product_id)
    {
        $this->product_id = $product_id;
    }

    public function getProductId()
    {
        return $this->product_id;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }
    
}

Product.php

<?php
final class Product
{
    protected ProductId $id;
    protected ProductName $name;
    protected $categories;

    public function setId($id)
    {
        $this->id = $id;
    }

    public function getId()
    {
        return $this->id;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }
    
    public function assignToCategory(Category $category)
    {
        $this->categories[] = $category;
    }

    public function getCategory()
    {
        return $this->categories;
    }
}

映射 XML 是:

Order.dcm.xml

<!-- config/xml/Product.dcm.xml -->
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
                          https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

    <entity name="Order" table="orders">
        <id name="id" type="order_id" column="id" length="36" />
        <embedded name="product_id" class="ProductId" use-column-prefix="false" />
        <embedded name="name" class="ProductName" use-column-prefix="false" />
        
    </entity>
</doctrine-mapping>

Product.dcm.xml

<!-- config/xml/Product.dcm.xml -->
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
                          https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

    <entity name="Product" table="products">
        <id name="id" type="product_id" column="id" length="36" />
        <embedded name="name" class="ProductName" use-column-prefix="false" />
        <many-to-many target-entity="Category" field="categories" />
    </entity>
</doctrine-mapping>

如您所见,从一方面来说,对于 Order ORM 映射,我对 product_id 字段使用了 embeddable,另一方面,对于 Product ORM 映射,我对 id 字段使用了自定义类型。 这是产品的 id 自定义 DBAL 类型定义:

ProductIdType.php

<?php
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\StringType;

class ProductIdType extends StringType
{
    public function getName(): string
    {
        return self::customTypeName();
    }

    public function convertToPHPValue($value,AbstractPlatform $platform)
    {
        $className = $this->typeClassName();

        return new $className($value);
    }

    public function convertToDatabaseValue($value,AbstractPlatform $platform)
    {
        return $value->value();
    }

    public static function customTypeName(): string
    {
        return 'product_id';
    }

    protected function typeClassName(): string
    {
        return ProductId::class;
    }
}

这里是需要订单 XML 映射的 ProductId XML 映射:

ProductId.dcm.xml

<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
                          https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

    <embeddable name="ProductId">
        <field name="value" type="string" column="product_id" />
    </embeddable>

</doctrine-mapping>

问题是当我尝试查找一个订单,然后在同一个脚本中尝试查找产品时。我认为问题在于同一类 ProductId 在同一脚本中用作可嵌入和自定义 DBAL 类型。但我希望有人能告诉我我是否正确,以及是否知道如何在不为 Order embedable 创建新类的情况下实现这一点。

我正在运行的脚本是:

show_product.php

<?php
require_once "bootstrap.php";

$id = $argv[1];

$order = $entityManager->find('Order',new OrderId($id));

if ($order === null) {
    echo "No product found.\n";
    exit(1);
}

echo print_r($order->getName());

$product = $entityManager->find('Product',new ProductId($id));

if ($product === null) {
    echo "No product found.\n";
    exit(1);
}

echo print_r($product->getName());

还有我的错误:

PHP Notice:  Undefined offset: 0 in /home/dani/www/dev/doctrine2-test/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php on line 769
PHP Stack trace:
PHP   1. {main}() /home/dani/www/dev/doctrine2-test/src/show_product.php:0
PHP   2. Doctrine\ORM\EntityManager->find() /home/dani/www/dev/doctrine2-test/src/show_product.php:16
PHP   3. Doctrine\ORM\UnitOfWork->getSingleIdentifierValue() /home/dani/www/dev/doctrine2-test/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:419
PHP   4. Doctrine\ORM\Mapping\ClassMetadata->getIdentifierValues() /home/dani/www/dev/doctrine2-test/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:3065

如果有人想查看所有代码,这里是 Github 存储库:https://github.com/daf111/doctrine2-test

非常感谢您抽出宝贵时间!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...