We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 11055 ☆ A M B ☆
    • 3,112 Posts
    I dug the xPDO docs and codes, and I couldn’t find any reference that related to this searching type.
    I’m using a custom table.

    For now on, I use some ’deprecated’ methods like this:
    <?php
            $queryString = "
                SELECT *, MATCH(title, url, author, category, level, version, tag, language, summary) AGAINST ('{$str}' IN BOOLEAN MODE) as score
                FROM {$this->modx->config['table_prefix']}linx
                WHERE MATCH(title, url, author, category, level, version, tag, language, summary) AGAINST ('{$str}' IN BOOLEAN MODE)
                ORDER BY score DESC
                ";
            $result = $this->modx->db->query($queryString);
    
            if (!$result) {
                echo __LINE__ . ' : #' . mysql_errno() . ' ' . mysql_error() . '<br />' . $queryString . '<br />';
                return FALSE;
            }
    
            $rowArray = $this->modx->db->makeArray($result);
    
    


    How to do it with xPDO?
    TIA.
      Rico
      Genius is one percent inspiration and ninety-nine percent perspiration. Thomas A. Edison
      MODx is great, but knowing how to use it well makes it perfect!

      www.virtudraft.com

      Security, security, security! | Indonesian MODx Forum | MODx Revo's cheatsheets | MODx Evo's cheatsheets

      Author of Easy 2 Gallery 1.4.x, PHPTidy, spieFeed, FileDownload R, Upload To Users CMP, Inherit Template TV, LexRating, ExerPlan, Lingua, virtuNewsletter, Grid Class Key, SmartTag, prevNext

      Maintainter/contributor of Babel

      Because it's hard to follow all topics on the forum, PING ME ON TWITTER @_goldsky if you need my help.
      • 22303 MODX Staff
      • 10,725 Posts
      NOTE: DO NOT use any mysql_ functions when working even with the deprecated DBAPI methods in Revolution—the DBAPI in Revolution uses xPDO itself already.

      You can pass any SQL-specific functions or statements, like MySQL fulltext query syntax, into any criteria, or you can simply do what you did using the PDO API, which again, is built into xPDO, and thus MODx. That said, there are still a lot of different ways to accomplish this with xPDO. Let’s start with the one closest to how you are used to doing it:
      <?php
      $queryString = "
          SELECT *, MATCH(title, url, author, category, level, version, tag, language, summary) AGAINST (:str1 IN BOOLEAN MODE) as score
          FROM {$this->modx->getOption('table_prefix')}linx
          WHERE MATCH(title, url, author, category, level, version, tag, language, summary) AGAINST (:str2 IN BOOLEAN MODE)
          ORDER BY score DESC
          ";
      $criteria = new xPDOCriteria($this->modx, $queryString, array(':str1' => $str, ':str2' => $str));
      if (!$criteria->prepare() || !$criteria->stmt->execute()) {
          echo __LINE__ . ' : ' . print_r($this->modx->errorInfo(), true) . '<br />' . $queryString . '<br />';
          return FALSE;
      }
      $rowArray = $criteria->stmt->fetchAll(PDO::FETCH_ASSOC);
      


      However, if you created an xPDO model for your linx table, you could create the criteria programmatically via a gsLinx class, e.g.
      <?php
      $criteria = $this->modx->newQuery('gsLinx');
      $criteria->select($this->modx->getSelectColumns('gsLinx'));
      $criteria->select("MATCH(title, url, author, category, level, version, tag, language, summary) AGAINST (:str1 IN BOOLEAN MODE) AS score");
      $criteria->where("MATCH(title, url, author, category, level, version, tag, language, summary) AGAINST (:str2 IN BOOLEAN MODE)");
      $criteria->sortby('score', 'DESC');
      $stmt = $criteria->prepare();
      $stmt->bindParam(':str1', $str);
      $stmt->bindParam(':str2', $str);
      

      At this point, you have a PDOStatement (the $stmt variable) wrapped by an xPDOCriteria object (the $criteria variable); note that $stmt is a reference to $criteria->stmt which is automatically assigned when you call prepare. You can make use of either one at this point in any way you want. For instance, if you just wanted an array result set like you had before:
      <?php
      if ($criteria->stmt->execute()) {
          $rowArray = $criteria->stmt->fetchAll(PDO::FETCH_ASSOC);
      } else {
          var_dump($criteria->stmt->errorInfo());
      }
      

      Or if you want to work with your rows as objects:
      <?php
      $collection = $this->modx->getCollection('gsLinx', $criteria);
      $output = array();
      foreach ($collection as $object) {
          $output[]= $object->toArray();
      }
      return implode("<br />", $output);
      
        • 11055 ☆ A M B ☆
        • 3,112 Posts
        TYVM for your answer, Jason.
        I agree 101% that I should keep away from mysql_ functions, but again, I was showing the dirty query to explain what I was trying to do.
        Your answer sheds me a light. smiley

        Anyhow,
        I tried the first option, it works.
        While I want to use the second option to keep the consistency of all passing properties among methods, it throws this:

        [2011-02-18 12:47:23] (ERROR @ D:\localhost\[mywebsite.com]\core\xpdo\om\xpdoobject.class.php : 235) PHP warning: PDOStatement::execute() [<a href=’pdostatement.execute’>pdostatement.execute</a>]: SQLSTATE[HY093]: Invalid parameter number: no parameters were bound
        [2011-02-18 12:47:23] (ERROR @ /[mywebsite.com]/www/index.php) Error HY093 executing statement:
        Array
        (
        [0] => HY093
        )
        What am I missing here?

        PS:
        There was a similar problem here: http://modxcms.com/forums/index.php?topic=60005.0
          Rico
          Genius is one percent inspiration and ninety-nine percent perspiration. Thomas A. Edison
          MODx is great, but knowing how to use it well makes it perfect!

          www.virtudraft.com

          Security, security, security! | Indonesian MODx Forum | MODx Revo's cheatsheets | MODx Evo's cheatsheets

          Author of Easy 2 Gallery 1.4.x, PHPTidy, spieFeed, FileDownload R, Upload To Users CMP, Inherit Template TV, LexRating, ExerPlan, Lingua, virtuNewsletter, Grid Class Key, SmartTag, prevNext

          Maintainter/contributor of Babel

          Because it's hard to follow all topics on the forum, PING ME ON TWITTER @_goldsky if you need my help.
          • 22303 MODX Staff
          • 10,725 Posts
          I updated the example to bind the parameters after the prepare()—that should resolve it if your model is properly created and included.
            • 11055 ☆ A M B ☆
            • 3,112 Posts
            it doesn't work.
            strangely, this works:
            <?php
                    if (!empty($str))
                        $this->searchString = $str;
            
                    ############################################################################
                    # Modified of Jason's:
                    # https://forums.modx.com/thread/31992/full-text-searching-using-match-against-in-xpdo#dis-post-172945
                    ############################################################################
                    $c = $this->modx->newQuery('Link');
                    $c->select($this->modx->getSelectColumns('Link'));
                    $fields = 'title, url, author, category, level, version, tag, language, summary';
                    $c->select("MATCH ($fields) AGAINST ('$this->searchString' IN BOOLEAN MODE) AS score");
                    $c->where("MATCH ($fields) AGAINST ('$this->searchString' IN BOOLEAN MODE)");
                    $c->where("approved='1'");
            
                    $this->_links['count'] = $this->modx->getCount('Link', $c);
                    
                    $c->sortby("score", "DESC");
            
                    if (!empty($limit)) {
                        $this->_links['limit'] = intval($limit);
                    } else {
                        $this->_links['limit'] = $this->config['limit'];
                    }
            
                    $c->limit($this->_links['limit'], $this->_links['limit'] * $this->config['p']);
            
                    $links = $this->modx->getCollection('Link', $c);
            
                    foreach ($links as $link) {
                        // ... filling the placeholders here
            
                    }
            


            Notice the single quotes that wrap $this->searchString
            PS:
            1. The getCount() was retrieved BEFORE the limit and sortby (You only mentioned about limit on the Doc).
            2. This $this->searchString property will be used again for the pagination method... as below
                   
            <?php
                    if (empty($this->searchString))
                        return FALSE;
                    $pages = array();
            
                    if (!isset($this->_links['count'])) {
                        $c = $this->modx->newQuery('Link');
                        $c->select('COUNT(DISTINCT id)');
                        $c->select("MATCH(title, url, author, category, level, version, tag, language, summary) AGAINST (:str1 IN BOOLEAN MODE) AS score");
                        $c->where("MATCH(title, url, author, category, level, version, tag, language, summary) AGAINST (:str2 IN BOOLEAN MODE)");
                        $c->where("approved='1'");
                        $c->sortby("score", "DESC");
            
                        $stmt = $c->prepare(array(':str1' => $this->searchString, ':str2' => $this->searchString));
            
                        $this->_links['count'] = 0;
                        if ($c->stmt->execute()) {
                            $rows = $c->stmt->fetchAll(PDO::FETCH_COLUMN);
                            $this->_links['count'] = (integer) reset($rows);
                        }
                    }
            
                    if ($this->_links['count'] <= $this->_links['limit'])
                        return FALSE;
            

            This pagination uses array, not object. [ed. note: goldsky last edited this post 14 years, 9 months ago.]
              Rico
              Genius is one percent inspiration and ninety-nine percent perspiration. Thomas A. Edison
              MODx is great, but knowing how to use it well makes it perfect!

              www.virtudraft.com

              Security, security, security! | Indonesian MODx Forum | MODx Revo's cheatsheets | MODx Evo's cheatsheets

              Author of Easy 2 Gallery 1.4.x, PHPTidy, spieFeed, FileDownload R, Upload To Users CMP, Inherit Template TV, LexRating, ExerPlan, Lingua, virtuNewsletter, Grid Class Key, SmartTag, prevNext

              Maintainter/contributor of Babel

              Because it's hard to follow all topics on the forum, PING ME ON TWITTER @_goldsky if you need my help.
              • 22303 MODX Staff
              • 10,725 Posts
              These things I exemplified (these were obviously not working, tested examples, since I don’t have access to your model or know the code involved until you reveal it) work fine in various implementations in my custom xPDO models, including MODX. I’m not sure what you are claiming doesn’t work, but ok... tongue
                • 33968
                • 863 Posts
                Just wanted to say that I found this post really useful - saved me plenty of headaches tongue

                A quick question with regards to this:
                $criteria = $this->modx->newQuery('gsLinx');
                $criteria->select($this->modx->getSelectColumns('gsLinx'));
                $criteria->select("MATCH(title, etc...) AGAINST (:str1 IN BOOLEAN MODE) AS score");
                $criteria->where("MATCH(title, etc...) AGAINST (:str2)");
                $criteria->sortby('score', 'DESC');
                $stmt = $criteria->prepare();
                $stmt->bindParam(':str1', $str);
                $stmt->bindParam(':str2', $str);
                
                $collection = $this->modx->getCollection('gsLinx', $criteria);
                


                I couldn't get it to work using $stmt->bindParam(); - I didn't understand how $stmt fits in with the getCollection call, so ended up doing this instead (simplified to get the idea across):
                $c = $modx->newQuery('myPackage');
                $c->select($modx->getSelectColumns('myPackage'));
                $c->where("MATCH (col_1, col_2) AGAINST ('$query')");
                
                $collection = $modx->getCollection('myPackage', $c);
                

                Do I miss out on any caching or any advantages by not using bindParam?