#6245: HABTM primaryKey identified in one direction only, bad DELETE queries ---------------------------------+------------------------------------------ Reporter: cuppett | Owner: Type: Test Case | Status: reopened Priority: High | Milestone: 1.2.x.x Component: General | Version: 1.2 Final Severity: Major | Resolution: Keywords: HABTM primaryKey | Php_version: PHP 5 Cake_version: 1.2.2.8120 | ---------------------------------+------------------------------------------ Comment (by cuppett):
Currently:[[BR]] [[BR]] CakePHP 1.2.3[[BR]] PHP 5.2.9[[BR]] Postgres 8.3.7[[BR]] WinXP[[BR]] Apache 2.2.x[[BR]] [[BR]] I have a tentative fix for this; however, I'm having lots of trouble trying to get the test suite installed and running. Can somebody take this patch and run it through? I'm getting good queries in my environment now for HABTM in both directions within the same controller. [[BR]] [[BR]] The problem was that if you were using both Models in your uses() and potentially executing HABTM updates from either side in the same Controller, you would get one designation of the column to be used for the preceeding DELETE queries in a ->save(). Taking mostly defaults for the HABTM relationship would first get a 'joinTable' calculation of abc order of the Model tables and then a 'with' calculation of a derivative of 'joinTable'. Later on, in __generateAssociation() it would set primaryKey to one of the two columns. Because this new dynamic class gets registered in the ClassRegistry, when the next model is loaded, it would pick up all the same stuff, including the $primaryKey designator. [[BR]][[BR]] My fix changes the code slightly to reduce an ordering dependency on __associationKeys wrt to the foreach loop and the calculation of 'joinTable' prior to 'with'. It also calculates the default value of 'with' for each side of the HABTM without ordering the tables. So in Posts, the name will be PostsTag and in Tags it will be TagsPost. This gets the deletes right no matter which is done and no matter what order they appear in the uses() array. Also, it has a minor optimization to to avoid multiple rows returned when getting the idList for the DELETE. [[BR]][[BR]] The patch is on TheChaw under Cuppett's Fork as 6a07...745e: [[BR]][[BR]] http://thechaw.com/forks/cuppett/cakephp/commits/view/6a07a5bc8b00235a19f59b5a43e004b39fd5745e [[BR]][[BR]] {{{ diff --git a/cake/libs/model/datasources/dbo_source.php b/cake/libs/model/datasources/dbo_source.php index f2aa64e..29c348e 100644 --- a/cake/libs/model/datasources/dbo_source.php +++ b/cake/libs/model/datasources/dbo_source.php @@ -1472,7 +1472,7 @@ class DboSource extends DataSource { $conditions = $this->conditions($this->defaultConditions($model, $conditions, false), true, true, $model); } else { $idList = $model->find('all', array( - 'fields' => "{$model->alias}.{$model->primaryKey}", + 'fields' => "DISTINCT {$model->alias}.{$model->primaryKey}", 'conditions' => $conditions )); @@ -2447,4 +2447,4 @@ class DboSource extends DataSource { return 'string'; } } -?> \ No newline at end of file +?> diff --git a/cake/libs/model/model.php b/cake/libs/model/model.php index ae19e51..d8662b1 100644 --- a/cake/libs/model/model.php +++ b/cake/libs/model/model.php @@ -674,7 +674,7 @@ class Model extends Overloadable { break; case 'with': - $data = Inflector::camelize(Inflector::singularize($this->{$type}[$assocKey]['joinTable'])); + $data = Inflector::camelize(Inflector::singularize($this->table . "_" . $this->{$class}->table)); $dynamicWith = true; break; @@ -2871,4 +2871,4 @@ class Model extends Overloadable { if (!defined('CAKEPHP_UNIT_TEST_EXECUTION')) { Overloadable::overload('Model'); } -?> \ No newline at end of file +?> }}} -- Ticket URL: <https://trac.cakephp.org/ticket/6245#comment:7> CakePHP : The Rapid Development Framework for PHP <https://trac.cakephp.org/> Cake is a rapid development framework for PHP which uses commonly known design patterns like ActiveRecord, Association Data Mapping, Front Controller and MVC. Our primary goal is to provide a structured framework that enables PHP users at all levels to rapidly develop robust web applications, without any loss to flexibility. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "tickets cakephp" group. To post to this group, send email to tickets-cakephp@googlegroups.com To unsubscribe from this group, send email to tickets-cakephp+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/tickets-cakephp?hl=en -~----------~----~----~----~------~----~------~--~---