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

    I’m trying to understand how to work with external tables in my snippets. I have created a schema and generated a package from that. I also have the mysql tables in place and what I can see, everything works so far. Now, i’m trying to create a snippet that will act as a hook for FormIt and save form data into my db tables. I will also do some further processing with the data and wan’t to have a base class with some helper functions.

    Here is my snippet code so far:
    <?php
    /**
    * @package entry
    */
      require_once $modx->getOption('entry.core_path',null,$modx->getOption('core_path').'components/entry/').'model/entry/entry.class.php';
      $ent = new Entry($modx,$scriptProperties);
      if (!($ent instanceof Entry)) {
        $modx->log(modX::LOG_LEVEL_ERROR,'[Entry] Could not load Entry class.');
        return false;
      }
      
      $competitorid =& $modx->user->id;
      
      $entrant = $modx->newObject('eResults');
      
      $fields = $hook->getValues();
      $tshirtsize = $fields['resultsThirtSize'][0];
    
      $entrant->fromArray(array(
        'competitorid' => $competitorid,
        'tshirtsize' => $tshirtsize,
        'lastmodified' => $_SERVER['REQUEST_TIME'],
        'timeregistered' => $_SERVER['REQUEST_TIME'],
      ));
     
      $entrant->save();
    
    return true;
    ?>


    And here is my base class:
    <?php
    /**
     * Entry
     *
     * Copyright 2011 by Kristoffer Karlström <[email protected]>
     *
     * @package entry
     */
    class Entry {
    	/**
    	 * Creates an instance of the Entry class.
    	 *
    	 * @param modX &$modx A reference to the modX instance.
    	 * @param array $config An array of configuration parameters.
    	 * @return Entry
       */
    	function __construct(modX &$modx,array $config = array()) {
    		$this->modx =& $modx;
    
    		 /* allows you to set paths in different environments
    			* this allows for easier SVN management of files
    			*/
    		$corePath = $this->modx->getOption('entry.core_path',null,MODX_CORE_PATH.'components/entry/');
    
    		/* loads some default paths for easier management */
    		$this->config = array_merge(array(
    			'corePath' => $corePath,
    			'modelPath' => $corePath.'model/',
    
    		),$config);
    
    		$this->modx->addPackage('entry',$this->config['modelPath']);
    	}
    }
    ?>


    When i’m trying to run the snippet, I get an error stating Call to a member function fromArray() on a non-object in ... pointing to this line in my snippet: $entrant = $modx->newObject(’eResults’);
    I’m also getting this input in the modx error log: (ERROR @ /index.php) Could not load class: eResults from mysql.eresults.
    I won’t get my own error message in the error log som my Entry class should be loaded, and the package should then also be loaded, right? But I can’t use any xpdo functions on my package.


    Now to my big confusion. If i’m changing my snippet code to not load the base class, everything works. Here is my working snippet:
    <?php
    /**
    * @package entry
    */
      $modx->addPackage('entry',$modx->getOption('core_path').'components/entry/model/');
      
      $competitorid =& $modx->user->id;
      
      $entrant = $modx->newObject('eResults');
      
      $fields = $hook->getValues();
      $tshirtsize = $fields['resultsThirtSize'][0];
    
      $entrant->fromArray(array(
        'competitorid' => $competitorid,
        'tshirtsize' => $tshirtsize,
        'lastmodified' => $_SERVER['REQUEST_TIME'],
        'timeregistered' => $_SERVER['REQUEST_TIME'],
      ));
     
      $entrant->save();
    
    return true;
    ?>



    What am I doing wrong?

    I’m attaching my schema file and a screenshot of my package folder structure.

    // Kristoffer
      • 3749
      • 24,544 Posts
      Are your tables inside the MODx DB? They need to be for the xPDO functions to work on them.

      Always check the return value of loadPackage() and the return value of newObject();

      loadPackage will return false if it fails.

      This will test the result of newObject():

      if (is_object($entrant) && ($entrant instanceof xPDOObject) ) {
          /* Object is OK, go ahead and process it */
      } else {
         /* Error */
      }


      That should give you more information about where things are going wrong.

      This will let you create a schema from an existing table (in the MODx DB):
      http://www.bobsguides.com/custom-db-tables.html

      Comparing the result with your schema may tell you something.
        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
        • 16348
        • 64 Posts
        Thank you BobRay for putting me on the right track.

        I’m using my snippet as a hook for FormIt. I have also used FormIt as a source of inspiration for the core of my snippet. The problem I had was caused by this.
        When FormIt calls the hook (my snippet), it sends it’s own config array as a parameter. I then merged this array with my own configs in the constructor of my base class. When I was using the same variable names for my paths as FormIt, my settings would be owerwritten by FormIt:s paths and I was then trying to load my package from the wrong path.
        I found this by outputting a lot of debug messages in the error messages.

        My solution was to remove the array_merge part in my base class constructor.


        An other opinion is that the kind of snippet thas is used in BobRay:s tutorial should be a native part of the manager.
          • 32699 ☆ A M B ☆
          • 427 Posts
          I apologize for not seeing this earlier. I have an entire section of my site dedicated to this topic:
          http://www.shawnwilkerson.com/xpdo/using-xpdo-across-tables/

          Hopefully, those finding this topic and needing more information will benefit from the link.


            Get your copy of MODX Revolution Building the Web Your Way http://www.sanitypress.com/books/modx-revolution-building-the-web-your-way.html

            Check out my MODX || xPDO resources here: http://www.shawnwilkerson.com
            • 3749
            • 24,544 Posts
            Quote from: wshawn at Feb 11, 2011, 11:58 AM

            I apologize for not seeing this earlier. I have an entire section of my site dedicated to this topic:
            http://www.shawnwilkerson.com/xpdo/using-xpdo-across-tables/

            Hopefully, those finding this topic and needing more information will benefit from the link.

            Nice stuff Shawn. cool

            I was surprised that you found getCollectionGraph() slower than separate queries. I had assumed that since gCG() did a single query, it would always be faster.
              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
              • 28042 ☆ A M B ☆
              • 24,524 Posts
              I was surprised that you found getCollectionGraph() slower than separate queries. I had assumed that since gCG() did a single query, it would always be faster.
              Not necessarily. If the single query produces a result set that PHP then needs to process, that PHP processing of a large result set could easily take longer than a few more specific queries would take.

              On the other hand, if a very complicated query is used to deliver pre-processed results, it can take more MySQL time to optimize the query than a set of simpler queries. Prepared statements or stored procedures might be interesting to try here. Most of a query’s overhead involves the MySQL engine deciding the best way to fetch the desired results; with prepared statements that only happens the first time the query is made; after that just the variable parts are plugged in to the already prepared optimized query.
                Studying MODX in the desert - http://sottwell.com
                Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
                Join the Slack Community - http://modx.org
                • 22303 MODX Staff
                • 10,725 Posts
                The only way it should be slower is if the relations are not properly indexed, or the iterations are very few. getCollectionGraph(), and all the xPDO object and object collection/iterator methods use prepared statements BTW.
                  • 28042 ☆ A M B ☆
                  • 24,524 Posts
                  I should have known better wink
                    Studying MODX in the desert - http://sottwell.com
                    Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
                    Join the Slack Community - http://modx.org