[DC-344] Trouble with auto including generate Base class with specifik name Created: 09/Dec/09  Updated: 21/Mar/10

Status: Open
Project: Doctrine 1
Component/s: None
Affects Version/s: 1.2.1
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Havelka Ondrej Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 3
Labels: None
Environment:

Linux, Ubuntu 9.04 64b



 Description   

I have found a problem during testing example model on page http://www.doctrine-project.org/documentation/cookbook/1_1/en/code-igniter-and-doctrine . A use YAML model with object name UserGroup and call method Doctrine_Core::createTablesFromModels('models'); process faling with error:

Fatal error: Class 'BaseUserGroup' not found in /sourcepath/models/UserGroup.php on line 13

Generate model file included abstract class BaseUserGroup exist and is OK. If I include BaseUserGroup manuly or rename object "UserGroup" on "UserGroups" everithing work fine. I thing here is a problem with autoloding base class with specifik name.

Here is my code example:

Doctrine_Core::dropDatabases();
Doctrine_Core::createDatabases();
Doctrine_Core::generateModelsFromYaml('sourcepath/yaml/model.yml', 'models');
Doctrine_Core::createTablesFromModels('models');

Trouble shotting YAML model is:

UserGroup:
columns:
user_id:
type: integer(4)
primary: true
group_id:
type: integer(4)
primary: true



 Comments   
Comment by Gustavo [ 26/Dec/09 ]

Same problem here following the same example of the 1.2 tutorial.

Comment by Michal Olszewski [ 08/Feb/10 ]

Hi,

I've stumbled upon the same problem and I think I know where the issue is.

So Doctrine_Core::createTablesFromModels() calls Doctrine_Export::exportSchema() which in turn calls Doctrine_Core::loadModels().

Doctrine_Core::loadModels() uses RecursiveIteratorIterator and iterates over all found files.

Now I think the order of files returned by RecursiveIteratorIterator is not always the same (depends on OS, filenames and cosmic radiation ), but the most important thing here is that class files from 'modules/generated' directory (as in examples) ARE NOT included before subclasses derived from generated classes. This means that Doctrine_Core::autoload() fails to load classes from 'modules/generated' directory, exactly this check fails:

if (0 !== stripos($className, 'Doctrine_') || class_exists($className, false) || interface_exists($className, false))

as base class is not starting with 'Doctrine_' and is not yet loaded.

To fix it properly the algorithm for loading modules must be changed to first include 'modules/generated' classes and then rest of classes. I am not sure but maybe Core::autoload() might be changed to include base classes properly.

QUICK WORKAROUND:
As a quick workaround I've changed parameters in call to createTablesFromModels() to:

Doctrine_Core::createTablesFromModels(array('models/generated','models'));

as createTablesFromModels() can accept array of directories.

Hope this helps you, please let me know if you need any more information. Thanks!

Comment by Svetoslav Shterev [ 09/Feb/10 ]

You are missing the model autoloader(http://www.doctrine-project.org/upgrade/1_2#Models%20Autoloading), which was added in 1.2

That should fix the problem with conservative autoloading.

Comment by Michal Olszewski [ 09/Feb/10 ]

I've tried registering modelsAutoload() and it works superb in this case for both aggressive and conservative loading.

It is a shame that it is not mentioned in 1.2 PDF I've got - it'd make life easier for some people

Thanks for your help.

Comment by blt [ 21/Mar/10 ]

i am a new user to doctrine and i hit this brick wall. this bug report was all that saved me, and it is a bit misleading. my test results are below. in the end i found a combination that worked, but this seems like a glaring bug especially since the pdf takes the user right down a path that fails completely in all cases (default aggressive loading, doesn't work for me at all).

i am using a pear loaded version 1.2 on ubuntu

here are my test results:
---------------------------------------------------------------------------------------------------
case 1: load models right after generating them, without modelsAutoLoad() call: SUCCESS/FAIL varies
---------------------------------------------------------------------------------------------------
in doctrine_bootstrap.php file:
<?
require_once('lib/vendor/doctrine/Doctrine.php');
spl_autoload_register(array('Doctrine', 'autoload'));
$manager = Doctrine_Manager::getInstance();
$conn = Doctrine_Manager::connection('mysql:// DSN REMOVED ','doctrine');

in test.php:
<?
require_once('doctrine_bootstrap.php');
Doctrine_Core::generateModelsFromDb('models', array('doctrine'), array('generateTableClasses' => true));
Doctrine_Core::loadModels('models');

---------------------------------------------------------------------------------------------------
case 2: load models after they have already been generated, without modelsAutoLoad() call: FAIL
---------------------------------------------------------------------------------------------------
in doctrine_bootstrap.php file:
<?
require_once('lib/vendor/doctrine/Doctrine.php');
spl_autoload_register(array('Doctrine', 'autoload'));
$manager = Doctrine_Manager::getInstance();
$conn = Doctrine_Manager::connection('mysql:// DSN REMOVED ','doctrine');

in test.php:
<?
// note: all model classes are in ./models and ./models/generated
require_once('doctrine_bootstrap.php');
Doctrine_Core::loadModels('models');

---------------------------------------------------------------------------------------------------
case 3: load models after they have already been generated, with the modelsAutoLoad() call and default aggressive setting: FAIL
---------------------------------------------------------------------------------------------------
in doctrine_bootstrap.php file:
<?
require_once('lib/vendor/doctrine/Doctrine.php');
spl_autoload_register(array('Doctrine', 'autoload'));
$manager = Doctrine_Manager::getInstance();
$conn = Doctrine_Manager::connection('mysql:// DSN REMOVED ','doctrine');

spl_autoload_register(array('Doctrine_Core', 'modelsAutoload'));

in test.php:
<?
// note: all model classes are in ./models and ./models/generated
require_once('doctrine_bootstrap.php');
Doctrine_Core::loadModels('models');

---------------------------------------------------------------------------------------------------
case 4: load models after they have already been generated, with the modelsAutoLoad() call and conservative loading: SUCCESS
---------------------------------------------------------------------------------------------------
in doctrine_bootstrap.php file:
<?
require_once('lib/vendor/doctrine/Doctrine.php');
spl_autoload_register(array('Doctrine', 'autoload'));
$manager = Doctrine_Manager::getInstance();
$conn = Doctrine_Manager::connection('mysql:// DSN REMOVED ','doctrine');

$manager->setAttribute(Doctrine_Core::ATTR_MODEL_LOADING, Doctrine_Core::MODEL_LOADING_CONSERVATIVE);
spl_autoload_register(array('Doctrine_Core', 'modelsAutoload'));

in test.php:
<?
// note: all model classes are in ./models and ./models/generated
require_once('doctrine_bootstrap.php');
Doctrine_Core::loadModels('models');

Generated at Mon Dec 22 11:31:55 UTC 2014 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.