1
votes

Sorry about the title - I really don't know how to call this - here is the story:

I have integrated doctrine/orm into Joomla3 as a library and I have created a component based on entities and repositories. It is really neat! I have actually created an J! installable library called JDoctrine which has a single entry point for obtaining the EntityManager. Something like:

require_once JPATH_ROOT."/libraries/jdoctrine/jdoctrine.php";
$JDO = new \stdClass();
$JDO->configuration = new \stdClass();
$JDO->configuration->type = "annotation";
$JDO->configuration->paths = [JPATH_ROOT."/administrator/components/com_something/Core/Entity"];
$JDO->configuration->isDevMode = false;
$JDO->connection = null;
$JDO->eventManager = null;
$em = \JDoctrine::getEntityManager($JDO);

It picks up Joomla's db configuration and table prefix and you can work with entities.

I'd like to distribute this library - maybe someone else finds it useful - but there is one thing I cannot figure out.

If I do this (which is what i want to have in my component install script):

$schemaTool = new SchemaTool($em);
$sqlArray = $schemaTool->getUpdateSchemaSql($classes, false);

I end up with an array of sql statements which will create/update all entities passed in $classes and DROP ALL OTHER TABLES.

For now, for my component for home-use, i fixed this with some really ugly cleanup method keeping only statements having table names that are associated with my entities.

What I'd like to do is to "instruct" doctrine to ignore all tables it does not know of - that is - skip everything there is no entity associated with. Any ideas?

2
Did I ask a stupid question?jakabadambalazs
it's not stupid at all, i would be happy to find a easy way to exclude unmapped tables from drop list.Constantin

2 Answers

0
votes

Jakabadambalazs I am also used Jdoctrine.I am new to this.I just installed it via joomla install.Now where can i place the above code.If you have any example please specify the paths.

0
votes

It is really quite straight forward and the answer is 'obviously' already there since Doctrine already does this. It was only a matter of finding the peaces.

Generally: You need to create 2 schemas(Doctrine\DBAL\Schema\Schema) and compare them with the Comparator(Doctrine\DBAL\Schema\Comparator) which will give you the difference(\Doctrine\DBAL\Schema\SchemaDiff). Then on ShemaDiff you can call: toSaveSql

The Schema class has a list of tables. So when you have $fromSchema and $toSchema and you compare them:

  • tables listed in $fromSchema but missing in $toSchema will be DROPed
  • tables missing in $fromSchema but listed in $toSchema will be CREATEd
  • tables listed in $fromSchema and listed in $toSchema will be ALTERed
  • tables missing in $fromSchema and missing in $toSchema will be ...IGNOREd ;-)

So, you'd do something like:

/** @var EntityManager $em */
$classes = $this->getArrayOfClassMetadataAboutYourEntities();
$em = $this->getAnEntityManagerFromSomewhere();
$sm = $em->getConnection()->getSchemaManager();
$st = new SchemaTool($em);

//FROM Schema
$tables = [];
foreach($classes as $class) {
  if(isset($class->table)&&isset($class->table["name"])) {
    $tables[] = $sm->listTableDetails($class->table["name"]);
  }
}
$sequences = ($sm->getDatabasePlatform()->supportsSequences()?$sm->listSequences():[]);
$fromSchema = new Schema($tables, $sequences, $sm->createSchemaConfig());

//TO SCHEMA - $classes is an array of ClassMetadata representing the entities
$toSchema = $st->getSchemaFromMetadata($classes);

//COMPARE
$comparator = new Comparator();
$schemaDiff = $comparator->compare($fromSchema, $toSchema);

//DO SOMETHING
$sqlStatements = $schemaDiff->toSaveSql($sm->getDatabasePlatform());
foreach($sqlStatements as $sql) {
    $em->getConnection()->exec($sql);
}

PS: I am writting this code on SO, beware of typos!