We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 26503
    • 620 Posts
    Hi modx is not adding records to a related table, wondering if it's actually supposed to be doing this:

    I have [part] of a schema:

    	<object class="ContractBudgets" table="contract_budgets" extends="xPDOSimpleObject">
    		<field key="created" dbtype="timestamp" phptype="timestamp" null="true" default="CURRENT_TIMESTAMP"  extra="on update current_timestamp" />
    		<field key="modified" dbtype="timestamp" phptype="timestamp" null="true" />
    		<field key="budget_type_id" dbtype="int" precision="8" phptype="integer" null="false" index="index" />
    		<field key="contract_id" dbtype="int" precision="8" phptype="integer" null="false" index="index" />
    		<field key="budget_f1" dbtype="decimal" precision="12,2" phptype="float" null="false" />
    		<field key="budget_f2" dbtype="decimal" precision="12,2" phptype="float" null="false" />
    		<field key="comment" dbtype="longtext" phptype="string" null="true" />
    		
    		<aggregate alias="Contracts" class="Contracts" local="contract_id" foreign="id" cardinality="one" owner="foreign" />
    		
    	</object>
    
    	<object class="Contracts" table="contracts" extends="xPDOSimpleObject">
    		<field key="created" dbtype="timestamp" phptype="timestamp" null="false" default="CURRENT_TIMESTAMP"  extra="on update current_timestamp" />
    		<field key="modified" dbtype="timestamp" phptype="timestamp" null="false" default="0000-00-00 00:00:00" />
    		<field key="status_id" dbtype="int" precision="8" phptype="integer" null="true" index="index" />
    		<field key="location_id" dbtype="int" precision="8" phptype="integer" null="false" />
    		<field key="client_id" dbtype="int" precision="8" phptype="integer" null="false" />
    		<field key="employer_id" dbtype="int" precision="8" phptype="integer" null="false" />
    		<field key="program_id" dbtype="int" precision="8" phptype="integer" null="false" />
    		<field key="requester_uid" dbtype="int" precision="8" phptype="integer" null="false" />
    		<field key="approver_uid" dbtype="int" precision="8" phptype="integer" null="false" />
    		<field key="start_date" dbtype="date" phptype="date" null="false" />
    		<field key="end_date" dbtype="date" phptype="date" null="false" />
    		<field key="start_balance" dbtype="decimal" precision="12,2" phptype="float" null="false" />
    		<field key="end_balance" dbtype="decimal" precision="12,2" phptype="float" null="true" />
    		<field key="comment" dbtype="longtext" phptype="string" null="true" />
    		
    		<aggregate alias="StatusFlags" class="StatusFlags" local="status_id" foreign="id" cardinality="one" owner="foreign" />
    		<aggregate alias="Locations" class="Locations" local="location_id" foreign="id" cardinality="one" owner="foreign" />
    		<aggregate alias="Clients" class="Clients" local="client_id" foreign="id" cardinality="one" owner="foreign" />
    		<aggregate alias="Employers" class="Employers" local="employer_id" foreign="id" cardinality="one" owner="foreign" />
    		<aggregate alias="Programs" class="Programs" local="program_id" foreign="id" cardinality="one" owner="foreign" />		
    		
    		<composite alias="ContractBudgets" class="ContractBudgets" local="id" foreign="contract_id" cardinality="many" owner="local" />		
    
    	</object>





    Then a form that submits pretty much all the required fields in both tables, it processed with this:

     /**
    * Generic add data to database function
    *
    * @access public
    * @param string $scriptProperties The properties for the snippet
    * @param string $hook a reference to the formit hook data
    * @return  
    *
    */
    	public function createDatabaseEntry($scriptProperties, & $hook){
    		
    		//print_r($scriptProperties);exit();
    		
    		$table = ucfirst($scriptProperties['table']);
    		
    		$formfields = $hook->getValues();
    		
    		///echo '<pre>';print_r($formfields);echo '</pre>';exit();
    				
    		$newData = $this->modx->newObject($table);
    		
    		foreach($formfields as $key => $value){
    			
    			$newData->set($key,$value);
    		
    		}
    		
    		if(!$newData->save()){
    			
    			$mess = $this->modx->lexicon('modflowthrough.add_'.$table.'_failed');
    			$this->modx->setPlaceholder('message_error',$mess);
    			return false;
    			
    		}else{
    			
    			$mess = $this->modx->lexicon('modflowthrough.add_'.$table.'_success');
    			$this->modx->setPlaceholder('message_success',$mess);
    			
    		}
    		
    		return true;
    
    	} // end createDatabaseEntry




    Which does add data to the main table, just not the related one... I'm not even sure if xpdo is supposed to be able to do that?

    any help?
      *** Not just websites, we also create signage, banners, print, trade show displays and more! ***

      Sean Kimball CLP, CLS.
      Technical Director / Sr. Developer | BigBlock Studios
      ._______________________________________________.
      Bigblock Studios http://www.bigblockstudios.ca Web site design & development.
      27-1300 King Street East. Box 167 Oshawa, Ontario L1H8J4 Canada.
      phone/fax: 905-426-5525
      • 3749
      • 24,544 Posts
      First, a few suggestions on variable and class names. Any alias that has a cardinality of one should have a singular name (StatusFlag, Location, Employer, etc.), otherwise, you're going to be doing stuff like $object->getOne('Employers'), which is just wrong. wink

      Also, class objects are usually named for what's in a single row of the table, not the whole table (e.g., modResource not modResources).

      Using $scriptProperties['table'] suggests that you're using a table name, but using it as the argument to newObject() requires the name of an object, not a table name. If it can be more than one object, call it something like $objectName or (better) $objectClass so it's clear what it is. It's definitely not a table.

      Now for your actual question. wink

      It doesn't look like your code creates any related object to be saved. xPDO will save related objects automatically, but they have to be created first. For example:

      $user = $modx->newObject('modUser');
      /* set user fields here */
      $profile = $modx->newObject('modUserProfile');
      /* set profile fields here */
      $user->addOne($profile);
      $user->save();
      


      The profile will be saved automatically since it was 'added' to the user object and is specified as a related object in the schema.

      A couple final questions:

      Have you generated class and map files from your schema (and have you regenerated them whenever the schema changes)?

      Are you loading the class somewhere before trying to run your code?

        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
        • 26503
        • 620 Posts
        Thanks Bob, I very clearly see my error now.

        Good advice on the naming as well, maybe I'm not so old that I can't learn some good habits wink

        How's the attached schema [modified/fixed] look? better? smiley

        -sean [ed. note: sean69 last edited this post 12 years, 7 months ago.]
          *** Not just websites, we also create signage, banners, print, trade show displays and more! ***

          Sean Kimball CLP, CLS.
          Technical Director / Sr. Developer | BigBlock Studios
          ._______________________________________________.
          Bigblock Studios http://www.bigblockstudios.ca Web site design & development.
          27-1300 King Street East. Box 167 Oshawa, Ontario L1H8J4 Canada.
          phone/fax: 905-426-5525
          • 26503
          • 620 Posts
          hmmmm - now I am getting this error:

          [2014-02-25 21:49:43] (WARN @ /index.php) Foreign key definition for class , alias ContractBudget not found, or cardinality is not 'one'. 
          
          [2014-02-25 21:49:43] (WARN @ /index.php) Could not add related object! 
          
          Array ( [id] => [created] => 2014-02-25 21:49:43 [modified] => [budget_type_id] => 2 [contract_id] => [budget_f1] => 99.99 [budget_f2] => 99.99 [comment] => [nospam:blank] => [requester_uid] => 1 [program_id] => 1 [status_id] => 2 [location_id] => 9 [client_id] => 3 [employer_id] => 3 [start_balance_f1] => 999.99 [start_balance_f2] => 999.99 [start_date] => 2014-02-05 [end_date] => 2014-02-07 [submit] => [nospam] => ) 


          it certainly looks right in the schema to me?
            *** Not just websites, we also create signage, banners, print, trade show displays and more! ***

            Sean Kimball CLP, CLS.
            Technical Director / Sr. Developer | BigBlock Studios
            ._______________________________________________.
            Bigblock Studios http://www.bigblockstudios.ca Web site design & development.
            27-1300 King Street East. Box 167 Oshawa, Ontario L1H8J4 Canada.
            phone/fax: 905-426-5525
            • 3749
            • 24,544 Posts
            The schema looks very good to me. I think you may be using addOne() where you should be using addMany(). If there can be more than one of what you're adding, addMany() is correct, even if you're just adding one. Here's an example:

            $tvs = array();
            $tv = $modx->newObject('modTemplateVar');
            $template = $modx->newObject('modTemplate');
            
            $tvs[] = $tv;
            $template->addMany($tvs);
            


              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
              • 26503
              • 620 Posts
              OMG that's embarrassing, the error kind of exactly says that, doesn't it.... too many late nights.

              Thanks again Bob.


              Quote from: BobRay at Feb 26, 2014, 01:17 AM
              The schema looks very good to me. I think you may be using addOne() where you should be using addMany(). If there can be more than one of what you're adding, addMany() is correct, even if you're just adding one. Here's an example:

              $tvs = array();
              $tv = $modx->newObject('modTemplateVar');
              $template = $modx->newObject('modTemplate');
              
              $tvs[] = $tv;
              $template->addMany($tvs);
              


                *** Not just websites, we also create signage, banners, print, trade show displays and more! ***

                Sean Kimball CLP, CLS.
                Technical Director / Sr. Developer | BigBlock Studios
                ._______________________________________________.
                Bigblock Studios http://www.bigblockstudios.ca Web site design & development.
                27-1300 King Street East. Box 167 Oshawa, Ontario L1H8J4 Canada.
                phone/fax: 905-426-5525