mipapo mipapo - 3 months ago 21
PHP Question

Symfony Doctrine (Migration) with prefix

We need to have a table prefix name for our application. I wish we wouldn't need it, but users are users.
In the moment we have this TablePrefix Subscriber

class TablePrefixSubscriber implements \Doctrine\Common\EventSubscriber {
protected $prefix = '';
public function __construct($prefix = '') {
$this->prefix = (string) $prefix;
}
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) {
$classMetadata = $eventArgs->getClassMetadata();
if(strlen($this->prefix)) {
if(0 !== strpos($classMetadata->getTableName(), $this->prefix)) {
$classMetadata->setTableName($this->prefix . $classMetadata->getTableName());
}
}
foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY) {
if(!isset($classMetadata->associationMappings[$fieldName]['joinTable'])) { continue; }
$mappedTableName = $classMetadata->associationMappings[$fieldName]['joinTable']['name'];
if(0 !== strpos($mappedTableName, $this->prefix)) {
$classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix . $mappedTableName;
}
}
}
}
public function getSubscribedEvents() {
return array('loadClassMetadata');
}


Service configuration:

services:
app.event.doctrine.table_prefix_subscriber:
class: RYZ\Bundle\CoreBundle\EventListener\TablePrefixSubscriber
arguments: ['%database_prefix%']
tags:
- { name: doctrine.event_subscriber }


This works just fine if you have no migrations or not writing the queries manually (by using the query builder).

I have no idea how to add the prefix to a query in a doctrine migration.

It would be fine if I could access the prefix configuration variable
database_prefix
in the migration and just add it to every query.

Also I want access the variable in the Entity repository classes.

I would be happy if anyone could point me to the right direction.

Update: I heard of the Doctrine Naming Strategy, but I think that won't help me here? (http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/namingstrategy.html)

Answer

Okay I think I found the solution for the migration: Keyword: ContainerAwareInterface

You can implement the ContainerAwareInterface to your migration class and just access all parameters and services you have implemented. Great thing!

Here is an example:

<?php

namespace FooBla\Migrations;

use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

class Version20160810121166 extends AbstractMigration implements ContainerAwareInterface
{
    private $container;

public function setContainer(ContainerInterface $container = null)
{
    $this->container = $container;
}

/**
 * @param Schema $schema
 */
public function up(Schema $schema)
{
    $em = $this->container->getParameter('database_prefix'); //Just use the parameter directly in the migration calls
    $this->addSql('CREATE TABLE `'.$em.'sessions` (`sess_id` VARBINARY(128) NOT NULL PRIMARY KEY, `sess_data` BLOB NOT NULL, `sess_time` INTEGER UNSIGNED NOT NULL, `sess_lifetime` MEDIUMINT NOT NULL) COLLATE utf8_bin, ENGINE = InnoDB');
}

/**
 * @param Schema $schema
 */
public function down(Schema $schema)
{
}
}
Comments