0
votes

my problem with the doctrine 2 orm schema tool is, that it drops a column (foreign key) which is defined in a parent class.

i have the following scenario:

namespace mycode\folderA;

class User {
    /**
    * @ManyToOne(targetEntity="Role", inversedBy="users")
    * @JoinColumn(name="role_id", referencedColumnName="id")
    * @var Role
    */
    protected $role;

    //getter and setter
}

running doctrine orm:schema-tool:update --dump-sql works pretty got, it creates a table with all defined column and sets the $role as foreign key with index. all good.

now i am trying to add some special fields for one special case so i inherit from my User class. the code look like:

namespace mycode\folderB;

use mycode\folderA\User as UserParent;

class User extends UserParent {
    /**
    * @Column(name="special", type="integer", nullable=true)
    * @var integer
    */
    protected $special;

    //getter and setter
}

when i now run doctrine orm:schema-tool:update --dump-sql it shows my the adding of column "special" but ALSO the following:

DROP INDEX role ON user;
ALTER TABLE user DROP role_id;

i already tried to define the foreign key in the child user class as well, but without success.

so, my question is: what am i missing/what did i missunderstood?

thanks for your help!

1

1 Answers

0
votes

So, I finally found a solution.

First of all, I had to update the class annotation in the parent class to the following:

/**
 * @Table(name="user")
 * @InheritanceType("SINGLE_TABLE")
 * @DiscriminatorMap({
 * "user" = "\mycode\folderB\User"
 * }) 
 */
class User

Then, I needed to tell my cli-config.php every Entity to generate the schema from. this is some annoing part to me, but at the end, the result counts. and it works as expected. the structure of my cli-config.php looks something similar to this:

$loader = new Classloader(APP_ROOT."src/");
$loader->register();

$classLoader = new \Doctrine\Common\ClassLoader('path/to/mycode', APP_ROOT);
$classLoader->register();

$classLoader = new \Doctrine\Common\ClassLoader('DoctrineProxies', APP_ROOT);
$classLoader->register();

$config = new \Doctrine\ORM\Configuration();
$driverImpl = $config->newDefaultAnnotationDriver(array(
    APP_ROOT.'src/path/to/mycode'
));
$config->setMetadataDriverImpl($driverImpl);
$config->setQueryCacheImpl(new \Doctrine\Common\Cache\ApcCache());
$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ApcCache());
$config->setProxyDir(APP_ROOT.'src/path/to/Proxy');
$config->setProxyNamespace('DoctrineProxies');

$connectionOptions = array(
    'driver' => 'pdo_mysql',
    'dbname' => $dbname,
    'user' => $dbuser,
    'password' => $dbpass,
    'host' => $dbhost,
    'charset' => "UTF8"
);

$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);

$helperSet = new \Symfony\Component\Console\Helper\HelperSet(array(
    'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
    'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)
));

//here begins the solution :)

$tool = new \Doctrine\ORM\Tools\SchemaTool($em);
$classes = array(
    $em->getClassMetadata('mycode\folderA\User'),
    $em->getClassMetadata('mycode\folderB\User')
);
$tool->updateSchema($classes);

well, that's it. it's kinda expensive but it creates resprectively updates the tables as defined in the entities.

if you have a similar problem, and my entity code is too abstract to transfer to your code, write me :)