Commit 56911217 authored by Benjamin Eberlei's avatar Benjamin Eberlei

Add a chapter on Doctrine Types with example, extended Platforms chapter

parent 8622cb3f
......@@ -5,6 +5,7 @@
+ Data Retrieval and Manipulation
+ Transactions
+ Platforms
+ Types
+ Schema Manager
+ Schema Representation
+ Supporting Other Databases
\ No newline at end of file
Platforms abstract query generation and specifics of the RDBMS feature sets. In most cases you don't need to interact with this package a lot, but there might be certain cases when you are programming database independent where you want to access the platform to generate queries for you.
Platforms abstract query generation and the subtle differences of the supported database vendors. In most cases you don't need to interact
with the `Doctrine\DBAL\Platforms` package a lot, but there might be certain cases when you are programming database
independent where you want to access the platform to generate queries for you.
The platform can be accessed from any `Doctrine\DBAL\Connection` instance by calling the `getDatabasePlatform()` method.
[php]
$platform = $conn->getDatabasePlatform();
When creating a connection you can specify a `platform` key to pass the platform
you want the connection to use:
Each database driver has a platform associated with it by default. Several drivers also share the same platform,
for example PDO_OCI and OCI8 share the `OraclePlatform`.
If you want to overwrite parts of your platform you can do so when creating a connection.
There is a `platform` option you can pass an instance of the platform you want the connection to use:
[php]
$myPlatform = new MyPlatform();
......@@ -17,4 +22,11 @@ you want the connection to use:
);
$conn = DriverManager::getConnection($options);
This way you can optimize your schema or generated SQL code with features that might not be portable for instance, however are required for your special needs.
\ No newline at end of file
This way you can optimize your schema or generated SQL code with features that might not be portable for instance, however
are required for your special needs. This can include using triggers or views to simulate features or adding behaviour
to existing SQL functions.
Platforms are also responsible to know which database type translates to which PHP Type. This is a very tricky issue
across all the different database vendors, for example MySQL BIGINT and Oracle NUMBER should be handled as integer.
Doctrine 2 offers a powerful way to abstract the database to php and back conversion, which is described in the
next section.
\ No newline at end of file
Besides abstraction of SQL one needs a translation between database and PHP data-types to implement database independent applications.
Doctrine 2 has a type translation system baked in that supports the conversion from and to PHP values from any
database platform, aswell as platform independent SQL generation for any Doctrine Type.
Using the ORM you generally don't need to know about the Type system. This is unless you wan't to make use of database
vendor specific database types not included in Doctrine 2. The following PHP Types are abstracted across all
the supported database vendors:
* Integer
* SmallInt
* BigInt
* String (string with maximum length, for example 255)
* Text (strings without maximum length)
* Decimal (restricted floats)
* Boolean
* DateTime
* Date (DateTime instance where only Y-m-d get persisted)
* Time (DateTime instance where only H:i:s get persisted)
* Array (serialized into a text field for all vendors by default)
* Object (serialized into a text field for all vendors by default)
Types are flyweights. This means there is only ever one instance of a type and it is not allowed to contain any state.
Creation of type instances is abstracted through a static get method `Doctrine\DBAL\Types\Type::getType()`.
++ Schema Detection of Database Types
When calling table inspection methods on your connections `SchemaManager` instance
the retrieved database column types are translated into Doctrine mapping types.
Translation is necessary to allow database abstraction and metadata comparisons
for example for Migrations or the ORM SchemaTool.
Each database platform has a default mapping of database types to Doctrine types. You can inspect this mapping
for platform of your choice looking at the `AbstractPlatform::initializeDoctrineTypeMappings()`
implementation.
If you want to change how Doctrine maps a database type to a `Doctrine\DBAL\Types\Type` instance
you can use the `AbstractPlatform::registerDoctrineTypeMapping($dbType, $doctrineType)` method to
add new database types or overwrite existing ones.
> **NOTE**
>
> You can only map a database type to exactly one Doctrine type. Database vendors that allow
> to define custom types like PostgreSql can help to overcome this issue.
++ Custom Mapping Types
Just redefining how database types are mapped to all the existing Doctrine types is not at all that useful.
You can define your own Doctrine Mapping Types by extending `Doctrine\DBAL\Types\Type`. You are required
to implement 4 different methods to get this working.
See this example of how to implement a Money object in PostgreSQL. For this we create the type in PostgreSQL as:
[sql]
CREATE DOMAIN MyMoney AS DECIMAL(18,3);
Now we implement our `Doctrine\DBAL\Types\Type` instance:
[php]
namespace My\Project\Types;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* My custom datatype.
*/
class MoneyType extends Type
{
const MONEY = 'money'; // modify to match your type name
public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return 'MyMoney';
}
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return new Money($value);
}
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
return $value->toDecimal();
}
public function getName()
{
return self::MONEY;
}
}
Now we have to register this type with the Doctrine Type system and hook it into the database platform:
[php]
Type::addType('money', 'My\Project\Types\MoneyType');
$conn->getDatabasePlatform()->registerDoctrineTypeMapping('MyMoney', 'money');
This would allow to use a money type in the ORM for example and have Doctrine automatically convert
it back and forth to the database.
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment