c33s / doctrine-extra
一组可用于构建Doctrine实体的特性。
Requires
- php: ^7.1.0
- doctrine/orm: >=2.4
Requires (Dev)
- c33s/parameter-objects-bundle: ^1.0.1
- codeception/codeception: ^4.1.22
- codeception/module-asserts: ^1.3.1
- codeception/module-cli: ^1.1.0
- codeception/module-filesystem: ^1.0.3
- doctrine/dbal: *
- doctrine/doctrine-fixtures-bundle: ^3.0.0
- doctrine/orm: ^2.7.5
- flagception/flagception: *
- gedmo/doctrine-extensions: *
- hidehalo/nanoid-php: *
- ramsey/uuid: *
- ramsey/uuid-doctrine: *
- symfony/http-foundation: *
- symfony/validator: *
- symfony/var-dumper: *
- theofidry/alice-data-fixtures: *
- vich/uploader-bundle: *
Suggests
- c33s/doctrine-extra-bundle: for registering InjectFeatureManagerListener as service
- c33s/parameter-objects-bundle: required for EnvironmentSpecificFixture (provides KernelEnvironment)
- c33s/user-bundle
- flagception/flagception
- gedmo/doctrine-extensions
- hidehalo/nanoid-php
- ramsey/uuid
- ramsey/uuid-doctrine
- symfony/event-dispatcher
- symfony/http-foundation
- symfony/validator
- symfony/var-dumper: *
- vich/uploader-bundle
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
用于简单的字符串值对象,例如名称AbstractValueObjectTextType
与AbstractValueObjectStringType
相同,但扩展了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
。用户实体应实现Serializable
、EquatableInterface
、UserInterface
RequiresPassword
有些复杂,因为需要哈希/加密密码。我们有两个字段:password
和plainPassword
。只有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