We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 6902
    • 126 Posts
    I am drawing a blank here... I’m not sure what I’m doing wrong, and I’m hoping someone can set me straight.

    The Scenario:
    --We have a database with listings for thousands of images (I already have a working snippet/page for searching through the database).
    --I am trying to create a snippet that will allow us to insert images from the database into any page (that will link back to the detailed database entry).
    --The snippet is supposed to take a serial number (and other optional parameters) and return the HTML for a linked image.
    --Within the snippet, I am using PDO to connect to the database.
    --The snippet call looks like this: [[!pli_image? &serial=`12345`]]

    The Problem:
    --The first call to my snippet on a page works fine... any other calls, as far as I can tell, run, but don’t connect to the database (thus, returning no results).
    --Also... any snippet calls in the template will load once, and then stop processing until I clear the site cache.
    --So, in my template head I have [[load_footer]] (a custom javascript file). In the content I call [[pli_image]] ... the first pli_image loads, the others return data, but anything pulled via PDO is empty. After the first load, [[load_footer]] stops working (along with any other snippets in the template).

    More (related?) Details:
    --I have all of my javascript and css loading through snippets. For example [[load_mootools]] loads the mootools javascripts. I did it this way so that I can make calls to whatever head elements are necessary for a given tool (which could appear in different combinations on different pages) without things possibly getting loaded multiple times (which tends to break them). Not 100% sure if this is good ModX practice.

    Any help would be much appreciated! What am I doing wrong here?!

    Thanks!

    *EDIT: This is on Revo Beta 5
      • 3749
      • 24,544 Posts
      Can you post the snippet code for the two snippets? It’s hard to know what’s happening without seeing it.
        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
        • 22303 MODX Staff
        • 10,725 Posts
        MODx Revolution already creates a connection to the database via PDO. How are you doing this? You creating a new instance of PDO manually?

        Posting the code would definitely help.
          • 6902
          • 126 Posts
          Ok - here’s the snippet. This is meant to be called multiple times on a page.
          <?php
          // load necessary modules
          $modx->runSnippet('load_mootools');
          $modx->runSnippet('load_squeezebox');
          
          $output = '';
          
          // generate paths
          $assets = $modx->getOption('base_url').'assets/';
          $pl_url = $assets.'photolab/';
          $pl_path = $modx->getOption('base_path').'assets/photolab/';
          
          // include image code
          // (moved to external file for easier editing)
          require($pl_path.'processors/image.inc.php');
          
          return $output;
          ?>


          And here is the code from the file (image.inc.php)...

          <?php
          
          	// include necessary functions & libraries
          	require_once($pl_path.'config.inc.php');
          	require_once($pl_path.'functions/filereader.func.php');
          	require_once($pl_path.'functions/photopath.func.php');
          
          	//#############################################################################################
          	// DATEBASE QUERIES
          	//#############################################################################################
          	
          	if ( isset($serial) ) {  //<--- make sure there's something to look up
          			
          		// connect to the database
          		try {
          			$dbh = new PDO("mysql:host=$SQL_HOST;dbname=$SQL_DB", $SQL_USER, $SQL_PASS, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false));
          		} catch (PDOException $e) {}
          		
          		
          		// CREATE QUERY TO PULL IMAGE INFO
          		// --------------------------------------------------------------
          		// selects
          		$sql = 'SELECT img.image_serial, eve.event_name ';
          		
          		// search main table
          		$sql.= 'FROM pl_images AS img ';
          		
          		 // join event table
          		$sql.= 'LEFT JOIN pl_events AS eve ON img.image_event = eve.event_id ';
          		
          		// where clauses
          		$sql.= 'WHERE img.image_serial=? ';
          		$sql.= 'AND img.image_active=1 ';
          		
          		// limit (just in case!)
          		$sql.= 'LIMIT 1 ';
          		
          		
          		// RUN QUERY
          		// --------------------------------------------------------------
          		$stmt = $dbh->prepare($sql);
          		$stmt->bindParam(1, $serial, PDO::PARAM_STR);
          		$stmt->execute();
          		$row = $stmt->fetch(PDO::FETCH_ASSOC);
          		
          		// close database connection;
          		$dbh = NULL;
          	
          	}
          	
          	
          	//#############################################################################################
          	// TEST AND SET OPTIONAL PARAMETERS
          	//#############################################################################################
          	
          	// test for width setting - default is 250
          	$myWidth = (isset($width)) ? (int)$width : 250;
          	// minimum width is 75
          	$myWidth = ($myWidth < 75) ? 75 : $myWidth;
          	// maximum width is 736
          	$myWidth = ($myWidth > 736) ? 736 : $myWidth;
          	
          	// select image type based on image size
          	if ($myWidth == 75) {
          		$type = 'thumb';
          	} elseif ($myWidth <= 300) {
          		$type = 'web';
          	} else {
          		$type = 'small';
          	} 
          	
          	// test for float setting - default is left
          	if (isset($float)) {
          		$myFloat = ($float=='left' || $float=='') ? 'float_left' : ($float=='right') ? 'float_right' : '';
          	} else {
          		$myFloat = 'float_left';
          	}
          	
          	// generate width string
          	$widthString = 'width: '.$myWidth.'px;';
          	
          	//#############################################################################################
          	// GENERATE DETAIL PAGE
          	//#############################################################################################
          	
          	if ($row['image_serial'] != NULL) { //<--- for non-empty result
          		
          		// generate image URL
          		$dispUrl = photoPath($row['image_serial'], $type, $pl_url);
          		
          		// generate link to detail popup
          		$vars = 'serial='.$serial;
          		$detailUrl = $modx->makeUrl($DETAIL_PAGE, '', $vars);
          		
          		// read in the image link template
          		$image_tpl = get_file_contents($pl_path.'templates/image.tpl.html');
          	
          		// inject content
          		$placeholders = array('[[+pli_img]]', '[[+pli_link]]', '[[+pli_title]]', '[[+pli_class]]', '[[+pli_style]]', '[[+pli_caption]]');
          		$values = array($dispUrl, $detailUrl, $row['event_name'], $myFloat, $widthString, $caption);
          		
          		$output = str_replace($placeholders, $values, $image_tpl);
          		
          		
          	} else { //<-- for empty result
          		
          		$output = '';
          				
          	}
          	
          	if ($debug) {
          		$output .= '<div style="background: #a00; color: #fff; padding: 20px;">';
          		$output .= "Serial: <strong>$serial</strong><br/>";
          		$output .= "SQL: <strong>$sql</strong><br/>";
          		$output .= "Result: <strong>".serialize($row)."</strong><br />";
          		$output .= "Float In: <strong>$float</strong><br/>";
          		$output .= "Width In: <strong>$width</strong><br/>";
          		$output .= "Caption In: <strong>$caption</strong><br/>";
          		$output .= "Type: <strong>$type</strong><br/>";
          		$output .= "URL: <strong>$dispUrl</strong><br/>";
          		$output .= "Detail: <strong>$detailUrl</strong><br/>";
          		$output .= "Float Out: <strong>$myFloat</strong><br/>";
          		$output .= "Width Out: <strong>$myWidth</strong><br/>";
          		$output .= "Width String: <strong>$widthString</strong>";
          		$output .= '</div>';
          	}
          	
          ?>


          As stated above. The first image works fine. Here’s an example of the debug dump from subsequent images:
          Serial: c6696-36a
          SQL: SELECT img.image_serial, eve.event_name FROM pl_images AS img LEFT JOIN pl_events AS eve ON img.image_event = eve.event_id WHERE img.image_serial=? AND img.image_active=1 LIMIT 1
          Result: b:0;
          Float In: left
          Width In: 100
          Caption In: TESTING 3
          Type: web
          URL:
          Detail:
          Float Out: float_right
          Width Out: 100
          Width String: width: 100px;

          From the above input, it seems that the call to the database is what’s breaking...

          Thanks for taking a look at it! smiley
            • 22303 MODX Staff
            • 10,725 Posts
            First of all, running that multiple times per page will create as many database connections as you are executing it; that’s bad. You want to reuse the same connection, so don’t close it and make sure you only get once instance of it for running all of these.
              • 6902
              • 126 Posts
              I’m not exactly sure how to accomplish something like that and still keep the backend easy to code (for our not-really-programmers web folks). There might be 10 images on a page on the outside. So, multiple database calls may not be too terrible of an issue. Of course, I’m totally open to suggestions or ideas.

              Here’s what I’m wanting to be able to do in the content area. The idea is to just use the snippet instead of an image tag so that the photo links back to our photo archive.

              <p>
              [[!pl_image? &serial=`D9081-6` &caption=`Main Image`]]
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit.
              </p>
              
              <p>
              [[!pl_image? &serial=`9347-30` &width=`150` &caption=`Secondary image` &float=`right`]]
              Ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt.
              </p>

                • 22303 MODX Staff
                • 10,725 Posts
                The best way is to make the script a class that you can instantiate once and then save as a placeholder for reuse (or at least the external database connection, i.e. PDO instance). You can also use modX::getService() to instantiate such a class as a modX service, i.e. $modx->myComponent.
                  • 6902
                  • 126 Posts
                  Reading about ModX Services... sounds freakin’ awesome. Any tutorials or examples that you can point me to?
                    • 28215
                    • 4,149 Posts
                      shaun mccormick | bigcommerce mgr of software engineering, former modx co-architect | github | splittingred.com
                      • 6902
                      • 126 Posts
                      I don’t think I’m understanding this correctly...

                      I set up a very simple test case:

                      Snippet:
                      <?php
                      $modx->getService('stuff', 'MyStuff', '/path/to/file/test.class.php');
                      return $modx->stuff->functionTest('Hello World!');
                      ?>


                      File:
                      <?php
                      class MyStuff {
                      	public function test ($string) {
                      		return '<hr/><strong>'.$string.'</strong><hr/>';
                      	}
                      }
                      ?>


                      Returns the following:
                      Fatal error: Call to a member function test() on a non-object in /our/path/core/model/modx/modscript.class.php(89) : eval()’d code on line 7