[DataFixtures] Fixed N-N relations

This commit is contained in:
William DURAND 2012-05-05 20:53:14 +02:00
parent 35dbf79170
commit 2e7bb13431
8 changed files with 69 additions and 157 deletions

View file

@ -11,7 +11,6 @@
namespace Propel\PropelBundle\DataFixtures;
use \Propel;
use Symfony\Component\Finder\Finder;
/**
@ -65,7 +64,10 @@ abstract class AbstractDataHandler
if (0 === count($this->dbMap->getTables())) {
$finder = new Finder();
$files = $finder->files()->name('*TableMap.php')->in($this->getRootDir() . '/../')->exclude('Tests');
$files = $finder->files()->name('*TableMap.php')
->in($this->getRootDir() . '/../')
->exclude('PropelBundle')
->exclude('Tests');
foreach ($files as $file) {
$class = $this->guessFullClassName($file->getRelativePath(), basename($file, '.php'));

View file

@ -10,15 +10,14 @@
namespace Propel\PropelBundle\DataFixtures\Loader;
use \Propel;
use \BasePeer;
use \BaseObject;
use \ColumnMap;
use \Propel;
use \PropelException;
use Propel\PropelBundle\DataFixtures\AbstractDataHandler;
use Propel\PropelBundle\Util\PropelInflector;
use Symfony\Component\Finder\Finder;
/**
@ -156,17 +155,18 @@ abstract class AbstractDataLoader extends AbstractDataHandler implements DataLoa
}
foreach ($data as $name => $value) {
try {
if (is_array($value) && 's' === substr($name, -1)) {
if (is_array($value) && 's' === substr($name, -1)) {
try {
// many to many relationship
$this->loadManyToMany($obj, substr($name, 0, -1), $value);
continue;
}
} catch (\PropelException $e) {
// Check whether this is actually an array stored in the object.
if ('Cannot fetch TableMap for undefined table: '.substr($name, 0, -1) === $e->getMessage()) {
if ('ARRAY' !== $tableMap->getColumn($name)->getType()) {
throw $e;
} catch (PropelException $e) {
// Check whether this is actually an array stored in the object.
if ('Cannot fetch TableMap for undefined table: '.substr($name, 0, -1) === $e->getMessage()) {
if ('ARRAY' !== $tableMap->getColumn($name)->getType()) {
throw $e;
}
}
}
}
@ -206,8 +206,7 @@ abstract class AbstractDataLoader extends AbstractDataHandler implements DataLoa
if (false !== $pos = array_search($name, $column_names)) {
$obj->setByPosition($pos, $value);
}
elseif (is_callable(array($obj, $method = 'set'.ucfirst(PropelInflector::camelize($name))))) {
} elseif (is_callable(array($obj, $method = 'set'.ucfirst(PropelInflector::camelize($name))))) {
$obj->$method($value);
} else {
throw new \InvalidArgumentException(sprintf('Column "%s" does not exist for class "%s".', $name, $class));
@ -234,12 +233,17 @@ abstract class AbstractDataLoader extends AbstractDataHandler implements DataLoa
protected function loadManyToMany($obj, $middleTableName, $values)
{
$middleTable = $this->dbMap->getTable($middleTableName);
$middleClass = $middleTable->getPhpName();
$middleClass = $middleTable->getClassname();
$tableName = constant(constant(get_class($obj).'::PEER').'::TABLE_NAME');
foreach ($middleTable->getColumns() as $column) {
if ($column->isForeignKey() && constant(constant(get_class($obj).'::PEER').'::TABLE_NAME') != $column->getRelatedTableName()) {
$relatedClass = $this->dbMap->getTable($column->getRelatedTableName())->getPhpName();
break;
if ($column->isForeignKey()) {
if ($tableName !== $column->getRelatedTableName()) {
$relatedClass = $this->dbMap->getTable($column->getRelatedTableName())->getClassname();
$relatedSetter = 'set' . $column->getRelation()->getName();
} else {
$setter = 'set' . $column->getRelation()->getName();
}
}
}
@ -247,9 +251,6 @@ abstract class AbstractDataLoader extends AbstractDataHandler implements DataLoa
throw new \InvalidArgumentException(sprintf('Unable to find the many-to-many relationship for object "%s".', get_class($obj)));
}
$setter = 'set'.get_class($obj);
$relatedSetter = 'set'.$relatedClass;
foreach ($values as $value) {
if (!isset($this->object_references[$relatedClass.'_'.$value])) {
throw new \InvalidArgumentException(

View file

@ -262,15 +262,26 @@ A valid _XML fixtures file_ is:
A valid _YAML fixtures file_ is:
``` yaml
\Awesome\Object:
Awesome\Object:
o1:
Title: My title
MyFoo: bar
\Awesome\Related:
Awesome\Related:
r1:
ObjectId: o1
Description: Hello world !
Awesome\Tag:
t1:
name: Foo
t2:
name: Baz
Awesome\Post:
p1:
title: A Post with tags (N-N relation)
tags: [ t1, t2 ]
```
You can load all fixtures files from a given _bundle_:

View file

@ -49,24 +49,24 @@ YAML;
{
$schema = <<<XML
<database name="default" package="vendor.bundles.Propel.PropelBundle.Tests.Fixtures.DataFixtures.Loader" namespace="Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader" defaultIdMethod="native">
<table name="book" phpName="YamlManyToManyBook">
<table name="table_book" phpName="YamlManyToManyBook">
<column name="id" type="integer" primaryKey="true" />
<column name="name" type="varchar" size="255" />
</table>
<table name="author" phpName="YamlManyToManyAuthor">
<table name="table_author" phpName="YamlManyToManyAuthor">
<column name="id" type="integer" primaryKey="true" />
<column name="name" type="varchar" size="255" />
</table>
<table name="book_author" phpName="YamlManyToManyBookAuthor">
<table name="table_book_author" phpName="YamlManyToManyBookAuthor" isCrossRef="true">
<column name="book_id" type="integer" required="true" primaryKey="true" />
<column name="author_id" type="integer" required="true" primaryKey="true" />
<foreign-key foreignTable="book" phpName="Book" onDelete="CASCADE" onUpdate="CASCADE">
<foreign-key foreignTable="table_book" phpName="Book" onDelete="CASCADE" onUpdate="CASCADE">
<reference local="book_id" foreign="id" />
</foreign-key>
<foreign-key foreignTable="author" phpName="Author" onDelete="CASCADE" onUpdate="CASCADE">
<foreign-key foreignTable="table_author" phpName="Author" onDelete="CASCADE" onUpdate="CASCADE">
<reference local="author_id" foreign="id" />
</foreign-key>
</table>
@ -74,17 +74,27 @@ YAML;
XML;
$fixtures = <<<YAML
Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyAuthor:
Author_1:
name: 'A famous one'
Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBook:
Book_1:
id: 1
name: 'An important one'
Book_2:
id: 2
name: 'Les misérables'
Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyAuthor:
Author_1:
id: 1
name: 'A famous one'
Author_2:
id: 2
name: 'Victor Hugo'
table_book_authors: [ Book_2 ]
Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBookAuthor:
BookAuthor_1:
book_id: Book_1
author_id: Author_1
YAML;
$filename = $this->getTempFile($fixtures);
@ -97,16 +107,23 @@ YAML;
$loader->load(array($filename), 'default');
$books = \Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBookPeer::doSelect(new \Criteria(), $con);
$this->assertCount(1, $books);
$this->assertCount(2, $books);
$this->assertInstanceOf('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBook', $books[0]);
$this->assertInstanceOf('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBook', $books[1]);
$authors = \Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyAuthorPeer::doSelect(new \Criteria(), $con);
$this->assertCount(1, $authors);
$this->assertCount(2, $authors);
$this->assertInstanceOf('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyAuthor', $authors[0]);
$this->assertInstanceOf('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyAuthor', $authors[1]);
$bookAuthors = \Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBookAuthorPeer::doSelect(new \Criteria(), $con);
$this->assertCount(1, $bookAuthors);
$this->assertCount(2, $bookAuthors);
$this->assertInstanceOf('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBookAuthor', $bookAuthors[0]);
$this->assertInstanceOf('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBookAuthor', $bookAuthors[1]);
$this->assertEquals('Victor Hugo', $authors[1]->getName());
$this->assertTrue($authors[1]->getBooks()->contains($books[1]));
$this->assertEquals('Les misérables', $authors[1]->getBooks()->get(0)->getName());
}
public function testLoadSelfReferencing()

View file

@ -56,9 +56,7 @@ XML;
$builder = new \PropelQuickBuilder();
$builder->setSchema($schema);
if (!class_exists('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\Book')) {
$builder->setClassTargets(array('peer', 'object', 'query', 'peerstub', 'objectstub', 'querystub'));
} else {
if (class_exists('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\Book')) {
$builder->setClassTargets(array());
}

View file

@ -1,58 +0,0 @@
<?php
namespace Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\map;
use \RelationMap;
use \TableMap;
/**
* This class defines the structure of the 'author' table.
*
*
*
* This map class is used by Propel to do runtime db structure discovery.
* For example, the createSelectSql() method checks the type of a given column used in an
* ORDER BY clause to know whether it needs to apply SQL to make the ORDER BY case-insensitive
* (i.e. if it's a text column type).
*
* @package propel.generator.vendor.bundles.Propel.PropelBundle.Tests.Fixtures.DataFixtures.Loader.map
*/
class BookAuthorTableMap extends TableMap
{
/**
* The (dot-path) name of this class
*/
const CLASS_NAME = 'vendor.bundles.Propel.PropelBundle.Tests.Fixtures.DataFixtures.Loader.map.BookAuthorTableMap';
/**
* Initialize the table attributes, columns and validators
* Relations are not initialized by this method since they are lazy loaded
*
* @return void
* @throws PropelException
*/
public function initialize()
{
// attributes
$this->setName('book_author');
$this->setPhpName('BookAuthor');
$this->setClassname('Propel\\PropelBundle\\Tests\\Fixtures\\DataFixtures\\Loader\\BookAuthor');
$this->setPackage('vendor.bundles.Propel.PropelBundle.Tests.Fixtures.DataFixtures.Loader');
$this->setUseIdGenerator(false);
// columns
$this->addPrimaryKey('ID', 'Id', 'INTEGER', true, null, null);
$this->addColumn('NAME', 'Name', 'VARCHAR', false, 255, null);
// validators
} // initialize()
/**
* Build the RelationMap objects for this table relationships
*/
public function buildRelations()
{
$this->addRelation('Book', 'Propel\\PropelBundle\\Tests\\Fixtures\\DataFixtures\\Loader\\Book', RelationMap::ONE_TO_MANY, array('id' => 'author_id', ), 'RESTRICT', 'CASCADE', 'Books');
} // buildRelations()
} // AuthorTableMap

View file

@ -1,59 +0,0 @@
<?php
namespace Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\map;
use \RelationMap;
use \TableMap;
/**
* This class defines the structure of the 'book' table.
*
*
*
* This map class is used by Propel to do runtime db structure discovery.
* For example, the createSelectSql() method checks the type of a given column used in an
* ORDER BY clause to know whether it needs to apply SQL to make the ORDER BY case-insensitive
* (i.e. if it's a text column type).
*
* @package propel.generator.vendor.bundles.Propel.PropelBundle.Tests.Fixtures.DataFixtures.Loader.map
*/
class BookTableMap extends TableMap
{
/**
* The (dot-path) name of this class
*/
const CLASS_NAME = 'vendor.bundles.Propel.PropelBundle.Tests.Fixtures.DataFixtures.Loader.map.BookTableMap';
/**
* Initialize the table attributes, columns and validators
* Relations are not initialized by this method since they are lazy loaded
*
* @return void
* @throws PropelException
*/
public function initialize()
{
// attributes
$this->setName('book');
$this->setPhpName('Book');
$this->setClassname('Propel\\PropelBundle\\Tests\\Fixtures\\DataFixtures\\Loader\\Book');
$this->setPackage('vendor.bundles.Propel.PropelBundle.Tests.Fixtures.DataFixtures.Loader');
$this->setUseIdGenerator(false);
// columns
$this->addPrimaryKey('ID', 'Id', 'INTEGER', true, null, null);
$this->addColumn('NAME', 'Name', 'VARCHAR', false, 255, null);
$this->addForeignKey('AUTHOR_ID', 'AuthorId', 'INTEGER', 'book_author', 'ID', true, null, null);
// validators
} // initialize()
/**
* Build the RelationMap objects for this table relationships
*/
public function buildRelations()
{
$this->addRelation('BookAuthor', 'Propel\\PropelBundle\\Tests\\Fixtures\\DataFixtures\\Loader\\BookAuthor', RelationMap::MANY_TO_ONE, array('author_id' => 'id', ), 'RESTRICT', 'CASCADE');
} // buildRelations()
} // BookTableMap

View file

@ -13,7 +13,7 @@
"propel/propel1": "1.6.*"
},
"require-dev": {
"sensio/framework-extra-bundle": "*"
"sensio/framework-extra-bundle": "dev-master"
},
"autoload": {
"psr-0": { "Propel\\PropelBundle": "" }