Move Custom Mapping Types into cookbook, restructure the chapter more.
This commit is contained in:
parent
caf6ba65e8
commit
546c817f64
97
docs/en/cookbook/custom-mapping-types.rst
Normal file
97
docs/en/cookbook/custom-mapping-types.rst
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
Custom Mapping Types
|
||||||
|
====================
|
||||||
|
|
||||||
|
Doctrine allows you to create new mapping types. This can come in
|
||||||
|
handy when you're missing a specific mapping type or when you want
|
||||||
|
to replace the existing implementation of a mapping type.
|
||||||
|
|
||||||
|
In order to create a new mapping type you need to subclass
|
||||||
|
``Doctrine\DBAL\Types\Type`` and implement/override the methods as
|
||||||
|
you wish. Here is an example skeleton of such a custom type class:
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
namespace My\Project\Types;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Types\Type;
|
||||||
|
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* My custom datatype.
|
||||||
|
*/
|
||||||
|
class MyType extends Type
|
||||||
|
{
|
||||||
|
const MYTYPE = 'mytype'; // modify to match your type name
|
||||||
|
|
||||||
|
public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
|
||||||
|
{
|
||||||
|
// return the SQL used to create your column type. To create a portable column type, use the $platform.
|
||||||
|
}
|
||||||
|
|
||||||
|
public function convertToPHPValue($value, AbstractPlatform $platform)
|
||||||
|
{
|
||||||
|
// This is executed when the value is read from the database. Make your conversions here, optionally using the $platform.
|
||||||
|
}
|
||||||
|
|
||||||
|
public function convertToDatabaseValue($value, AbstractPlatform $platform)
|
||||||
|
{
|
||||||
|
// This is executed when the value is written to the database. Make your conversions here, optionally using the $platform.
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return self::MYTYPE; // modify to match your constant name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
The following assumptions are applied to mapping types by the ORM:
|
||||||
|
|
||||||
|
- If the value of the field is *NULL* the method
|
||||||
|
``convertToDatabaseValue()`` is not called.
|
||||||
|
- The ``UnitOfWork`` never passes values to the database convert
|
||||||
|
method that did not change in the request.
|
||||||
|
|
||||||
|
When you have implemented the type you still need to let Doctrine
|
||||||
|
know about it. This can be achieved through the
|
||||||
|
``Doctrine\DBAL\Types\Type#addType($name, $className)``
|
||||||
|
method. See the following example:
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// in bootstrapping code
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Types\Type;
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
// Register my type
|
||||||
|
Type::addType('mytype', 'My\Project\Types\MyType');
|
||||||
|
|
||||||
|
To convert the underlying database type of your
|
||||||
|
new "mytype" directly into an instance of ``MyType`` when performing
|
||||||
|
schema operations, the type has to be registered with the database
|
||||||
|
platform as well:
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$conn = $em->getConnection();
|
||||||
|
$conn->getDatabasePlatform()->registerDoctrineTypeMapping('db_mytype', 'mytype');
|
||||||
|
|
||||||
|
When registering the custom types in the configuration you specify a unique
|
||||||
|
name for the mapping type and map that to the corresponding fully qualified
|
||||||
|
class name. Now the new type can be used when mapping columns:
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
class MyPersistentClass
|
||||||
|
{
|
||||||
|
/** @Column(type="mytype") */
|
||||||
|
private $field;
|
||||||
|
}
|
||||||
|
|
@ -7,8 +7,9 @@ After working through this guide you should know:
|
|||||||
- How to create PHP classes that can be saved in the database with Doctrine
|
- How to create PHP classes that can be saved in the database with Doctrine
|
||||||
- How to configure the mapping between columns on tables and properties on
|
- How to configure the mapping between columns on tables and properties on
|
||||||
entities.
|
entities.
|
||||||
|
- What Doctrine Mapping types are
|
||||||
- Defining primary keys and how identifiers are generated by Doctrine
|
- Defining primary keys and how identifiers are generated by Doctrine
|
||||||
- What Doctrine types are
|
- How quoting of reserved symbols works in Doctrine
|
||||||
|
|
||||||
Mapping of associations will be covered in the next chapter on
|
Mapping of associations will be covered in the next chapter on
|
||||||
:doc:`Association Mapping <association-mapping>`.
|
:doc:`Association Mapping <association-mapping>`.
|
||||||
@ -41,7 +42,10 @@ example Entity:
|
|||||||
|
|
||||||
Because Doctrine is a generic library, it can only know about your
|
Because Doctrine is a generic library, it can only know about your
|
||||||
entities when you are describing their existance and structure using
|
entities when you are describing their existance and structure using
|
||||||
Metadata Configuration.
|
Metadata Mapping, a pattern `described by Martin Fowler in PoEAA
|
||||||
|
<http://martinfowler.com/eaaCatalog/metadataMapping.html>`_. Because
|
||||||
|
of this pattern the documentation will often speak of "mapping something",
|
||||||
|
which means that we use the metadata mapping pattern to use this feature.
|
||||||
|
|
||||||
Doctrine provides several different ways for specifying object-relational
|
Doctrine provides several different ways for specifying object-relational
|
||||||
mapping metadata:
|
mapping metadata:
|
||||||
@ -207,10 +211,11 @@ list:
|
|||||||
Doctrine Mapping Types
|
Doctrine Mapping Types
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
A Doctrine Mapping Type defines the conversion the type of a PHP variable and
|
The ``type`` option used in the ``@Column`` accepts any of the existing
|
||||||
an SQL type. All Mapping Types that ship with Doctrine are fully portable
|
Doctrine types or even your own custom types. A Doctrine type defines
|
||||||
between the supported database systems. You can add your own custom mapping
|
the conversion between PHP and SQL types, indepedant from the database vendor
|
||||||
types to add more conversions.
|
you are using. All Mapping Types that ship with Doctrine are fully portable
|
||||||
|
between the supported database systems.
|
||||||
|
|
||||||
As an example the Doctrine Mapping Type ``string`` defines the
|
As an example the Doctrine Mapping Type ``string`` defines the
|
||||||
mapping from a PHP string to a SQL VARCHAR (or VARCHAR2 etc.
|
mapping from a PHP string to a SQL VARCHAR (or VARCHAR2 etc.
|
||||||
@ -222,7 +227,7 @@ built-in mapping types:
|
|||||||
- ``smallint``: Type that maps a database SMALLINT to a PHP
|
- ``smallint``: Type that maps a database SMALLINT to a PHP
|
||||||
integer.
|
integer.
|
||||||
- ``bigint``: Type that maps a database BIGINT to a PHP string.
|
- ``bigint``: Type that maps a database BIGINT to a PHP string.
|
||||||
- ``boolean``: Type that maps a SQL boolean to a PHP boolean.
|
- ``boolean``: Type that maps a SQL boolean or equivalent (TINYINT) to a PHP boolean.
|
||||||
- ``decimal``: Type that maps a SQL DECIMAL to a PHP string.
|
- ``decimal``: Type that maps a SQL DECIMAL to a PHP string.
|
||||||
- ``date``: Type that maps a SQL DATETIME to a PHP DateTime
|
- ``date``: Type that maps a SQL DATETIME to a PHP DateTime
|
||||||
object.
|
object.
|
||||||
@ -248,10 +253,14 @@ built-in mapping types:
|
|||||||
varchar but uses a specific type if the platform supports it.
|
varchar but uses a specific type if the platform supports it.
|
||||||
- ``blob``: Type that maps a SQL BLOB to a PHP resource stream
|
- ``blob``: Type that maps a SQL BLOB to a PHP resource stream
|
||||||
|
|
||||||
|
A cookbook article shows how to define :doc:`your own custom mapping types
|
||||||
|
<../cookbook/custom-mapping-types>`.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
DateTime and Object types are compared by reference, not by value. Doctrine updates this values
|
DateTime and Object types are compared by reference, not by value. Doctrine
|
||||||
if the reference changes and therefore behaves as if these objects are immutable value objects.
|
updates this values if the reference changes and therefore behaves as if
|
||||||
|
these objects are immutable value objects.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
@ -266,22 +275,24 @@ built-in mapping types:
|
|||||||
on working with datetimes that gives hints for implementing
|
on working with datetimes that gives hints for implementing
|
||||||
multi timezone applications.
|
multi timezone applications.
|
||||||
|
|
||||||
|
|
||||||
Identifiers / Primary Keys
|
Identifiers / Primary Keys
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
Every entity class needs an identifier/primary key. You designate
|
Every entity class requires an identifier/primary key. You can select
|
||||||
the field that serves as the identifier with the ``@Id``
|
the field that serves as the identifier with the ``@Id``
|
||||||
annotation:
|
annotation.
|
||||||
|
|
||||||
.. configuration-block::
|
.. configuration-block::
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
class MyPersistentClass
|
class Message
|
||||||
{
|
{
|
||||||
/** @Id @Column(type="integer") */
|
/**
|
||||||
|
* @Id @Column(type="integer")
|
||||||
|
* @GeneratedValue
|
||||||
|
*/
|
||||||
private $id;
|
private $id;
|
||||||
//...
|
//...
|
||||||
}
|
}
|
||||||
@ -289,58 +300,17 @@ annotation:
|
|||||||
.. code-block:: xml
|
.. code-block:: xml
|
||||||
|
|
||||||
<doctrine-mapping>
|
<doctrine-mapping>
|
||||||
<entity name="MyPersistentClass">
|
<entity name="Message">
|
||||||
<id name="id" type="integer" />
|
|
||||||
<field name="name" length="50" />
|
|
||||||
</entity>
|
|
||||||
</doctrine-mapping>
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
MyPersistentClass:
|
|
||||||
type: entity
|
|
||||||
id:
|
|
||||||
id:
|
|
||||||
type: integer
|
|
||||||
fields:
|
|
||||||
name:
|
|
||||||
length: 50
|
|
||||||
|
|
||||||
This definition is missing an ID generation strategy, which means that your code needs to assign
|
|
||||||
the identifier manually before passing a new entity to
|
|
||||||
``EntityManager#persist($entity)``.
|
|
||||||
|
|
||||||
Doctrine can alternatively generate identifiers for entities using generation strategies,
|
|
||||||
using database sequences or auto incrementing numbers.
|
|
||||||
|
|
||||||
.. configuration-block::
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
class MyPersistentClass
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @Id @Column(type="integer")
|
|
||||||
* @GeneratedValue
|
|
||||||
*/
|
|
||||||
private $id;
|
|
||||||
}
|
|
||||||
|
|
||||||
.. code-block:: xml
|
|
||||||
|
|
||||||
<doctrine-mapping>
|
|
||||||
<entity name="MyPersistentClass">
|
|
||||||
<id name="id" type="integer">
|
<id name="id" type="integer">
|
||||||
<generator strategy="AUTO" />
|
<generator strategy="AUTO" />
|
||||||
</id>
|
</id>
|
||||||
<field name="name" length="50" />
|
<!-- -->
|
||||||
</entity>
|
</entity>
|
||||||
</doctrine-mapping>
|
</doctrine-mapping>
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
MyPersistentClass:
|
Message:
|
||||||
type: entity
|
type: entity
|
||||||
id:
|
id:
|
||||||
id:
|
id:
|
||||||
@ -348,15 +318,12 @@ using database sequences or auto incrementing numbers.
|
|||||||
generator:
|
generator:
|
||||||
strategy: AUTO
|
strategy: AUTO
|
||||||
fields:
|
fields:
|
||||||
name:
|
# fields here
|
||||||
length: 50
|
|
||||||
|
|
||||||
This tells Doctrine to automatically generate a value for the
|
In most cases using the automatic generator strategy (``@GeneratedValue``) is
|
||||||
identifier. How this value is generated is specified by the
|
what you want. It defaults to the identifier generation mechanism your current
|
||||||
``strategy`` attribute, which is optional and defaults to 'AUTO'. A
|
database vendor prefers: AUTO_INCREMENT with MySQL, SERIAL with PostgreSQL,
|
||||||
value of ``AUTO`` tells Doctrine to use the generation strategy
|
Sequences with Oracle and so on.
|
||||||
that is preferred by the currently used database platform. See
|
|
||||||
below for details.
|
|
||||||
|
|
||||||
Identifier Generation Strategies
|
Identifier Generation Strategies
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -524,112 +491,3 @@ You can use it with the following code:
|
|||||||
use Doctrine\ORM\Mapping\AnsiQuoteStrategy;
|
use Doctrine\ORM\Mapping\AnsiQuoteStrategy;
|
||||||
|
|
||||||
$configuration->setQuoteStrategy(new AnsiQuoteStrategy());
|
$configuration->setQuoteStrategy(new AnsiQuoteStrategy());
|
||||||
|
|
||||||
Custom Mapping Types
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Doctrine allows you to create new mapping types. This can come in
|
|
||||||
handy when you're missing a specific mapping type or when you want
|
|
||||||
to replace the existing implementation of a mapping type.
|
|
||||||
|
|
||||||
In order to create a new mapping type you need to subclass
|
|
||||||
``Doctrine\DBAL\Types\Type`` and implement/override the methods as
|
|
||||||
you wish. Here is an example skeleton of such a custom type class:
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
namespace My\Project\Types;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Types\Type;
|
|
||||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* My custom datatype.
|
|
||||||
*/
|
|
||||||
class MyType extends Type
|
|
||||||
{
|
|
||||||
const MYTYPE = 'mytype'; // modify to match your type name
|
|
||||||
|
|
||||||
public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
|
|
||||||
{
|
|
||||||
// return the SQL used to create your column type. To create a portable column type, use the $platform.
|
|
||||||
}
|
|
||||||
|
|
||||||
public function convertToPHPValue($value, AbstractPlatform $platform)
|
|
||||||
{
|
|
||||||
// This is executed when the value is read from the database. Make your conversions here, optionally using the $platform.
|
|
||||||
}
|
|
||||||
|
|
||||||
public function convertToDatabaseValue($value, AbstractPlatform $platform)
|
|
||||||
{
|
|
||||||
// This is executed when the value is written to the database. Make your conversions here, optionally using the $platform.
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getName()
|
|
||||||
{
|
|
||||||
return self::MYTYPE; // modify to match your constant name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
The following assumptions are applied to mapping types by the ORM:
|
|
||||||
|
|
||||||
- If the value of the field is *NULL* the method
|
|
||||||
``convertToDatabaseValue()`` is not called.
|
|
||||||
- The ``UnitOfWork`` never passes values to the database convert
|
|
||||||
method that did not change in the request.
|
|
||||||
|
|
||||||
When you have implemented the type you still need to let Doctrine
|
|
||||||
know about it. This can be achieved through the
|
|
||||||
``Doctrine\DBAL\Types\Type#addType($name, $className)``
|
|
||||||
method. See the following example:
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
// in bootstrapping code
|
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Types\Type;
|
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
// Register my type
|
|
||||||
Type::addType('mytype', 'My\Project\Types\MyType');
|
|
||||||
|
|
||||||
To convert the underlying database type of your
|
|
||||||
new "mytype" directly into an instance of ``MyType`` when performing
|
|
||||||
schema operations, the type has to be registered with the database
|
|
||||||
platform as well:
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$conn = $em->getConnection();
|
|
||||||
$conn->getDatabasePlatform()->registerDoctrineTypeMapping('db_mytype', 'mytype');
|
|
||||||
|
|
||||||
When registering the custom types in the configuration you specify a unique
|
|
||||||
name for the mapping type and map that to the corresponding fully qualified
|
|
||||||
class name. Now the new type can be used when mapping columns:
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
class MyPersistentClass
|
|
||||||
{
|
|
||||||
/** @Column(type="mytype") */
|
|
||||||
private $field;
|
|
||||||
}
|
|
||||||
|
|
||||||
Custom ColumnDefinition
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
You can define a custom definition for each column using the "columnDefinition"
|
|
||||||
attribute of ``@Column``. You have to define all the definitions that follow
|
|
||||||
the name of a column here.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
Using columnDefinition will break change-detection in SchemaTool.
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user