We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 4058
    • 17 Posts
    I have an interesting problem with multiple instances of the same snippet.

    I am getting the following error:

    Fatal error: Cannot redeclare class Csv2table in /home/content/59/6758359/html/clients/npca/core/cache/elements/modsnippet/8.include.cache.php on line 53


    I am using the getResources snippet to return multiple instances of the csv2table snippet on a single page. My chunk tpl for csv2table retrieves the value of a tv from each child resource. This value is simply the source to the csv file.

    Upon troubleshooting my issue, when I limit getResources to 1, it will retrieve the converted table and display it. When I go beyond 1 limit, say 2, it will return the above error. As the error above states, it’s a problem with re-declaring the class twice on one page. However, if I keep the limit at 2, go into my chunk tpl and replace the tv placeholder with the path to a csv file (which would return the same file twice) it works fine and displays both of my tables.

    This seems backwards to me because if it is in fact because of a class being re-declared, wouldn’t it return the error any time there are multiple instances? I don’t see why the same file source in multiple instances would work, but different file sources dont?

    I’m assuming that I need to modify something with the class code; however, I’m not sure the appropriate way to do so. I’m hoping someone here can review this snippet and provide a correction that would allow the class to be declared more than once.

    Here is the snippet code:

    <?php
    # csv2table 0.1 - Converts CSV to HTML table
    # Created by Chris Pratt 09/08/09.
    # -----------------------------------------------------
    # _Version_History_
    # 0.1 - Inital Release
    # 
    # _Basic_Usage_
    # This snippet will only return the content of the table and not the
    # opening and closing <table> tags. This is by design to allow you to
    # add any attributes, classes or id to the table at will.
    #
    # Ex.
    #
    #   <table>
    #     [[csv2table? &csv=`/path/to/file.csv`]]
    #   </table>
    #
    # _Parameters_
    # &csv           : Path to CSV file (relative to document root)
    # &delimiter     : Character that separates values (defaults to `,`)
    # &enclosure     : Character that encloses strings (defaults to `"`)
    # &hasColHeader  : First row is column headings (boolean 0 or 1, defaults to 1)
    # &hasRowHeader  : First column of each row is a header (boolean 0 or 1, defaults to 0)
    # &alternateRows : Add a class to every 2nd row (boolean 0 or 1, defaults to 1)
    # &altRowClass   : Classname to use for alternating rows (defaults to `alt`)
    #
    # _Notes_
    # MODx snippets can be called with either `[[...]]` or `[!...!]`. The first
    # is a "cached" snippet call: the results of the snippet will be saved and
    # used again later instead of re-running the snippet. The second form is an
    # "uncached" snippet call: the results will not be saved and the snippet will
    # be run each time. Processing CSV files, especially large CSV files, may
    # consume an inordinant amount of resources, so you should always used the
    # "cached" version (`[[...]]`) of the snippet call to save processing time.
    
    
    $params = array(
      'csv' => isset($csv) ? $csv : '',
      'delimiter' => isset($delimiter) ? $delimiter : ',',
      'enclosure' => isset($enclosure) ? $enclosure : '"',
      'hasColHeader' => isset($hasColHeader) ? $hasColHeader : 1,
      'hasRowHeader' => isset($hasRowHeader) ? $hasRowHeader : 0,
      'alternateRows' => isset($alternateRows) ? $alternateRows : 1,
      'altRowClass' => isset($altRowClass) ? $altRowClass : 'alt'
    );
    
    class Csv2table {
      var $params;
      var $fp;
      
      function Csv2table (&$params) {
        //destructor
        register_shutdown_function(array(&$this, ‘__destruct’));
    
        //constructor
        $argcv = func_get_args();
        call_user_func_array(array(&$this, ‘__construct’), $argcv);
      }
      
      function __construct(&$params) {
        $this->params = $params;
      } // __construct
      
      function __destruct() {
        if ($this->fp) fclose($this->fp);
        unset($this->params);
        unset($this->fp);
      } // __destruct
      
      function load_csv_file () {
        if (isset($this->params['csv'])) {
          if (substr($this->params['csv'],0,1) != '/') $this->params['csv'] = '/'.$this->params['csv'];
          if (file_exists("{$_SERVER['DOCUMENT_ROOT']}{$this->params['csv']}")) {
            $this->fp = fopen("{$_SERVER['DOCUMENT_ROOT']}{$this->params['csv']}", 'rb');
          } else {
            return 'Could not find CSV file!';
          }
        } else {
          return 'No CSV file specified!';
        }
        
        if (!$this->fp) {
          return 'Could not open CSV file!';
        }
        
        return false;
      } // load_csv_file
      
      function build_table () {
        $output = '';
        
        if ($this->params['hasColHeader']) {
          $row = fgetcsv($this->fp, 1024, $this->params['delimiter'], $this->params['enclosure']);
          $output .= '    <tr class="heading">'."\n";
          foreach($row as $v) {
            $v = ($v == '') ? ' ' : htmlentities($v);
            $output .= '     <td>'.$v.'</td>'."\n";
          }
          $output .= '    </tr>'."\n";
        }
    
        $row_count = 0;
        while ($row = fgetcsv($this->fp, 1024, $this->params['delimiter'], $this->params['enclosure'])) {
          $row_count++;
    
          $row_class = ($this->params['alternateRows'] && (($row_count % 2) == 0)) ? ' class="'.$this->params['altRowClass'].'"' : '';
    
          $output .= '    <tr'.$row_class.'>'."\n";
          foreach($row as $k => $v) {
            $v = ($v == '') ? ' ' : htmlentities($v);
    
            if (($k == 0) && $this->params['hasRowHeader']) {
              $output .= '      <th>'.$v.'</th>'."\n";
            } else {
              $output .= '      <td class="norm">'.$v.'</td>'."\n";
            }
          }
          $output .= '    </tr>'."\n";
        }
        if ($this->params['hasColHeader']) {
        }
        
        return $output;
      } // build_table
      
      function get_output () {
        if (!$this->fp) $errors = $this->load_csv_file();
        if ($errors) return $errors;
        elseif (!$this->fp) return 'Could not open CSV file!';
        else return $this->build_table();
      } // get_output
      
    }
    
    $csv2table = new Csv2table($params);
    return $csv2table->get_output();
    


    Thanks guys.
      • 4058
      • 17 Posts
      Doh,

      This was fixed by wrapping the class with:

      if (!class_exists ('Csv2table')) {
           
           class Csv2table { ... }
      
      }
      


      Hope that helps anyone else having redeclare problems.
        • 3749
        • 24,544 Posts
        How about:

        <?php
        
        if (! class_exists()) {
          class Csv2table
            // etc.
        
        
        }
          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
          • 4058
          • 17 Posts
          Thanks Bob.