From 12b4c981cf8e14b86205e4d938df0e40eef2724d Mon Sep 17 00:00:00 2001 From: Alexandre Quercia Date: Sun, 16 Sep 2018 15:52:29 +0200 Subject: [PATCH 1/2] Add test for connection binding to component --- .travis.yml | 3 ++ composer.json | 3 ++ tests/BaseTestCase.php | 39 ++++++++++++++++++++++++ tests/autoloaded/ModelBindConnection.php | 11 +++++++ tests/bootstrap.php | 2 +- 5 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 tests/autoloaded/ModelBindConnection.php diff --git a/.travis.yml b/.travis.yml index bb6c4423d..af80f3572 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,5 +20,8 @@ matrix: - php: nightly - php: hhvm +before_script: + - composer install + script: - php -dshort_open_tag=Off -dmagic_quotes_gpc=Off tests/index.php diff --git a/composer.json b/composer.json index 440a405b9..de07bf918 100644 --- a/composer.json +++ b/composer.json @@ -15,5 +15,8 @@ }, "autoload": { "psr-0": { "Doctrine_": "lib/" } + }, + "autoload-dev": { + "psr-4": { "": "tests/autoloaded/" } } } diff --git a/tests/BaseTestCase.php b/tests/BaseTestCase.php index 6a6595cd4..a98248849 100644 --- a/tests/BaseTestCase.php +++ b/tests/BaseTestCase.php @@ -78,6 +78,45 @@ public function testAllModelsAvailable() $this->assertTrue( class_exists('BaseConservativeModelLoadingUser', true)); } + public function testCreateTableBindConnection() + { + Doctrine_Manager::getInstance()->openConnection('sqlite::memory:', 'test_bind_connection', false); + + $table = Doctrine_Core::getTable('ModelBindConnection'); + $this->assertEqual('test_bind_connection', $table->getConnection()->getName()); + } + + public function testCreateQueryBindConnection() + { + $manager = Doctrine_Manager::getInstance(); + $currentConnection = $manager->getCurrentConnection(); + $connection = $manager->openConnection('sqlite::memory:', 'test_bind_connection', false); + + $query = Doctrine_Core::getTable('ModelBindConnection')->createQuery(); + + $refl = new ReflectionProperty($query, '_passedConn'); + $refl->setAccessible(true); + $isPassedConn = $refl->getValue($query); + $refl->setAccessible(false); + + // Assert that the connedtion of the query is not passed. + $this->assertFalse($isPassedConn); + + $query->getSqlQuery(); + + // Assert that the current connection was not changed. + $this->assertTrue($currentConnection === $manager->getCurrentConnection()); + + // Assert that the model does not exists on the current connection. + $this->assertFalse($currentConnection->hasTable('ModelBindConnection')); + + // Assert that the model does not exists on the bound connection. + $this->assertTrue($connection->hasTable('ModelBindConnection')); + + // Assert that the connection of the query is the bound connection. + $this->assertEqual('test_bind_connection', $query->getConnection()->getName()); + } + public function testModelLoadingCacheInformation() { $models = Doctrine_Core::getLoadedModels(); diff --git a/tests/autoloaded/ModelBindConnection.php b/tests/autoloaded/ModelBindConnection.php new file mode 100644 index 000000000..496e710b3 --- /dev/null +++ b/tests/autoloaded/ModelBindConnection.php @@ -0,0 +1,11 @@ +bindComponent('ModelBindConnection', 'test_bind_connection'); + +class ModelBindConnection extends Doctrine_Record +{ + public function setTableDefinition() + { + $this->hasColumn('name', 'string', 1); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 2bb1704da..04096bb71 100755 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -12,7 +12,7 @@ define('DOCTRINE_DIR', $_SERVER['DOCTRINE_DIR']); -require_once(DOCTRINE_DIR . '/lib/Doctrine/Core.php'); +require_once DOCTRINE_DIR.'/vendor/autoload.php'; spl_autoload_register(array('Doctrine_Core', 'autoload')); spl_autoload_register(array('Doctrine_Core', 'modelsAutoload')); From e01214f36ee4374b2e6355f468805483ffbbae3f Mon Sep 17 00:00:00 2001 From: Alexandre Quercia Date: Sun, 16 Sep 2018 16:18:14 +0200 Subject: [PATCH 2/2] Fix connection binding to component for all autoloaded models Patch for more than one master connection. Modern and symfony1 applications do not use `Doctrine_Core::loadModels()` even conservative or aggressive mode. For such setup models that are bound to a specific connection are attached to the current connection instead of the bound one. After some deeper investigations for the query factory the connection is set on the flow (`_passedConn === false`): * on create set the current connection * call `preQuery()` (usage like on `sfDoctrineMasterSlavePlugin` get the current connection) * on build SQL query (just before execution) it sets the query connection for each components (I do not see any check when at least two components use different connection) --- lib/Doctrine/Manager.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/Doctrine/Manager.php b/lib/Doctrine/Manager.php index 957c51478..6cb974f4e 100644 --- a/lib/Doctrine/Manager.php +++ b/lib/Doctrine/Manager.php @@ -552,9 +552,7 @@ public function bindComponent($componentName, $connectionName) */ public function getConnectionForComponent($componentName) { - Doctrine_Core::modelsAutoload($componentName); - - if (isset($this->_bound[$componentName])) { + if ($this->hasConnectionForComponent($componentName)) { return $this->getConnection($this->_bound[$componentName]); } @@ -569,6 +567,10 @@ public function getConnectionForComponent($componentName) */ public function hasConnectionForComponent($componentName = null) { + if (!Doctrine_Core::modelsAutoload($componentName)) { + class_exists($componentName); // Trigger autoloader to bind connection. + } + return isset($this->_bound[$componentName]); }