c33s / doctrine-extra
A Collection of Traits which can be used to build a Doctrine Entity.
Installs: 183
Dependents: 1
Suggesters: 0
Security: 0
Stars: 1
Forks: 0
pkg:composer/c33s/doctrine-extra
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:
AbstractValueObjectJsonTypefor using with objects which can be serialized into arrays/jsonAbstractValueObjectStringTypeused for simple string value objects like for a nameAbstractValueObjectTextTypethe same asAbstractValueObjectStringTypebut 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|nullfor ease of use with__construct($name=null)defaultsgetProperty(): ?typebecause 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