We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 36972
    • 8 Posts
    Hi all, I'm having some issues when extending modUser and linking it to a custom table. Basically I'm extending users to have a school_id and salutation field, and more will come later.

    Schema:
    <model package="jaylearn" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM">	
    
    	<object class="jlUser" table="users" extends="modUser">
    		<composite alias="Data" class="jlUserData" local="id" foreign="user_id" cardinality="one" owner="local" />
    	</object>
    	
    	<object class="jlUserData" table="userdata" extends="xPDOObject">
    		<field key="user_id" dbtype="int" precision="11" phptype="integer" null="false" index="index" />
    		<field key="school_id" dbtype="int" precision="11" phptype="integer" null="false" index="index" />
    		<field key="salutation" dbtype="varchar" precision="255" phptype="string" null="true" index="index" />
    		<aggregate alias="User" class="jlUser" local="user_id" foreign="id" cardinality="one" owner="foreign" />
    		<composite alias="School" class="jlSchool" local="school_id" foreign="id" cardinality="one" owner="local" />
    	</object>
    	
    	
    	<object class="jlSchool" table="schools" extends="xPDOObject">
    		<field key="id" dbtype="int" precision="11" phptype="integer" null="false" index="pk"  generated="native" />
    		<field key="name" dbtype="varchar" phptype="string" null="true" />
    		<index alias="PRIMARY" name="PRIMARY" primary="true" unique="true">
    			<column key="id" collation="A" null="false" />
    		</index>
    		<composite alias="UserData" class="jlUserData" local="id" foreign="school_id" cardinality="many" owner="local" />
    	</object>
    </model>
    


    Creation code:
    $base_path = !empty($base_path) ? $base_path : $modx->getOption('core_path').'components/jaylearn/';
    $modx->addPackage('jaylearn',$base_path.'model/', "jl_");
    
    $newUser = $modx->newObject('jlUser');
    $newUser->fromArray(array(
        'username' => 'newuser',
        'password' => 'password',
        'class_key' => 'jlUser',
    ));
    
    $newProfile = $modx->newObject('modUserProfile');
    $newProfile->set('fullname', 'New User');
    $newProfile->set('email', '[email protected]');
    
    $newData = $modx->newObject('jlUserData');
    $newData->set('salutation', 'Mr');
    
    $newUser->addOne($newProfile);
    $newUser->addOne($newData, 'Data');
    
    $newUser->save();
    


    If I instantiate $newUser as modUser, I get this error:
    [2011-09-16 23:15:36] (ERROR @ /index.php) No foreign key definition for parentClass: modUser using relation alias: Data


    and if I instantiate as jlUser, this is what happens:

    [2011-09-16 23:17:01] (ERROR @ /connectors/security/user.php) Could not get table class for class: modAccess
    [2011-09-16 23:17:01] (ERROR @ /connectors/security/user.php) Could not get table name for class: modAccess
    [2011-09-16 23:17:01] (ERROR @ /connectors/security/user.php) Error 42000 executing statement: 
    Array
    (
        [0] => 42000
        [1] => 1064
        [2] => You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS `modAccess` WHERE `modAccess`.`principal` = 38' at line 1
    )
    
    [2011-09-16 23:17:01] (ERROR @ /connectors/security/user.php) Error 42S02 executing statement: 
    Array
    (
        [0] => 42S02
        [1] => 1146
        [2] => Table 'jaylearn_modx.modx_userdata' doesn't exist
    )
    
    [2011-09-16 23:17:15] (ERROR @ /index.php) Error 42S02 executing statement:
    INSERT INTO `jl_users` (`username`, `password`, `cachepwd`, `class_key`, `active`, `hash_class`, `salt`) VALUES ('newuser', 'NTiGQBjLFnw3NQwATf1y0lQMvT6NWpsvjQkoxRuMTL4=', '', 'jlUser', 1, 'hashing.modPBKDF2', 'e989c82f51caf063b65167bd946caba5')
    Array
    (
        [0] => 42S02
        [1] => 1146
        [2] => Table 'jaylearn_modx.jl_users' doesn't exist
    )



    Am I close?? Or am I going about this the wrong way? Thanks in advance!

    This question has been answered by opengeek. See the first response.

      • 26903
      • 1,336 Posts
      Table 'jaylearn_modx.modx_userdata' doesn't exist
      Well, does it, the schema definition above doesn't create the tables for you.
        Use MODx, or the cat gets it!
        • 28215
        • 4,149 Posts
        Due to the way the User is loaded in MODX currently, you cannot add metadata to the custom user. So, your aggregate for your jlUser is moot.

        This is because you're calling addPackage with your package far after the User is loaded. Jason can elaborate further, but with Users you'll have to do normal joins instead of addOne/getOne.

        Also, make sure your tables are created first.
          shaun mccormick | bigcommerce mgr of software engineering, former modx co-architect | github | splittingred.com
          • 36972
          • 8 Posts
          I should've mentioned, my custom tables are created with the prefix jl_
          So when I use modUser and try to assign metadata, it adds the modx_ prefix incorrectly. Thank you for your reply, you've pointed me in the right direction. I'll have a further look tomorrow and see if I can get my extended user working properly.
            • 22303 MODX Staff
            • 10,725 Posts
            Actually, that should work fine. You do definitely need to create the related tables before attempting to use your derivative class. Before 2.1, they would be created automatically, but now you need to make sure they are created or set the option for them to be automatically created. Typically, this is done in a resolver when installing a package.

            You do need to create the User as your derivative class explicitly though. Do not try to create it as modUser and just set the class_key.
              • 36972
              • 8 Posts
              I haven't had a problem with creating the actual tables, I followed the tutorial here:

              http://rtfm.modx.com/display/revolution20/Extending+modUser

              and tried to modify it to my needs. One thing that tutorial does not show is how to programmatically create an instance of your extended user. So back to this error:

              [2011-09-17 08:22:41] (ERROR @ /index.php) Error 42S02 executing statement:
              INSERT INTO `jl_users` (`username`, `password`, `cachepwd`, `class_key`, `active`, `hash_class`, `salt`) VALUES ('newuser', 'Mv/iAPyyKsQD1FDm5iK2QQ2pDH2/PBSEWZzrO9dHEjo=', '', 'jlUser', 1, 'hashing.modPBKDF2', '685625e6468d8e3713f6aab5c4318984')
              Array
              (
                  [0] => 42S02
                  [1] => 1146
                  [2] => Table 'jaylearn_modx.jl_users' doesn't exist
              )


              My custom tables are using the prefix jl_ but because my extended user is in the same package, it is trying to access jl_users instead of modx_users. How do you mix table prefixes in the one package? Looking at the tutorial, their schema is mixing the 'users' table in with their own custom-prefixed tables, so wouldn't they run into the same problem I'm having?

              • discuss.answer
                • 22303 MODX Staff
                • 10,725 Posts
                To be honest, you should not use a table prefix different from the modx install unless there is a very specific reason. Instead, allow the prefix set for modx itself to be used for your tables as well. Table prefixes are runtime mechanisms that are there only to allow you to run more than one instance of a model within a single database container, not to "prefix" your model for differentiation.
                  • 3749
                  • 24,544 Posts
                  You need the table name (without the modx_ prefix) in your schema. Something like this:

                  <object class="modJlUser" table="jl_users" extends="modUser">


                  Changing the table name to "modx_jl_users" might take care of things, but you may have to regenerate the class and map files.
                    Did I help you? Buy me a beer
                    Get my Book: MODX:The Official Guide
                    MODX info for everyone: http://bobsguides.com/modx.html
                    My MODX Extras
                    Bob's Guides is now hosted at A2 MODX Hosting
                    • 36972
                    • 8 Posts
                    Thanks for all the input guys, I've got the creation of users sorted! My setup:

                    Database tables:

                    • modx_jl_userdata
                    • modx_jl_salutations
                    • modx_jl_schools

                    Schema:
                    <model package="jaylearn" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM">	
                    	<object class="jlUser" table="users" extends="modUser">
                    		<composite alias="Data" class="jlUserData" local="id" foreign="user_id" cardinality="one" owner="local" />
                    	</object>
                    	
                    	<object class="jlUserData" table="jl_userdata" extends="xPDOObject">
                    		<field key="user_id" dbtype="int" precision="11" phptype="integer" null="false" index="index" />
                    		<field key="school_id" dbtype="int" precision="11" phptype="integer" null="false" index="index" />
                    		<field key="salutation" dbtype="varchar" precision="255" phptype="string" null="true" index="index" />
                    		<aggregate alias="User" class="jlUser" local="user_id" foreign="id" cardinality="one" owner="foreign" />
                    		<composite alias="School" class="jlSchool" local="school_id" foreign="id" cardinality="one" owner="local" />
                    	</object>
                    	
                    	<object class="jlSchool" table="jl_schools" extends="xPDOObject">
                    		<field key="id" dbtype="int" precision="11" phptype="integer" null="false" index="pk"  generated="native" />
                    		<field key="name" dbtype="varchar" phptype="string" null="true" />
                    		<index alias="PRIMARY" name="PRIMARY" primary="true" unique="true">
                    			<column key="id" collation="A" null="false" />
                    		</index>
                    		<composite alias="UserData" class="jlUserData" local="id" foreign="school_id" cardinality="many" owner="local" />
                    	</object>
                    </model>


                    Code:
                    $base_path = !empty($base_path) ? $base_path : $modx->getOption('core_path').'components/jaylearn/';
                    $modx->addPackage('jaylearn',$base_path.'model/', 'modx_');
                    
                    $newUser = $modx->newObject('jlUser');
                    $newUser->fromArray(array(
                        'username' => 'seconduser',
                        'password' => 'password',
                        'class_key' => 'jlUser',
                    ));
                    
                    $newProfile = $modx->newObject('modUserProfile');
                    $newProfile->set('fullname', 'Second User');
                    $newProfile->set('email', '[email protected]');
                    
                    $newData = $modx->newObject('jlUserData');
                    $newData->set('salutation', 'Dr');
                    
                    $newUser->addOne($newProfile, 'Profile');
                    $newUser->addOne($newData, 'Data');
                    
                    $newUser->save();
                    
                    //echo out some details of the new user
                    //note: getData is a custom method added to the jlUser class and simply returns $user->getOne('Data'); 
                    echo "<br/>User created: ".$newUser->getData()->get('salutation').' '.$newUser->getOne('Profile')->get('fullname');
                    


                    Everything is working well with the above code, but I'm getting an error when I try and delete the user from within Manager -
                    [2011-09-17 13:59:31] (ERROR @ /connectors/security/user.php) Could not get table class for class: modAccess
                    [2011-09-17 13:59:31] (ERROR @ /connectors/security/user.php) Could not get table name for class: modAccess
                    [2011-09-17 13:59:31] (ERROR @ /connectors/security/user.php) Error 42000 executing statement: 
                    Array
                    (
                        [0] => 42000
                        [1] => 1064
                        [2] => You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS `modAccess` WHERE `modAccess`.`principal` = 47' at line 1
                    )


                    However, the user is successfully removed and all related data too, so should I be worried?
                      • 22303 MODX Staff
                      • 10,725 Posts
                      Don't worry about the modAccess error. That is a core issue that needs to be resolve and it should not affect anything.