We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 26503
    • 620 Posts
    I have a function:

    public function createNewContract($scriptProperties, & $hook){
    
    		$formfields = $hook->getValues();		
    		
    		$newContract = $this->modx->newObject('Contract');
    
    		foreach($formfields as $key => $value){
    			
    			$newContract->set($key,$value);
    					
    		}
    		
    		foreach($formfields['budget_type_id'] as $value){
    			
    			$newBudget = $this->modx->newObject('ContractBudget');
    			
    			$newBudget->set('budget_type_id',$value);
    			$newBudget->set('budget_f1',$value);
    			$newBudget->set('budget_f2',$value);
    			
    		    $newContract->addOne($newBudget);
    		}
    
    		if(!$newContract->save()){
    
    			return false;
    	
    		}
    		//exit();
    		return true;
    
    	}



    which is inserting the following form fields into a custom table:

    Array
    (
        [nospam:blank] => 
        [requester_uid] => 1
        [program_id] => 1
        [status_id] => 1
        [location_id] => 1
        [client_id] => 1
        [employer_id] => 1
        [start_balance_f1] => 999.99
        [start_balance_f2] => 999.99
        [budget_type_id] => Array
            (
                [0] => 1
                [1] => 2
                [2] => 2
            )
    
        [budget_f1] => Array
            (
                [0] => 34534
                [1] => 234523
                [2] => 234523
            )
    
        [budget_f2] => Array
            (
                [0] => 2345234
                [1] => 234523
                [2] => 23452345
            )
    
        [start_date] => 2015-02-04
        [end_date] => 2015-01-02
        [comment] => 
        [submit] => 
        [nospam] => 
    )




    It adds the Contract object well enough, but I can only get it to add a single ContractBudget object!

    eventually I need to figure out how to merge the three budget_type_id, budget_f1, budget_f2 so that each record in the DB looks like:

    budget_f2[0] | budget_f1[0] | budget_type_id[0]
    budget_f2[1] | budget_f1[1] | budget_type_id[1]
    budget_f2[2] | budget_f1[2] | budget_type_id[2]

    What is there is just test for now.

      *** 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
      Because a contract can have more than one budget, you need to use addMany(). Something like this:

      $cbs = array();
      foreach($formfields['budget_type_id'] as $value){
                   
          $newBudget = $this->modx->newObject('ContractBudget');
          
          $newBudget->set('budget_type_id',$value);
          $newBudget->set('budget_f1',$value);
          $newBudget->set('budget_f2',$value);
                
          $cbs[] = $newBudget;
      }
      
      $newContract->addMany($cbs);
      

        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 see exactly what should be happening now & as far as I can tell everything I have is correct with the exception of possibly the schema, here's what I have, the comments tell the story, but basically addOne will work, while addMany will not!

        public function createNewContract($scriptProperties, & $hook){
        
        	$formfields = $hook->getValues();		
        
        	echo '<pre>';print_r($formfields);echo '</pre>';
        
        	$newContract = $this->modx->newObject('Contract');
        
        	foreach($formfields as $key => $value){
        
        		$newContract->set($key,$value);
        
        	}
        
        	$contractBudgets = array();
        
        	foreach($formfields['budget_type_id'] as $value){
        
        		$newBudget = $this->modx->newObject('ContractBudget');	
        
        		$newBudget->set('budget_type_id',$value);
        		$newBudget->set('budget_f1',$value);
        		$newBudget->set('budget_f2',$value);
        		// I don't have to set this, it get automatically picked up from the newContract object
        		$newBudget->set('contract_id',999);
        
        		$contractBudgets[] = $newBudget;
        
        	}
        
        	// this works, shows correct count of array of objects
        	echo '<br>'.count($contractBudgets);
        
        	// works, I can extract the correct data from each object
        	echo '<br> budget_f2 0 = '.$contractBudgets[0]->get('budget_f2');
        	echo '<br> budget_f2 1 = '.$contractBudgets[1]->get('budget_f2');
        	echo '<br> budget_f2 2 = '.$contractBudgets[2]->get('budget_f2');
        
        	// does not work, no records are added to the contrac_budget table.
        	$newContract->addMany($contractBudgets);
        
        	// this will add a contract budget but gives the error
        	// (ERROR @ /index.php) ContractBudget: Attempt to set NOT NULL field contract_id to NULL
        	$newContract->addOne($newBudget);
        
        	// a new contract is saved however!?
        	if(!$newContract->save()){
        
        		$mess = $this->modx->lexicon('modflowthrough.add_Contract_failed');
        		$this->modx->setPlaceholder('message_error',$mess);
        		return false;
        
        	}else{
        
        		$mess = $this->modx->lexicon('modflowthrough.add_Contract_success');
        		$this->modx->setPlaceholder('message_success',$mess);
        
        	}
        	exit();
        	return true;
        
        } // end createNewContract
        




        And the appropriate part of the schema:



        <object class="ContractBudget" table="contract_budget" 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="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" />
        
        	<!-- a budget may only belong to one contract -->
        	<field key="contract_id" dbtype="int" precision="8" phptype="integer" null="false" index="index" />
        	<aggregate alias="Contract" class="Contract" local="contract_id" foreign="id" cardinality="many" owner="foreign" />
        
        </object>
        
        <object class="Contract" table="contract" 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_f1" dbtype="decimal" precision="12,2" phptype="float" null="false" />
        	<field key="start_balance_f2" 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="StatusFlag" class="StatusFlag" local="status_id" foreign="id" cardinality="one" owner="foreign" />
        	<aggregate alias="Location" class="Location" local="location_id" foreign="id" cardinality="one" owner="foreign" />
        	<aggregate alias="Client" class="Client" local="client_id" foreign="id" cardinality="one" owner="foreign" />
        	<aggregate alias="Employer" class="Employer" local="employer_id" foreign="id" cardinality="one" owner="foreign" />
        	<aggregate alias="Program" class="Program" local="program_id" foreign="id" cardinality="one" owner="foreign" />		
        
        	<!-- contracts may have many budgets -->
        	<composite alias="ContractBudget" class="ContractBudget" local="id" foreign="contract_id" cardinality="one" owner="local" />		
        
        </object>







        so after all that, my error *HAS* to be in the schema? Correct? everything works correctly and checks out except when it comes time to addMany... ?







          *** 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
          • 10487 MODX Staff
          • 1,535 Posts
          Looks to me like cardinality="one" needs to be cardinality="many" in your composite relationship for ContractBudget. You'll need to regenerate your model class files for the change to take effect.
            Garry Nutting
            Senior Developer
            MODX, LLC

            Email: [email protected]
            Twitter: @garryn
            Web: modx.com
            • 26503
            • 620 Posts
            Wow - thanks, that's got it. I was dead sure that was correct.

            I'll bet that means all the other key definitions are wrong.

            Looks like it's time to re-read the docs sad


            Quote from: garryn at Feb 26, 2014, 05:12 PM
            Looks to me like cardinality="one" needs to be cardinality="many" in your composite relationship for ContractBudget. You'll need to regenerate your model class files for the change to take effect.
              *** 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
              Good catch Gary -- I didn't see that.
                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