How to customize the Doctrine library to work with the Timestamp type

Asked

Viewed 93 times

-1

I’m using Composer with Doctrine in my application, and it’s getting wonderful. But I need to customize some Doctrine features, changing the classes Doctrine\DBAL\Platforms\AbstractPlatform and Doctrine\DBAL\Platforms\MySqlPlatform.

For this I created the classes MY_AbstractPlatform and MY_MySqlPlatform and extended the respective superclasses. So I added them to my autoload, but nothing happened.

When I write the code directly in the Doctrine classes the customization is performed, but when I implement the respective methods in the subclasses nothing happens.

I need to customize the Doctrine library, but how to do this?

  • First of all, it would be possible to talk about the reason for customization, so that the community can discuss whether it would really be necessary? :)

  • Hello Rodrigo Rigotti, I updated the question, inserting the solution I found this morning. The customization I wanted was to work with timestamp fields, because I already have a database in production that cannot be modified, and it makes use of this type constantly.

1 answer

0


I was able to do the customization modularized. That is, I was able to create the Doctrine subclasses in my application and use them from the connection configuration, defining the property driverClass connection array, instantiating my driver class MY_Driver.

Here’s how I set up the Doctrine connection, watch out for the 'driverClass' property':

$connection_options = array(
            'driver' => 'pdo_mysql',
            'user' => $db['default']['username'],
            'password' => $db['default']['password'],
            'host' => $db['default']['hostname'],
            'dbname' => $db['default']['database'],
            'charset' => $db['default']['char_set'],
            'driverOptions' => array(
                'charset' => $db['default']['char_set'],
            ),
            'driverClass' => new MY_Driver()
        );

How my goal was to allow Doctrine to work in fields timetamp, I created a class to represent my application Driver, inheriting the native Doctrine Driver class. My subclass declares another subclass MY_MySqlPlatform containing the customizations for the Mysql platform to apply the timestamp.

class MY_Driver extends Doctrine\DBAL\Driver\Mysqli\Driver {

    /**
     * Define a classe personalizada para o driver da plataforma MySql
     * 
     * {@inheritdoc}
     */
    public function getDatabasePlatform() {

        return new MY_MySqlPlatform();
    }

}

The class MY_MySqlPlatform inherits the classMySqlPlatform native to Doctrine, but applying timestamp methods.

class MY_MySqlPlatform extends Doctrine\DBAL\Platforms\MySqlPlatform {

    /**
     * {@inheritDoc}
     */
    public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) {
        if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) {
            return 'TIMESTAMP';
        }

        return 'TIMESTAMP';
    }

    /**
     * {@inheritDoc}
     */
    public function getTimestampTypeDeclarationSQL(array $fieldDeclaration) {
        return 'TIMESTAMP';
    }

    /**
     * {@inheritDoc}
     */
    protected function initializeDoctrineTypeMappings() {
        $this->doctrineTypeMapping = array(
            'tinyint' => 'boolean',
            'smallint' => 'smallint',
            'mediumint' => 'integer',
            'int' => 'integer',
            'integer' => 'integer',
            'bigint' => 'bigint',
            'tinytext' => 'text',
            'mediumtext' => 'text',
            'longtext' => 'text',
            'text' => 'text',
            'varchar' => 'string',
            'string' => 'string',
            'char' => 'string',
            'date' => 'date',
            'datetime' => 'datetime',
            'timestamp' => 'timestamp',
            'time' => 'time',
            'float' => 'float',
            'double' => 'float',
            'real' => 'float',
            'decimal' => 'decimal',
            'numeric' => 'decimal',
            'year' => 'date',
            'longblob' => 'blob',
            'blob' => 'blob',
            'mediumblob' => 'blob',
            'tinyblob' => 'blob',
            'binary' => 'blob',
            'varbinary' => 'blob',
            'set' => 'simple_array',
        );
    }

}

And finally I created the class TimestampType in my project, inheriting the class Type Doctrine native, to represent a Tymestamp type attribute during mapping.

namespace Doctrine\DBAL\Types;

use Doctrine\DBAL\Platforms\AbstractPlatform;

class TimestampType extends Type {

    const TIMESTAMP = 'timestamp';

    /**
     * {@inheritdoc}
     */
    public function getName() {
        return self::TIMESTAMP;
    }

    /**
     * {@inheritdoc}
     */
    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) {

        return $platform->getTimestampTypeDeclarationSQL($fieldDeclaration);
    }

    /**
     * {@inheritdoc}
     */
    public function convertToDatabaseValue($value, AbstractPlatform $platform) {
        return ($value !== null) ? $value->format($platform->getTimestampTypeDeclarationSQL()) : null;
    }

    /**
     * {@inheritdoc}
     */
    public function convertToPHPValue($value, AbstractPlatform $platform) {
        if ($value === null || $value instanceof \DateTime) {
            return $value;
        }

        $val = \DateTime::createFromFormat($platform->getDateTimeFormatString(), $value);
        if (!$val) {
            throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateTimeFormatString());
        }

        return $val;
    }

}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.