Question

I'm working on a Web application using the symfony framework. My database design is pre-existing is not vary 'classical' - That is, field types of 'hstore' and 'json' are in use.

So far, I'v encountered 2 problems:

  1. Doctrine does not support hstore or json field formats on PgSQL - I'v managed to change the sources of the vendor/doctrine of both the DBAL driver and the ORM to do this.
  2. Doctrine also HAS A BUG (used latest version of symfony) that was supposedly solved in earlier versions, the bug has to do with the translation of pg timestamp back to PHP timestamp, the time format does not include microseconds ('u') while the Pg does return it with a HH:mm:ss.uuuuuu (http://www.doctrine-project.org/jira/browse/DBAL-33)

Let's assume that I was able to fix these problems with source code changes to the packages.

The question here is composed out of different questions with alternatives I have in mind, any good answer to one of them would do, I guess.

  • How do I stay updated if the files are managed by the composer?
  • How can I deploy it onto another environment if I'v changed the source?
  • Are there alternative solutions/hakcs to fix the above problems without changing the 3rd party packages?
  • Is there a way I could deploy custom commit (don't mind forking the DoctorineBundle) in the composer?
  • Is there a good way to 'patch' the sources after vendor installation? (Maybe with a post-install script somehow)

I hope(but doubt it) I can remove the require for the corresponding package from the composer.json and keep the new vendor/ files along with my src/ but that's not the solution I'm looking for anyway.

Note I'm new to all of this kind of dependency and package import/management using the composer.

Was it helpful?

Solution

First of all, Doctrine is pretty extensible. There definitely should be a way of extending it with your bundle code without the need to modify anything in vendor/.

Doctrine's doc states that json type is already supported: http://doctrine-dbal.readthedocs.org/en/latest/reference/types.html#mapping-matrix. hstore is not, according to the doc, but if you can implement it, that's something worth merging into the Doctrine project.

The datetime issue is known, too: http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/known-vendor-issues.html#postgresql

On forking Composer-provided libraries: you can fork Doctrine on Github and add a repositories block into your composer.json, pointing to your fork:

{
...
"repositories": [
         {
             "type": "vcs",
             "url": "http://github.com/**your/fork**"
         } 
    ]
}

Update the Doctrine package with Composer (that should be php composer.phar update doctrine/orm, or doctrine/dbal, doctrine/common or maybe doctrine/doctrine-bundle if you're forking the bundle), and it should pull your fork code instead of the original Doctrine code. Watch the "name" value in composer.json of the library you're forking.

Here's a more verbose tutorial on forking: http://mnapoli.fr/overriding-dependencies-with-composer/

OTHER TIPS

After some research it's apperent that Doctrine on symfony (DoctrineBundle) could be extended to know custom types.

json DBAL type is in fact called json_array and not json (doono why), hstore and inet need to be implemented as new types (inet might not be needed, might be able to alias it to string).

We need to 2 BOTH of these next steps in order for everything to work properly (if you do only one of them, then either mapping import fails, or cache:clear fails).

  1. Register totally new types as Doctrine types

    # config.yaml
    doctrine:
            types:
                hstore:  vendor\MyBundle\Types\Hstore
                inet:  vendor\MyBundle\Types\Inet
    
  2. Turns out that bootstrap code is the boot() method of the bundle; We now need to tell the ORM to link the database to these classes, like so:

    class MyBundle extends Bundle
    {
        public function boot()
        {
    
            $em = $this->container->get('doctrine')->getEntityManager();
            $platform = $em->getConnection()->getDatabasePlatform();
    
            //for some reason, Doctrine DBAL calls a json type json_array, we rename it / alias it here.
            $platform->registerDoctrineTypeMapping('Json', 'json_array');
            $platform->registerDoctrineTypeMapping('Hstore', 'hstore');
            $platform->registerDoctrineTypeMapping('Inet', 'inet');
        }
    }
    

A mix of some trial&error + these 2 docs: http://symfony.com/doc/current/cookbook/doctrine/dbal.html#registering-custom-mapping-types http://doctrine-orm.readthedocs.org/en/latest/cookbook/custom-mapping-types.html

I'v yet to test the implementation of all of this, but at least now there aren't any exceptions on app/console. i'll update with the types sources once i'v sure my implementations are correct.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top