Hi All

I'm having problems modifying the following script, which is a module for Joomla/Virtuemart.

<?php
defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' ); 
/*
* Best selling Products module for VirtueMart
* @version $Id: mod_virtuemart_topten.php 617 2007-01-04 19:43:08Z soeren_nb $
* @package VirtueMart
* @subpackage modules
*
* @copyright (C) John Syben (john@webme.co.nz)
* Conversion to Mambo and the rest:
* 	@copyright (C) 2004-2005 Soeren Eberhardt
*
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
* VirtueMart is Free Software.
* VirtueMart comes with absolute no warranty.
*
* www.virtuemart.net
*----------------------------------------------------------------------
* This code creates a list of the bestselling products
* and displays it wherever you want
*----------------------------------------------------------------------
*/
global $mosConfig_absolute_path, $sess;

/* Load the virtuemart main parse code */
require_once( $mosConfig_absolute_path.'/components/com_virtuemart/virtuemart_parser.php' );

require_once(CLASSPATH.'ps_product.php');
$ps_product = new ps_product;

// change the number of items you wanna haved listed via module parameters
$num_topsellers = $params->get ('num_topsellers', 10);

$list  = "SELECT p.product_id, p.product_sales as sales, p.product_parent_id, p.product_name, c.category_id, c.category_flypage ";
$list .= "FROM #__{vm}_product p, #__{vm}_product_category_xref pc, #__{vm}_category c WHERE ";
$q = "p.product_publish='Y' AND ";
$q .= "pc.product_id = p.product_id AND ";
$q .= "pc.category_id = c.category_id AND ";
$q .= "p.product_sales > 0 ";
$q .= "GROUP BY p.product_id ";
$q .= "ORDER BY sales DESC, p.product_name ";
$list .= $q . " LIMIT 0, $num_topsellers "; 

$db = new ps_DB;
$db->query($list);

$tt_item=0;
$i = 0;
?>

<table border="0" cellpadding="0" cellspacing="0" width="100%">
<?php

  while ($db->next_record()) {
      if ($i == 0) {
          $sectioncolor = "sectiontableentry2";
          $i += 1;
      }
      else {
          $sectioncolor = "sectiontableentry1";
          $i -= 1;
      } 
      if( !$db->f('category_flypage') ) {
      	$flypage = ps_product::get_flypage( $db->f('product_id'));
      }
      else {
      	$flypage = $db->f('category_flypage');
      }
      $tt_item++;
      $pid = $db->f("product_parent_id") ? $db->f("product_parent_id") : $db->f("product_id");

  ?>
<tr class="<?php echo $sectioncolor ?>">
  <td width="15%"><?php printf("%02d", $tt_item); ?></td>
  <td width="85%">
    <a href="<?php  $sess->purl(URL . "index.php?page=shop.product_details&flypage=$flypage&product_id=" . $pid . "&category_id=" . $db->f("category_id")) ?>">
        <?php $db->p("product_name"); ?>
    </a>
  </td>
</tr>
<?php 
  } ?>
</table>

What I want to do is limit the number of characters returned in the line:

            <?php $db->p("product_name"); ?>

I've tried replacing it with something like this..

$prodname = $db->p("product_name");
$prodname1 = substr($prodname,0,5);  
echo $prodname1;

..and it returns the right product names, but doesnt limit the number of characters.

Weird thing is, if I use:

$prodname = "anytext";
$prodname1 = substr($prodname,0,5);  
echo $prodname1;

then it returns "anyte" - so I know my code is along the right lines.

Can anyone help me out with a solution?

    That's weird. My guess is that you have a typo error. Try:

    echo substr($db->p("product_name"), 0, 5);

      No joy with that either, it still returns the correct product names, but full names.

        No joy with that either, it still returns the correct product names, but full names.

        What is the code that you tested with, and its output?

        If your code is correct, you have discovered a bizarre bug with substr().

          This is the script in it's current state. <url removed>

          The output in question is the "Top Ten" module on the bottom left of the page.

          <?php
          defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' ); 
          /*
          * Best selling Products module for VirtueMart
          * @version $Id: mod_virtuemart_topten.php 617 2007-01-04 19:43:08Z soeren_nb $
          * @package VirtueMart
          * @subpackage modules
          *
          * @copyright (C) John Syben (john@webme.co.nz)
          * Conversion to Mambo and the rest:
          * 	@copyright (C) 2004-2005 Soeren Eberhardt
          *
          * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
          * VirtueMart is Free Software.
          * VirtueMart comes with absolute no warranty.
          *
          * www.virtuemart.net
          *----------------------------------------------------------------------
          * This code creates a list of the bestselling products
          * and displays it wherever you want
          *----------------------------------------------------------------------
          */
          global $mosConfig_absolute_path, $sess;
          
          /* Load the virtuemart main parse code */
          require_once( $mosConfig_absolute_path.'/components/com_virtuemart/virtuemart_parser.php' );
          
          require_once(CLASSPATH.'ps_product.php');
          $ps_product = new ps_product;
          
          // change the number of items you wanna haved listed via module parameters
          $num_topsellers = $params->get ('num_topsellers', 10);
          
          $list  = "SELECT p.product_id, p.product_sales as sales, p.product_parent_id, p.product_name, c.category_id, c.category_flypage ";
          $list .= "FROM #__{vm}_product p, #__{vm}_product_category_xref pc, #__{vm}_category c WHERE ";
          $q = "p.product_publish='Y' AND ";
          $q .= "pc.product_id = p.product_id AND ";
          $q .= "pc.category_id = c.category_id AND ";
          $q .= "p.product_sales > 0 ";
          $q .= "GROUP BY p.product_id ";
          $q .= "ORDER BY sales DESC, p.product_name ";
          $list .= $q . " LIMIT 0, $num_topsellers "; 
          
          $db = new ps_DB;
          $db->query($list);
          
          $tt_item=0;
          $i = 0;
          ?>
          
          <table border="0" cellpadding="0" cellspacing="0" width="100%">
          <?php
          
            while ($db->next_record()) {
                if ($i == 0) {
                    $sectioncolor = "sectiontableentry2";
                    $i += 1;
                }
                else {
                    $sectioncolor = "sectiontableentry1";
                    $i -= 1;
                } 
                if( !$db->f('category_flypage') ) {
                	$flypage = ps_product::get_flypage( $db->f('product_id'));
                }
                else {
                	$flypage = $db->f('category_flypage');
                }
                $tt_item++;
                $pid = $db->f("product_parent_id") ? $db->f("product_parent_id") : $db->f("product_id");
          
            ?>
          <tr class="<?php echo $sectioncolor ?>">
            <td width="15%"><?php printf("%02d", $tt_item); ?></td>
            <td width="85%">
              <a href="<?php  $sess->purl(URL . "index.php?page=shop.product_details&flypage=$flypage&product_id=" . $pid . "&category_id=" . $db->f("category_id")) ?>">
                  <?php echo substr($db->p("product_name"), 0, 5);  ?>
              </a>
            </td>
          </tr>
          <?php 
            } ?>
          </table>
          
          <!--Top 10 End-->
          

            Oh my, it looks correct to me. Okay, let's try another test. Instead of using substr(), use strtoupper(). What is the effect?

              strtoupper() isn't working either, letters do not change to uppercase.

                strtoupper() isn't working either, letters do not change to uppercase.

                Okay, that means that your code is probably at fault. It is unlikely (though possible) that the same bug applies to both substr() and strtoupper().

                I suggest finding the smallest and simplest script that demonstrates the error. For example, I might simplify it to:

                <?php
                defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );
                
                global $mosConfig_absolute_path, $sess;
                
                /* Load the virtuemart main parse code */
                require_once( $mosConfig_absolute_path.'/components/com_virtuemart/virtuemart_parser.php' );
                
                require_once(CLASSPATH.'ps_product.php');
                $ps_product = new ps_product;
                
                // change the number of items you wanna haved listed via module parameters
                $num_topsellers = $params->get('num_topsellers', 10);
                
                $query = "SELECT p.product_id, p.product_sales as sales, p.product_parent_id, p.product_name, c.category_id, c.category_flypage
                          FROM #__{vm}_product p, #__{vm}_product_category_xref pc, #__{vm}_category c
                          WHERE p.product_publish='Y'
                              AND pc.product_id = p.product_id
                              AND pc.category_id = c.category_id
                              AND p.product_sales > 0
                          GROUP BY p.product_id
                          ORDER BY sales DESC, p.product_name
                          LIMIT 0, $num_topsellers";
                
                $db = new ps_DB;
                $db->query($query);
                
                while ($db->next_record()) {
                    echo htmlspecialchars(substr($db->p("product_name"), 0, 5)) . '<br />';
                }
                ?>

                  The code you just posted results in the same error still.

                    Then simplify it further. I have no way to test this myself. If you can post a script that can be tested by others, that's even better.

                      I'm sorry, I do apoligse.

                      My level of PHP is way, way below other areas of my knowledge (CSS/XHTML/Flash).

                      Would you be able to take a look if I gave you a temporary FTP account? If not, I understand.

                        Would you be able to take a look if I gave you a temporary FTP account? If not, I understand.

                        Unfortunately, I need to sleep very soon, and I would discourage such offers because they impose a security risk.

                          If I were you I would use Joomla's DB class and just re-write it myself.

                          
                          //If inside a function you need global database
                          global $database;
                          
                          $query = "SELECT p.product_id, p.product_sales as sales, p.product_parent_id, p.product_name, c.category_id, c.category_flypage
                                    FROM #__{vm}_product p, #__{vm}_product_category_xref pc, #__{vm}_category c
                                    WHERE p.product_publish='Y'
                                        AND pc.product_id = p.product_id
                                        AND pc.category_id = c.category_id
                                        AND p.product_sales > 0
                                    GROUP BY p.product_id
                                    ORDER BY sales DESC, p.product_name
                                    LIMIT 0, $num_topsellers";
                          
                          $database->setQuery($query);
                          $database->loadObjectList($products);
                          
                          while ($products as $p) {
                              echo htmlspecialchars(substr($p->product_name, 0, 5)) . '<br />';
                          }
                          
                          
                            Write a Reply...