Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Propel Generator: for getManyToManyTables use real ManyToMany, fixes #88, #90

Merged
merged 2 commits into from

5 participants

@jaugustin
Collaborator

Propel Generator: for getManyToManyTables use real ManyToMany, fixes #88,

Now the generator us the Many To Many relation to generate form with list of related object

You need to set isCrossRef to true for this to work.

it could continue to fail in special case:

where 2 tables have a many to many relation with one table and another table in relation.
This could be fixed when this propel PR is accepted:

propelorm/Propel#146

@jaugustin
Collaborator

This PR will force user to have a isCrossRef attribute to identify Many-To-Many relations.

Some plugins will have to be updated for example sfGuardPlugin which doesn't use isCrossRef

@willdurand
Owner

Is it your last PR ? Could you provide unit tests?

@jaugustin
Collaborator

I will try to write unit Test for that.

It's missing one thing (to test the isCrossRef) but this will force to use Propel master to work, so I don't know if I make the fix in that PR or wait until propel 1.6.4 is released.

@willdurand
Owner

@jaugustin Where are your unit tests? :)

@jaugustin
Collaborator

@willdurand the unit tests are not written yet ;)

but this PR still need to have propel 1.6.4 ;)

@willdurand
Owner

@jaugustin Propel 1.6.4 should be released soon, tic tac ;)

@jaugustin
Collaborator

release it ;) and I will write tests :)

@willdurand
Owner

@jaugustin Propel 1.6.4 is out :)

@willdurand
Owner

@jaugustin are you alive? :p

I would like to merge your fix ;)

@jaugustin
Collaborator

I will do it soon ;)

@willdurand
Owner

@jaugustin any news?

@jaugustin
Collaborator

nop :( I really should look at it and wrote tests

@willdurand
Owner

I hope you'll do that these days Jérémie :)

@jaugustin
Collaborator

I look at the PR and how to write tests for that but it seems not easy to write tests for this plugin and also tests script do not work on windows :D,

I will give a try soon ;)

@jaugustin
Collaborator

Tests written and pass
Build Status

@willdurand willdurand merged commit cc91e66 into propelorm:master
@willdurand
Owner

Awesome, thanks!

@jaugustin
Collaborator

maybe we need to put some doc about the isCrossref impact because it's a little BC break ;)

form will only generate m2m list if isCrossref is true.

@bdujon

this break nearly all my apps i did with propel for the last 4 years.
and putting isCrossRef for all many to many relation is quite bad for me since the function created by this behavior can conflict with other function created by other relation with the same name...!

@yellottyellott

Please put this in the docs. This totally does break sfGuard.

@jaugustin
Collaborator

this is normaly fixed in the last version
look at PR #136

@hd-deman hd-deman referenced this pull request from a commit in hd-deman/sfPropelORMPlugin
@shane-l shane-l Fix #90 PropelOnDemandFormatter formatter broken when using single ta…
…ble inheritance
1acaf0c
@hd-deman hd-deman referenced this pull request from a commit in hd-deman/sfPropelORMPlugin
@willdurand willdurand Merged PR #177.
Fixes #90
6984ed0
@rozwell
Collaborator

Take a look at #139

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
57 lib/generator/sfPropelFormGenerator.class.php
@@ -124,35 +124,48 @@ public function generate($params = array())
public function getManyToManyTables()
{
$tables = array();
+ $foreignTables = array();
+ $relations = array();
- // go through all tables to find m2m relationships
- foreach ($this->dbMap->getTables() as $tableName => $table)
+ // go through all relations
+ foreach ($this->table->getRelations() as $relation)
+ {
+ //we have a many to many Relation
+ if (RelationMap::MANY_TO_MANY === $relation->getType())
+ {
+ $foreignTables[$relation->getLocalTable()->getClassname()] = $relation->getLocalTable();
+ }
+ else if (RelationMap::ONE_TO_MANY === $relation->getType())
+ {
+ $relations[$relation->getLocalTable()->getClassname()] = $relation;
+ }
+ }
+
+ // find middleTable for Many to Many relation
+ foreach ($foreignTables as $tableName => $foreignTable)
{
- foreach ($table->getColumns() as $column)
+ foreach ($foreignTable->getRelations() as $foreignRelation)
{
- if ($column->isForeignKey() && $column->isPrimaryKey() && $this->table->getClassname() == $this->getForeignTable($column)->getClassname())
+ $foreignTableName = $foreignRelation->getLocalTable()->getClassname();
+
+ // Test if the foreign table has a common relation with our table
+ // TODO: test if is CrossRef
+ if (RelationMap::ONE_TO_MANY === $foreignRelation->getType()
+ && array_key_exists($foreignTableName, $relations))
{
- // we have a m2m relationship
- // find the other primary key
- foreach ($table->getColumns() as $relatedColumn)
- {
- if ($relatedColumn->isForeignKey() && $relatedColumn->isPrimaryKey() && $this->table->getClassname() != $this->getForeignTable($relatedColumn)->getClassname())
- {
- // we have the related table
- $tables[] = array(
- 'middleTable' => $table,
- 'relatedTable' => $this->getForeignTable($relatedColumn),
- 'column' => $column,
- 'relatedColumn' => $relatedColumn,
- );
-
- break 2;
- }
- }
+ $columns = $relations[$foreignTableName]->getLocalColumns();
+ $relatedColumns = $foreignRelation->getLocalColumns();
+
+ $tables[] = array(
+ 'middleTable' => $foreignRelation->getLocalTable(),
+ 'relatedTable' => $foreignTable,
+ 'column' => reset($columns),
+ 'relatedColumn' => reset($relatedColumns),
+ );
+ continue 2;
}
}
}
-
return $tables;
}
View
58 lib/generator/sfPropelGenerator.class.php
@@ -66,38 +66,48 @@ public function getTableMap()
public function getManyToManyTables()
{
$tables = array();
+ $foreignTables = array();
+ $relations = array();
- // go through all tables to find m2m relationships
- foreach ($this->dbMap->getTables() as $tableName => $table)
+ // go through all relations
+ foreach ($this->getTableMap()->getRelations() as $relation)
{
- // load this table's relations and related tables
- $table->getRelations();
+ //we have a many to many Relation
+ if (RelationMap::MANY_TO_MANY === $relation->getType())
+ {
+ $foreignTables[$relation->getLocalTable()->getClassname()] = $relation->getLocalTable();
+ }
+ else if (RelationMap::ONE_TO_MANY === $relation->getType())
+ {
+ $relations[$relation->getLocalTable()->getClassname()] = $relation;
+ }
+ }
- foreach ($table->getColumns() as $column)
+ // find middleTable for Many to Many relation
+ foreach ($foreignTables as $tableName => $foreignTable)
+ {
+ foreach ($foreignTable->getRelations() as $foreignRelation)
{
- if ($column->isForeignKey() && $column->isPrimaryKey() && $this->getTableMap()->getClassname() == $this->dbMap->getTable($column->getRelatedTableName())->getClassname())
+ $foreignTableName = $foreignRelation->getLocalTable()->getClassname();
+
+ // Test if the foreign table has a common relation with our table
+ // TODO: test if is CrossRef
+ if (RelationMap::ONE_TO_MANY === $foreignRelation->getType()
+ && array_key_exists($foreignTableName, $relations))
{
- // we have a m2m relationship
- // find the other primary key
- foreach ($table->getColumns() as $relatedColumn)
- {
- if ($relatedColumn->isForeignKey() && $relatedColumn->isPrimaryKey() && $this->getTableMap()->getClassname() != $this->dbMap->getTable($relatedColumn->getRelatedTableName())->getClassname())
- {
- // we have the related table
- $tables[] = array(
- 'middleTable' => $table,
- 'relatedTable' => $this->dbMap->getTable($relatedColumn->getRelatedTableName()),
- 'column' => $column,
- 'relatedColumn' => $relatedColumn,
- );
-
- break 2;
- }
- }
+ $columns = $relations[$foreignTableName]->getLocalColumns();
+ $relatedColumns = $foreignRelation->getLocalColumns();
+
+ $tables[] = array(
+ 'middleTable' => $foreignRelation->getLocalTable(),
+ 'relatedTable' => $foreignTable,
+ 'column' => reset($columns),
+ 'relatedColumn' => reset($relatedColumns),
+ );
+ continue 2;
}
}
}
-
return $tables;
}
View
19 test/functional/fixtures/config/schema.xml
@@ -46,7 +46,7 @@
<column name="hobbies" type="array" required="false" />
</table>
- <table name="author_article">
+ <table name="author_article" isCrossref="true">
<behavior name="symfony">
<parameter name="form" value="false"/>
<parameter name="filter" value="false"/>
@@ -150,4 +150,21 @@
<column name="id" type="integer" required="true" primaryKey="true" autoincrement="true" />
<column name="enum_values" type="enum" valueSet="one, two, three space" />
</table>
+
+ <!-- model and data for testing many to many -->
+ <table name="seller">
+ <column name="id" type="integer" required="true" primaryKey="true" autoincrement="true" />
+ <column name="name" type="varchar" size="255" />
+ </table>
+ <table name="sale">
+ <column name="seller_id" type="integer" primaryKey="true" />
+ <column name="book_id" type="integer" primaryKey="true" />
+ <column name="number" type="integer" />
+ <foreign-key foreignTable="seller">
+ <reference local="seller_id" foreign="id" />
+ </foreign-key>
+ <foreign-key foreignTable="book">
+ <reference local="book_id" foreign="id" />
+ </foreign-key>
+ </table>
</database>
View
17 test/functional/formTest.php
@@ -291,3 +291,20 @@
checkElement('select option[selected="selected"]', 'three space')->
end()
;
+
+//Checks that many-to-many relations are generated correctly
+$form = new SellerForm();
+try {
+ $form->getWidget('sale_list');
+ $b->test()->fail('The seller form shoud not has sale_list field because it is not a many to many relation');
+} catch (InvalidArgumentException $e) {
+ $b->test()->pass('The seller form shoud not has sale_list field because it is not a many to many relation');
+}
+
+$form = new BookForm();
+try {
+ $form->getWidget('sale_list');
+ $b->test()->fail('The book form shoud not has sale_list field because it is not a many to many relation');
+} catch (InvalidArgumentException $e) {
+ $b->test()->pass('The book form shoud not has sale_list field because it is not a many to many relation');
+}
Something went wrong with that request. Please try again.