c33s / doctrine-extra
A Collection of Traits which can be used to build a Doctrine Entity.
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
A Collection of Traits which can be used to build a Doctrine Entity.
Example Entity 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;
}
Requirements
Minimum Php version is 7.1
Custom Types Abstract Classes
if you prefer to work with value objects you can easily define new doctrine orm types (like string
) with the available
abstract types. there are three abstract types you can use:
AbstractValueObjectJsonType
for using with objects which can be serialized into arrays/jsonAbstractValueObjectStringType
used for simple string value objects like for a nameAbstractValueObjectTextType
the same asAbstractValueObjectStringType
but extends Doctrines TextType to use the correct database field for text.
if you want to create a custom type address
to put into your Person
entity
first create a value object for your address (which can of course contain other objects). it must implement the array interface so the data can be converted to an array.
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;
}
then create your custom type where the name is the name of the type and valueObject class is the class it should be mapped to.
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
Fields
Basic Definitions
- Embeds... -> `@ORM\Embedded(class="...")
- Has... ->
@ORM\Column(type="...")
&getProperty(): ?type
&setProperty(?type $property)
- Requires... ->
@ORM\Column(type="...", nullable=false)
&@Assert\NotBlank()
&getProperty(): ?type
&setProperty(type $property)
- RequiresUnique... ->
@ORM\Column(type="...", unique=true, nullable=false)
&@Assert\NotBlank()
&getProperty(): ?type
&setProperty(type $property)
Requires Traits use
@var Type|null
for ease of use with__construct($name=null)
defaultsgetProperty(): ?type
because the function may be called before the property is set - for example in EasyAdminBundle when adding a new entry
Available Fields
- HasDate
- HasDescription
- HasDisplayName
- HasEmail
- HasEmbeddedEmail
- HasFaxNumber
- HasFirstName
- HasIsActive
- HasIsEnabled
- HasIsPublished
- HasIsVisible
- HasLastName
- HasPhoneNumber
- HasPostTitle
- HasPreTitle
- HasRank
- HasRoles
- HasSlugFromName
- HasUserSerializer
- RequiresDate
- RequiresDescription
- RequiresEmail
- RequiresFaxNumber
- RequiresFirstName
- RequiresId
- RequiresLastName
- RequiresPassword
- RequiresPhoneNumber
- RequiresPostTitle
- RequiresRank
- RequiresUrl
- RequiresUniqueName
- RequiresUniqueUrl
- RequiresUniqueUsername
- EntityHasUploadableImage: found in src/Entity/Traits/Field/edition -> copy to src/Entity/Traits/Field/
- Replace Trait name to reflect the name of your Entity (like
ProductHasUploadableImage
) - change namesapce
- adjust mapping(currently
entity_image
)* @Vich\UploadableField(mapping="entity_image", fileNameProperty="imageName", size="imageSize")
- create vich_uploader configuration for your mapping
vich_uploader: mappings: entity_image: # see config/app/vich_uploader.yaml or config/edition/vich_uploader.yaml for examples
Behavior
- IsBlameable
- IsFeatureFlagable
- IsPublishable
- IsTimestampable
Method
- HasDummyAdvancedUserInterface
- HasDummySalt
- HasParentAndChildren
General
- UploadableTypeEmbeddedTrait
RequirePassword & User Entity & UserBundle
we need an entity called LoginUser
to work with this lib out of the box. in the user bundle RequirePassword
is used.
The user entity should implement Serializable
, EquatableInterface
, UserInterface
RequiresPassword
is a little bit tricky because of the requirement of hashed/crypted passwords. we have two fields
password
and plainPassword
. the password
field is the only mapped field. plainPassword
is only used to set a
plain password which will be auto-encoded using an event listener.
Overriding Metadata of Traits
this will override length
and all @Assert
. so in this case no @Assert\NotBlank
from the Trait. this works out
of the box without the
<?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