c33s/doctrine-extra

一组可用于构建Doctrine实体的特性。


README

一组可用于构建Doctrine实体的特性。

示例实体 Customer

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use C33s\Entity\Traits\Field;
use C33s\Entity\Traits\Behaviour;
use C33s\Entity\Embeddable\CustomerNumber;
use Gedmo\Timestampable\Traits\TimestampableEntity;

class Customer
{
    use Field\RequiresId;
    use Field\RequiresUniqueName;
    use Field\RequiresEmail;
    use Field\HasDescription;
    use Field\HasIsActive;
    use Behaviour\IsTimestampable;
    use Behaviour\IsPublishable;
    use TimestampableEntity;
}

需求

最低PHP版本为7.1

自定义类型抽象类

如果你更喜欢使用值对象,你可以轻松定义新的Doctrine ORM类型(如string),使用可用的抽象类型。你可以使用以下三种抽象类型

  • AbstractValueObjectJsonType 用于可以序列化为数组/json的对象
  • AbstractValueObjectStringType 用于简单的字符串值对象,例如名称
  • AbstractValueObjectTextTypeAbstractValueObjectStringType 相同,但扩展了Doctrines TextType以使用正确的数据库字段用于文本。

如果你想创建一个名为address的自定义类型并将其放入Person实体中

首先创建一个地址值对象(它当然可以包含其他对象)。它必须实现数组接口,以便可以将数据转换为数组。

src/Value/Address.php:


use C33s\Doctrine\Interfaces\ArrayInterface;

final class Address extends ArrayInterface
{
    private AddressLine $streetLine1;
    private AddressLine $streetLine2;
    private City $city;
    private Zip $zip;
    private Province $province;
    private CountryCode $country;
}

然后创建你的自定义类型,其中名称是类型的名称,valueObject类是要映射到的类。

src/ORM/Types/AddressType.php:

namespace App\ORM\Types;

use App\Value\Address;
use C33s\Doctrine\Types\AbstractValueObjectJsonType;

class AddressType extends AbstractValueObjectJsonType
{
    protected $name = 'address';
    protected $valueObjectClass = Address::class;
}

App/Entity/Person.php:

class Person
{
    /**
     * @ORM\Column(type="string", length=255)
     */
    private $name;

    /**
     * @ORM\Column(type="address")
     */
    private $address;
    
    public function getAddress(): Address
    {
        return $this->address;    
    }
      
}

config/../doctrine.yaml:

doctrine:
    dbal:
        types:
            address: App\ORM\Types\AddressType

字段

基本定义

  • 嵌入... -> @ORM\Embedded(class="...")
  • 具有... -> @ORM\Column(type="...") & getProperty(): ?type & setProperty(?type $property)
  • 需要... -> @ORM\Column(type="...", nullable=false) & @Assert\NotBlank() & getProperty(): ?type & setProperty(type $property)
  • 需要唯一... -> @ORM\Column(type="...", unique=true, nullable=false) & @Assert\NotBlank() & getProperty(): ?type & setProperty(type $property)

需要特性使用

  • @var Type|null 以便于与 __construct($name=null) 默认值一起使用
  • getProperty(): ?type 因为该函数可能在设置属性之前被调用 - 例如在EasyAdminBundle添加新条目时

可用字段

  • 有日期
  • 有描述
  • 有显示名称
  • 有电子邮件
  • 有嵌入式电子邮件
  • 有传真号码
  • 有名
  • 有活动状态
  • 有启用状态
  • 有发布状态
  • 有可见状态
  • 有姓
  • 有电话号码
  • 有帖子标题
  • 有前置标题
  • 有等级
  • 有角色
  • 有名缩写
  • 有用户序列化器
  • 需要日期
  • 需要描述
  • 需要电子邮件
  • 需要传真号码
  • 需要名
  • 需要ID
  • 需要姓
  • 需要密码
  • 需要电话号码
  • 需要帖子标题
  • 需要等级
  • 需要URL
  • 需要唯一名称
  • 需要唯一URL
  • 需要唯一用户名
  • 实体有可上传的图像:在src/Entity/Traits/Field/edition -> 复制到src/Entity/Traits/Field/
  • 将特性名称更改为反映实体的名称(如ProductHasUploadableImage
  • 更改命名空间
  • 调整映射(当前entity_image
     * @Vich\UploadableField(mapping="entity_image", fileNameProperty="imageName", size="imageSize")
    
  • 为你的映射创建vich_uploader配置
    vich_uploader:
    mappings:
      entity_image:
    # see config/app/vich_uploader.yaml or config/edition/vich_uploader.yaml for examples
    

行为

  • 可归责的
  • 可特性标记的
  • 可发布的
  • 可时间戳的

方法

  • 有虚拟高级用户接口
  • 有虚拟盐
  • 有父子关系

通用

  • 可上传类型内嵌特性

需要密码 & 用户实体 & 用户包

我们需要一个名为LoginUser的实体来与这个库一起工作。在用户包中使用了RequirePassword。用户实体应实现SerializableEquatableInterfaceUserInterface

RequiresPassword有些复杂,因为需要哈希/加密密码。我们有两个字段:passwordplainPassword。只有password字段是映射字段。plainPassword仅用于设置明文密码,它将通过事件监听器自动编码。

覆盖特性元数据

这将会覆盖length以及所有的@Assert。因此在这种情况下,来自特质的@Assert\NotBlank不会生效。这无需任何修改即可直接使用。

<?php


namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use C33s\Doctrine\Entity\Traits\Field;

/**
 * @ORM\Entity()
 * @codeCoverageIgnore
 */
class OverrideTest
{
    use Field\RequiresId;
    use Field\RequiresEmail;

    /**
     * @var string
     *
     * @ORM\Column(type="string", length=10, unique=true)
     * @Assert\Email()
     */
    protected $email;
}

https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/tutorials/override-field-association-mappings-in-subclasses.html https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/inheritance-mapping.html https://stackoverflow.com/questions/32571920/overriding-doctrine-trait-properties https://andy-carter.com/blog/overriding-extending-a-php-trait-method