Doctrine 1
  1. Doctrine 1
  2. DC-344

Trouble with auto including generate Base class with specifik name

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 1.2.1
    • Fix Version/s: None
    • Component/s: None
    • 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

        Activity

        Hide
        blt added a comment -

        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');

        Show
        blt added a comment - 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');
        Hide
        Michal Olszewski added a comment -

        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.

        Show
        Michal Olszewski added a comment - 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.
        Hide
        Svetoslav Shterev added a comment -

        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.

        Show
        Svetoslav Shterev added a comment - 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.
        Hide
        Michal Olszewski added a comment -

        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!

        Show
        Michal Olszewski added a comment - 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!
        Hide
        Gustavo added a comment -

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

        Show
        Gustavo added a comment - Same problem here following the same example of the 1.2 tutorial.

          People

          • Assignee:
            Benjamin Eberlei
            Reporter:
            Havelka Ondrej
          • Votes:
            3 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: