We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 43302
    • 18 Posts
    Hi,

    So I've run into this small problem that I'm not sure if I'm not sure if I'm doing something wrong or if I'm just not understanding things right. I'm building a custom CMP for MODX Revolution to manage events of different types. For now I only have contests, but plan to add more in the future, so I'm building it in such a way that this is easy and keeps a clean database without too much duplicated data. For each event people can then send in an application through a form, these are handled as attendees.

    Lets start with the schema (I have redacted the indexes to save space). I have the following objects set up:

    <object class="harbourEvent" table="harbour_events" extends="xPDOSimpleObject">
            <field key="name" dbtype="varchar" precision="100" phptype="string" null="false" default=""/>
            <field key="location" dbtype="text" phptype="string" null="false" default=""/>
            <field key="type" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false"/>
            <field key="start_date" dbtype="datetime" phptype="datetime" null="true"/>
            <field key="end_date" dbtype="datetime" phptype="datetime" null="true"/>
            <field key="price_member" dbtype="decimal" precision="8,2" phptype="float" null="false" default="0"/>
            <field key="price_others" dbtype="decimal" precision="8,2" phptype="float" null="false" default="0"/>
            <field key="max_attendees" dbtype="int" precision="8" phptype="integer" null="true"/>
    
            <aggregate alias="EventType" class="harbourEventType" local="type" foreign="id" cardinality="one" owner="foreign"/>
            <composite alias="Attendees" class="harbourEventAttendee" local="id" foreign="event_id" cardinality="many" owner="local"/>
            <composite alias="Contestants" class="harbourContestAttendee" local="id" foreign="event_id" cardinality="many" owner="local"/>
        </object>
    
        <object class="harbourEventType" table="harbour_event_types" extends="xPDOSimpleObject">
            <field key="name" dbtype="varchar" precision="100" phptype="string" null="false"/>
            <field key="controller" dbtype="varchar" precision="25" phptype="string" null="false"/>
    
            <composite alias="Events" class="harbourEvent" local="id" foreign="type" cardinality="many" owner="local"/>
        </object>
    
        <object class="harbourEventAttendee" table="harbour_event_attendees" extends="xPDOSimpleObject">
            <field key="user_id" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="true"/>
            <field key="event_id" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false"/>
            <field key="boat_id" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="true"/>
            <field key="additional" dbtype="text" phptype="string" null="true"/>
    
            <aggregate alias="User" class="modUser" local="user_id" foreign="id" cardinality="one" owner="foreign"/>
            <aggregate alias="Event" class="harbourEvent" local="event_id" foreign="id" cardinality="one" owner="foreign"/>
        </object>
    
        <object class="harbourContestAttendee" table="harbour_contest_attendees" extends="harbourEventAttendee">
            <field key="spinnaker" dbtype="tinyint" precision="1" phptype="boolean" null="false" default="0"/>
            <field key="skipper_name" dbtype="varchar" precision="50" phptype="string" null="false"/>
            <field key="skipper_phone" dbtype="varchar" precision="24" phptype="string" null="false"/>
            <field key="skipper_email" dbtype="varchar" precision="50" phptype="string" null="false"/>
            <field key="association" dbtype="varchar" precision="100" phptype="string" null="false" default=""/>
            <field key="deckhands" dbtype="text" phptype="string" null="true"/>
        </object>


    I have one table for harbourEventType, this tells the CMP which panels to render and all that stuff. Next I have the harbourEvent table with stores data about each event. Finally I have harbourEventAttendee which is the main table with general fields that all types share, and harbourContestAttendee which is a specialised type of table that extends harbourEventAttendee, gets it's fields and adds some of it's own. Note how the inheritance goes xPDOSimpleObject <- harbourEventAttendee <- harbourContestAttendee.

    The harbourContestAttendee class looks like this:

    <?php
    /**
     * @package harbour
     * @subpackage model.mysql
     */
    require_once (strtr(realpath(dirname(__FILE__)), '\\', '/') . '/harboureventattendee.class.php');
    class harbourContestAttendee extends harbourEventAttendee {}

    I had to manually add the require to make it find the parent class.

    I then try to save the object with parent field data:

    <?php
    $attendee = $modx->newObject('harbourContestAttendee');
    $attendee->set('user_id', $hook->getValue('user_id'));
    $attendee->set('event_id', $hook->getValue('event'));
    $attendee->set('boat_id', $boat->get('id'));
    $attendee->fromArray(array(
        'additional' => $hook->getValue('additional'),
        'spinnaker' => $hook->getValue('spinnaker'),
        'skipper_name' => $hook->getValue('skipper_name'),
        'skipper_phone' => $hook->getValue('skipper_phone'),
        'skipper_email' => $hook->getValue('skipper_email'),
        'association' => $hook->getValue('association'),
        'deckhands' => $hook->getValue('deckhands')
    ));
    $attendee->save();

    I have checked what the object looks like after saving ($attendee->toJSON()), and there it still has the parent fields, but they have not been stored in the database table.

    The resulting table in the database has all the fields from EventAttendee and the additional ones from ContestAttendee, all in the same table. This makes sense to me. But when adding a ContestAttendee and saving the new object, all the EventAttendee fields never get saved. This I think, is because they do not exist in the map for ContestAttendee, and thus it does not know what to do with them.

    My question now is how do I get around this issue without hacking up the maps? How do I get it to save the parent fields as well into the same table where the fields exist already? Is this intended behaviour and am I just missing some crucial inheritance detail?

    Any help is appreciated! I really want to solve this one, and quickly.

    Thanks,
    Joakim

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

    [ed. note: fractalwolfe last edited this post 13 years, 3 months ago.]
    • discuss.answer
      • 22303 MODX Staff
      • 10,725 Posts
      Are you loading the class/map for harbourEventAttendee before loading harbourContestAttendee?
        • 43302
        • 18 Posts
        I'm guessing I have to do this manually before creating a new harbourContestAttendee object then? What's a good way of doing this? I remember seeing something like $modx->loadClass(), but not sure if that is what it's intended for, or if there's a better way.
          • 22303 MODX Staff
          • 10,725 Posts
          Calling loadClass() on the parent before loading the child is the appropriate way until we have proper autoloading in xPDO.
            • 43302
            • 18 Posts
            Alright, I tried the following, and it looks like the class gets loaded successfully (setDebug(true) and checked error log) but it still doesn't know what to do with the parent fields.

            $modx->loadClass('harbour.harbourEventAttendee', $harbour->config['modelPath'], true, true);
            $attendee = $modx->newObject('harbourContestAttendee');
            $attendee->set('user_id', $hook->getValue('user_id'));
            $attendee->set('event_id', intval($hook->getValue('event')));
            $attendee->set('boat_id', $boat->get('id'));
            $attendee->fromArray(array(
                'additional' => $hook->getValue('additional'),
                'spinnaker' => $hook->getValue('spinnaker'),
                'skipper_name' => $hook->getValue('skipper_name'),
                'skipper_phone' => $hook->getValue('skipper_phone'),
                'skipper_email' => $hook->getValue('skipper_email'),
                'association' => $hook->getValue('association'),
                'deckhands' => $hook->getValue('deckhands')
            ));
            $attendee->save();


            This is what it outputs in the error log:

            [2013-07-09 16:13:15] (DEBUG @ /index.php) Returning table name: `modx_harbour_contest_attendees` for class: harbourContestAttendee
            [2013-07-09 16:13:15] (DEBUG @ /index.php) Returning ancestry for harbourContestAttendee: Array
            (
                [0] => harbourContestAttendee
                [1] => harbourEventAttendee
                [2] => xPDOSimpleObject
                [3] => xPDOObject
            )
            [2013-07-09 16:13:15] (DEBUG @ /index.php) No primary key value found for pk definition: id
            
            [2013-07-09 16:13:15] (DEBUG @ /index.php) Returning ancestry for harbourContestAttendee: Array
            (
                [0] => harbourEventAttendee
                [1] => xPDOSimpleObject
                [2] => xPDOObject
            )
            
            [2013-07-09 16:13:15] (DEBUG @ /index.php) Returning validation rules: Array
            (
            )
            
            [2013-07-09 16:13:15] (DEBUG @ /index.php) Validation called but no rules were found.
            [2013-07-09 16:13:15] (DEBUG @ /index.php) Validator class executed, result = 1
            [2013-07-09 16:13:15] (DEBUG @ /index.php) Executing SQL:
            INSERT INTO `modx_harbour_contest_attendees` (`spinnaker`, `skipper_name`, `skipper_phone`, `skipper_email`, `association`, `deckhands`) VALUES (:spinnaker, :skipper_name, :skipper_phone, :skipper_email, :association, :deckhands)
            with bindings:
            Array
            (
                [:spinnaker] => Array
                    (
                        [value] => 0
                        [type] => 1
                    )
            
                [:skipper_name] => Array
                    (
                        [value] => John Doe
                        [type] => 2
                    )
            
                [:skipper_phone] => Array
                    (
                        [value] => 012-3456789
                        [type] => 2
                    )
            
                [:skipper_email] => Array
                    (
                        [value] => [email protected]
                        [type] => 2
                    )
            
                [:association] => Array
                    (
                        [value] => WSF
                        [type] => 2
                    )
            
                [:deckhands] => Array
                    (
                        [value] => Jane Doe
            Carl Test
            Ren Test
                        [type] => 2
                    )
            
            )
            
            [2013-07-09 16:13:15] (DEBUG @ /index.php) Returning table class: harbourContestAttendee for class: harbourContestAttendee
            [2013-07-09 16:13:15] (DEBUG @ /index.php) Returning table name: `modx_harbour_contest_attendees` for class: harbourContestAttendee
            
            [2013-07-09 16:13:15] (DEBUG @ /index.php) xPDOObject::_getDataType() -- No data type specified for field (user_id), using `text`.
            [2013-07-09 16:13:15] (DEBUG @ /index.php) xPDOObject::_getPHPType() -- No PHP type specified for field (user_id), using `string`.
            [2013-07-09 16:13:15] (DEBUG @ /index.php) xPDOObject::_getDataType() -- No data type specified for field (event_id), using `text`.
            [2013-07-09 16:13:15] (DEBUG @ /index.php) xPDOObject::_getPHPType() -- No PHP type specified for field (event_id), using `string`.
            [2013-07-09 16:13:15] (DEBUG @ /index.php) xPDOObject::_getDataType() -- No data type specified for field (boat_id), using `text`.
            [2013-07-09 16:13:15] (DEBUG @ /index.php) xPDOObject::_getPHPType() -- No PHP type specified for field (boat_id), using `string`.
            [2013-07-09 16:13:15] (DEBUG @ /index.php) xPDOObject::_getDataType() -- No data type specified for field (additional), using `text`.
            [2013-07-09 16:13:15] (DEBUG @ /index.php) xPDOObject::_getPHPType() -- No PHP type specified for field (additional), using `string`.


            I must say I don't completely understand the last two parameters of loadClass(), but from what I gathered from the forums that should be right? Am I missing something?


            EDIT:
            I just realized my error, obviously the class is related an xPDOObject. Switched $transient to false and it's now working perfectly.

            $modx->loadClass('harbour.harbourEventAttendee', $harbour->config['modelPath'], true, false);


            Thanks for your help! [ed. note: fractalwolfe last edited this post 13 years, 3 months ago.]
              • 22303 MODX Staff
              • 10,725 Posts
              Quote from: fractalwolfe at Jul 09, 2013, 08:23 AM
              I just realized my error, obviously the class is related an xPDOObject. Switched $transient to false and it's now working perfectly.

              $modx->loadClass('harbour.harbourEventAttendee', $harbour->config['modelPath'], true, false);


              Thanks for your help!
              You don't actually need to include anything but the first parameter if your package is loaded, and likely don't need the "harbour." prefix, though that is harmless, e.g.
              $modx->loadClass('harbourEventAttendee');