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

    Thanks to BobRay's excellent tutorial, I've built a small package to store shipping estimates to the database.
    The package has 3 custom tables: quotes_customers, quotes_requests and quotes_processed. I've also built two snippets to interact with the package. The first snippet stores user-submitted estimate requests into the quotes_customer and quotes_request tables. The second stores estimate processed into the quotes_processed table. The first portion is easy stuff. The user-submitted quote request is saved to the database like this:
    if (isset($_POST['submit'])) {
      $customer = $modx->newObject('quoteCustomer', $customer_fields);//name, email, phone
      $request    = $modx->newObject('quoteRequest', $request_fields);// itinerary,shipping details
      $request>addOne($customer);
      if ($request->save()) {
        // Send report via Formit
        $params = array(
        'hooks' => $hooks,
        'emailSubject' => $emailSubject,
        'emailTpl' => $emailTpl,
        'emailTo' => $emailTo,
        'emailReplyTo' => $emailReplyTo,
        'emailReplyToName' => $emailReplyToName,
        'redirectTo' => $redirectTo,
        'store' => $store,
        'validate' => $validate
        );
        $output = $modx->runSnippet('Formit', $params);
        
      } else {
        $output = "An error occurred while saving the quote request.";
      }
      
    } else {
      // Display the form before submission
      $output = $modx->getChunk($tpl);
    }
    return $output;
    
    I'm having a little struggle with the next step. I could definitely use some help here.

    Once the quote request is saved, the next step is to create an estimate, save it and send an email to the user using the second snippet. I can easily get the quoteCustomer and quoteRequest objects. My struggle is: how to get those two objects, update them if necessary while also creating a third related quoteProcess object (which stores processed estimates).

    Here's my logic. It's failing at creating the relationship between the quoteCustomer and quoteProcess tables:
    // Save quote and send email report    
        if (isset($_POST['submit'])) {
          // Form has been submitted
    
         // submissionId is supplied via url
            $request = $modx->getObject('quoteRequest', array(
            'submissionid' => $submissionId
            ));
          $process = $modx->newObject('quoteProcess', $process_fields);
          $customer = $modx->getObject('quoteCustomer', $customerId);      
          $process->addOne($request);
          $process->addOne($customer);
          
          if ($process->save()) {
            // Quote saved successfully. Send report via Formit
            $params = array(
            'hooks' => $hooks,
            'emailSubject' => $emailSubject,
            'emailTpl' => $emailTpl,
            'emailTo' => $emailTo,
            'emailReplyTo' => $emailReplyTo,
            'emailReplyToName' => $emailReplyToName,
            'redirectTo' => $redirectTo,
            'store' => $store,
            'validate' => $validate
            );
            $output = $modx->runSnippet('Formit', $params);
          } else {
            // Quote save failed. Show error.
            $output = $modx->getChunk('tplQuotesError', array(
            'content' => 'An error occurred while saving the quote.'
            ));
            return $output;
          }
          
        } else {
          // Display the form before submission
          $output = $modx->getChunk($tpl, $request->toArray());
        }
      } else {
        // No submission ID supplied
        // Display a blank form, save the quote and 
        // send email report via Formit
       ....
    }
    

    Finally, the table relationships are defined like this:

    quoteCustomer => quoteRequest [ONE=>MANY]
    quoteCusomter => quoteProcess [ONE => MANY]
    quoteRequest => quoteProcess [ONE => MANY]

    I'd appreciate any help.

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

      A MODx Fanatic
      • 4172
      • 5,888 Posts
      what's your xpdo-schema?
        -------------------------------

        you can buy me a beer, if you like MIGX

        http://webcmsolutions.de/migx.html

        Thanks!
        • 30585
        • 833 Posts
        @Bruno17. Thanks for the quick follow-up.

        Here's the schema:

        <?xml version="1.0" encoding="UTF-8"?>
        <model package="quotes" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" version="1.1">
        	<!-- This extends modUser and adds the relations into the extended class. This way we don't need to modify the MODX schema. -->
        	<object class="extUser" extends="modUser">
        		<composite alias="bookedBy" class="quoteBooking" local="id" foreign="bookedby" cardinality="one" owner="local" />
        	</object>
        	<object class="quoteCustomer" table="quotes_customers" extends="xPDOSimpleObject">
        		<field key="firstname" dbtype="varchar" precision="100" phptype="string" null="false" default="" />
        		<field key="lastname" dbtype="varchar" precision="100" phptype="string" null="false" default="" />
        		<field key="email" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        		<field key="phone" dbtype="varchar" precision="100" phptype="string" null="false" default="" />
        		<field key="company" dbtype="varchar" precision="100" phptype="string" null="false" default="" />
        		<field key="website" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        
        		<composite alias="Request" class="quoteRequest" local="id" foreign="customer" cardinality="many" owner="local" />
        		<composite alias="Process" class="quoteProcess" local="id" foreign="customer" cardinality="many" owner="local" />
        		<composite alias="Booking" class="quoteBooking" local="id" foreign="customer" cardinality="many" owner="local" />
        	</object>
        	<object class="quoteRequest" table="quotes_requests" extends="xPDOSimpleObject">
        		<field key="customer" dbtype="int" precision="10" phptype="integer" null="false" default="0" />
        		<field key="movingdate" dbtype="int" precision="11" phptype="integer" null="false" default="0" />
        		<field key="movingtime" dbtype="char" precision="11" phptype="string" null="false" default="" />
        		<field key="streetnumber_pickup" dbtype="varchar" precision="25" phptype="string" null="false" default="" />
        		<field key="streetname_pickup" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        		<field key="unit_pickup" dbtype="char" precision="10" phptype="string" null="false" default="" />
        		<field key="country_pickup" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        		<field key="city_pickup" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        		<field key="province_pickup" dbtype="varchar" precision="25" phptype="string" null="false" default="" />
        		<field key="postalcode_pickup" dbtype="varchar" precision="25" phptype="string" null="false" default="" />
        		<field key="homesize_pickup" dbtype="varchar" precision="25" phptype="string" null="false" default="" />
        		<field key="hometype_pickup" dbtype="varchar" precision="25" phptype="string" null="false" default="" />
        		<field key="floor_pickup" dbtype="varchar" precision="10" phptype="string" null="false" default="" />
        		<field key="flooraccess_pickup" dbtype="varchar" precision="11" phptype="string" null="false" default="" />
        
        		<field key="streetnumber_dropoff" dbtype="varchar" precision="25" phptype="string" null="false" default="" />
        		<field key="streetname_dropoff" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        		<field key="unit_dropoff" dbtype="char" precision="10" phptype="string" null="false" default="" />
        		<field key="country_dropoff" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        		<field key="city_dropoff" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        		<field key="province_dropoff" dbtype="varchar" precision="25" phptype="string" null="false" default="" />
        		<field key="postalcode_dropoff" dbtype="varchar" precision="25" phptype="string" null="false" default="" />
        		<field key="homesize_dropoff" dbtype="varchar" precision="25" phptype="string" null="false" default="" />
        		<field key="hometype_dropoff" dbtype="varchar" precision="25" phptype="string" null="false" default="" />
        		<field key="floor_dropoff" dbtype="varchar" precision="10" phptype="string" null="false" default="" />
        		<field key="flooraccess_dropoff" dbtype="varchar" precision="11" phptype="string" null="false" default="" />
        		<field key="contentlist" dbtype="text" phptype="string" null="false" default="" />
        
        		<field key="comment" dbtype="text" phptype="string" null="false" default="" />
        		<field key="ip" dbtype="varchar" precision="15" phptype="string" null="false" default="" />
        		<field key="referrer" dbtype="varchar" precision="100" phptype="string" null="false" default="" />
        		<field key="refhost" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        		<field key="refquery" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        		<field key="refispaid" dbtype="char" precision="3" phptype="string" null="false" default="" />
        		<field key="submissiondate" dbtype="int" precision="10" phptype="integer" null="false" default="0" />
        		<field key="submissionid" dbtype="int" precision="10" phptype="integer" null="false" default="0" />
        		<field key="ismobile" dbtype="tinyint" precision="1" attributes="unsigned" phptype="boolean" null="false" default="0" index="index" />
        
        		<!-- ONE-TO-ONE: ...-->
        		<aggregate alias="Customer" class="quoteCustomer" local="customer" foreign="id" cardinality="one" owner="foreign" />
        		<!-- ONE-TO-MANY: ...-->
        		<composite alias="Process" class="quoteProcess" local="id" foreign="request" cardinality="many" owner="local" />
        		<composite alias="Booking" class="quoteBooking" local="id" foreign="request" cardinality="many" owner="local" />
        	</object>
        
        	<object class="quoteProcess" table="quotes_processed" extends="xPDOSimpleObject">
        		<field key="customer" dbtype="int" precision="10" phptype="integer" null="false" default="0" />
        		<field key="request" dbtype="int" precision="10" phptype="integer" null="false" default="0" />
        
        		<field key="load" dbtype="int" precision="3" phptype="integer" null="false" default="" />
        		<field key="drive" dbtype="int" precision="3" phptype="integer" null="false" default="" />
        		<field key="offload" dbtype="int" precision="3" phptype="integer" null="false" default="" />
        		<field key="travel" dbtype="int" precision="3" phptype="integer" null="false" default="" />
        		<field key="fuel" dbtype="int" precision="6" phptype="integer" null="false" default="" />
        		<field key="other" dbtype="int" precision="6" phptype="integer" null="false" default="" />
        		<field key="discount" dbtype="int" precision="3" phptype="integer" null="false" default="" />
        		<field key="firsthour" dbtype="int" precision="6" phptype="integer" null="false" default="" />
        		<field key="halfhour" dbtype="int" precision="6" phptype="integer" null="false" default="" />
        		<field key="crewsize" dbtype="int" precision="3" phptype="integer" null="false" default="" />
        		<field key="trucksize" dbtype="int" precision="3" phptype="integer" null="false" default="" />
        		<field key="optinsurance" dbtype="tinyint" precision="1" attributes="unsigned" phptype="boolean" null="false" default="0" index="index" />
        		<field key="comment" dbtype="text" phptype="string" null="false" default="" />
        		<field key="ip" dbtype="varchar" precision="15" phptype="string" null="false" default="" />
        		<field key="submissionid" dbtype="int" precision="10" phptype="integer" null="false" default="0" />
        
        		<index alias="optinsurance" name="optinsurance" primary="false" unique="false" type="BTREE" >
        			<column key="optinsurance" length="" collation="A" null="false" />
        		</index>
        
        		<!-- ONE-TO-ONE: ...-->
        		<aggregate alias="Customer" class="quoteCustomer" local="customer" foreign="id" cardinality="one" owner="foreign" />
        		<aggregate alias="Request" class="quoteRequest" local="request" foreign="id" cardinality="one" owner="foreign" />
        		<!-- ONE-TO-MANY: ...-->
        		<composite alias="Booking" class="quoteBooking" local="id" foreign="estimate" cardinality="many" owner="local" />
        	</object>
        
        	<object class="quoteBooking" table="quotes_bookings" extends="xPDOSimpleObject">
        		<field key="customer" dbtype="int" precision="10" phptype="integer" null="false" default="0" />
        		<field key="request" dbtype="int" precision="10" phptype="integer" null="false" default="0" />
        		<field key="estimate" dbtype="int" precision="10" phptype="integer" null="false" default="0" />
        		<field key="bookedby" dbtype="int" precision="10" phptype="integer" null="false" default="0" />
        		<field key="confirmation" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        		<field key="bookingdate" dbtype="int" precision="11" phptype="integer" null="false" default="0" />
        		<field key="spins" dbtype="text" phptype="string" null="false" default="" />
        
        		<aggregate alias="Request" class="quoteRequest" local="request" foreign="id" cardinality="one" owner="foreign" />
        		<aggregate alias="Process" class="quoteProcess" local="estimate" foreign="id" cardinality="one" owner="foreign" />
        		<aggregate alias="Customer" class="quoteCustomer" local="customer" foreign="id" cardinality="one" owner="foreign" />
        		<aggregate alias="bookedBy" class="modUser" local="bookedby" foreign="id" cardinality="one" owner="foreign" />
        	</object>
        </model>
        
          A MODx Fanatic
          • 4172
          • 5,888 Posts
          maybe something simple like that:

          <?php
          
          // Save quote and send email report
          if (isset($_POST['submit'])) {
              // Form has been submitted
          
              // submissionId is supplied via url
              $request = $modx->getObject('quoteRequest', array('submissionid' => $submissionId));
              $process = $modx->newObject('quoteProcess', $process_fields);
              $process->set('request',$request->get('id'));
              $process->set('customer',$request->get('customer'));
          
              if ($process->save()) {
          
              } else {
          
              }
          
          } else {
          
          }
          
            -------------------------------

            you can buy me a beer, if you like MIGX

            http://webcmsolutions.de/migx.html

            Thanks!
            • 30585
            • 833 Posts
            @Bruno17 thanks for the help. This looks pretty straightforward. Let me give it a try.
              A MODx Fanatic
              • 30585
              • 833 Posts
              @Bruno17 After playing around with the code, I can now create the quoteProcess object and save form values. My only issue is that it's assigning '1' to foreign key fields (customer, request) if i set those fields via a variable. when I explicitly specify a numeric value, the problem is solved. Any idea why?

              Here's the snippet in full (Minus the unecessary porttions)
              <?php
              
              // Default properties (Formit)
              // ===========================
              ...
              
              // Load class
              // ==========
              ...
              
                // Save quote request form data
                // Then send email reports with formit
                // ===================================
                
                $submissionId = $modx->getOption('submissionId', $scriptProperties, htmlspecialchars($_GET["submission"]));
                // submissionId is supplied via url
                $request      = $modx->getObject('quoteRequest', array('submissionid' => $submissionId));
                // Show error message if quote request is not found
                // with supplied submissionId     
                if (empty($request)) {
                  $output = $modx->getChunk('tplQuotesError', array('content' => 'Could not find Quote Request with ID: ' . $submissionId));
                  return $output;
                }
                // Get the related customer + assign placeholders
                $customer   = $request->getOne('Customer');
                $customerId = $customer->get('id');
                $firstname  = $customer->get('firstname');
                $lastname   = $customer->get('lastname');
                $email      = $customer->get('email');
                $phone      = $customer->get('phone');
                
                $modx->setPlaceholders(array(
                  'customerid' => $customerId,
                  'firstname' => $firstname,
                  'lastname' => $lastname,
                  'email' => $email,
                  'phone' => $phone
                ), 'eq.');  
                // Customer fields
                $customer_fields = array(
                'firstname' => isset($_POST['firstname']) && (!empty($_POST['firstname'])) ? $_POST['firstname'] : '',
                'lastname' => isset($_POST['lastname']) && (!empty($_POST['lastname'])) ? $_POST['lastname'] : '',
                'email' => isset($_POST['email']) && (!empty($_POST['email'])) ? $_POST['email'] : '',
                'phone' => isset($_POST['phone']) && (!empty($_POST['phone'])) ? $_POST['phone'] : ''
                );  
                // Quote request fields   => Will be used later. Not needed now.
                $request_fields = array(
                ...
                );
                // Quote process fields
                $process_fields = array(
                  'request' => $request->get('id'), // If I Change this to a number e.g.: 'request' => 32, the value is saved properly. Otherwise, it's saving '1' into that field.
                  'customer' => $customerId, // Same case as above.
                  ...       
                );
                
                // Ceate quote and send reports
                // ============================
                
                if (isset($_POST['submit'])) {
                  // Form has been submitted 
                  $process = $modx->newObject('quoteProcess', $process_fields);
                  if ($process->save()) {
                    // Send report via Formit
                    $params = array(
                    ...
                    );
                    $output = $modx->runSnippet('Formit', $params);
                    
                  } else {
                    $output = "An error occurred while saving the quote request.";
                  }
                  
                } else {
                  // Not a repost, just display the form 
                  // Replace placeholders with existing request values
                  $output = $modx->getChunk($tpl, $request->toArray());
                }
                return $output;
              
                A MODx Fanatic
                • 4172
                • 5,888 Posts
                do you get the correct values by debugging like:

                  $process_fields = array(
                    'request' => $request->get('id'), // If I Change this to a number e.g.: 'request' => 32, the value is saved properly. Otherwise, it's saving '1' into that field.
                    'customer' => $customerId, // Same case as above.
                          
                  );
                print_r($process_fields);
                die();
                  -------------------------------

                  you can buy me a beer, if you like MIGX

                  http://webcmsolutions.de/migx.html

                  Thanks!
                  • 30585
                  • 833 Posts
                  Yes. I'm getting array of values starting with:
                  Array ( [request] => 30 [customer] => 32.

                    A MODx Fanatic
                    • 4172
                    • 5,888 Posts
                    you can also try:

                        $process = $modx->newObject('quoteProcess');
                        $process->fromArray($process_fields);
                        if ($process->save()) {
                          // Send report via Formit
                          $params = array(
                          ...
                          );
                          $output = $modx->runSnippet('Formit', $params);
                           
                        } else {
                          $output = "An error occurred while saving the quote request.";
                        }
                      -------------------------------

                      you can buy me a beer, if you like MIGX

                      http://webcmsolutions.de/migx.html

                      Thanks!
                      • 30585
                      • 833 Posts
                      @Romain17. Thanks again. Believe it or not, that too didn't give. I even went back to the schema file and removed the zeros defaults for both fields. Still nothing. This is rather odd.
                        A MODx Fanatic