Skip to content

CodeIgniter HTML Table Extension

World Wide Web Server edited this page Jul 4, 2012 · 13 revisions

UPDATED: 0.2 Added the ability to hide a column and the ability to selectively format a column.

This class is an extension of the HTML Table class its purpose is to allow the combination of columns as well as special formatting for date values. I created this class mainly for creating tables directly from CI SQL results. Instead of writing a more complex query than I already had it was much easier to set an array of keys and values to combine query results in my table.

Note: this is using the MY_ prefix you would need to change it based on your config.

[code] <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class MY_Table extends CI_Table { var $hide_columns = array(); var $format_columns = array(); var $merge_columns = array(); var $merged_delimiter = ' ';

/**
 * Set the columns to merge along with 
 * the spacer that goes in between.
 *
 * @access public
 * @param array
 * @param string
 * @return void
 **/
function set_columns_to_merge($merge_columns, $merged_delimiter = ' ')
{
    if(!is_array($merge_columns))return FALSE;
    $this->merge_columns = $merge_columns;
    
    if(is_null($merged_delimiter))$merged_delimiter = ' ';
    $this->merged_spacer = $merged_delimiter;
}

/**
 * Set the columns to hide
 *
 * @access public
 * @param array
 * @return void
 **/
function set_columns_to_hide($hide_columns)
{
    if(!is_array($hide_columns))return FALSE;
    $this->hide_columns = $hide_columns;
}

/**
 * Set the columns to format
 *
 * @access public
 * @param array with keys being the column names and values being the format function names
 * @return void
 **/    
function set_columns_to_format($format_columns)
{
    if(!is_array($format_columns))return FALSE;
    $this->format_columns = $format_columns;
}

/**
 * Generate the table format special cells (Enumerations, Dates).
 * Columns can also be merged by specifying the master and slave
 * columns (master => slave)in the merge_column array. The
 * merged_spacer goes in between all merged column values.
 *
 * NOTE: Merged columns always take the header of the
 * master (key) column.
 *
 * @access    public
 * @param    mixed
 * @return    string
 */
function generate($table_data = NULL)
{
    // The table data can optionally be passed to this function
    // either as a database result object or an array
    if(!is_null($table_data))
    {
        if(is_object($table_data))$this->_set_from_object($table_data);
        elseif(is_array($table_data))
        {
            $set_heading = (count($this->heading) == 0 AND $this->auto_heading == FALSE) ? FALSE : TRUE;
            $this->_set_from_array($table_data, $set_heading);
        }
    }
    
    // Is there anything to display?  No?  Smite them!
    if(count($this->heading) == 0 AND count($this->rows) == 0)return 'Undefined table data';
    
    // Compile and validate the template date
    $this->_compile_template();

    // Build the table!
    
    $out = $this->template['table_open'];
    $out .= $this->newline;        

    // Add any caption here
    if($this->caption)
    {
        $out .= $this->newline;
        $out .= '<caption>' . $this->caption . '</caption>';
        $out .= $this->newline;
    }

    // Is there a table heading to display?
    if(count($this->heading) > 0)
    {
        $out .= $this->template['heading_row_start'];
        $out .= $this->newline;        
        foreach($this->heading as $heading_key => $heading)
        {
            $heading_key = is_object($table_data) ? $heading : $heading_key;
            
            //Only add non-combined headers (ie master headers or regular headers)
            if(!$this->_merge_column($heading_key) &&
               !$this->_hide_column($heading_key))
            {
                $out .= $this->template['heading_cell_start'];
                $out .= $heading;
                $out .= $this->template['heading_cell_end'];
            }
        }

        $out .= $this->template['heading_row_end'];
        $out .= $this->newline;                
    }

    // Build the table rows
    if (count($this->rows) > 0)
    {
        $i = 1;
        
        foreach($this->rows as $row)
        {
            if(!is_array($row))break;
            
            // We use modulus to alternate the row colors
            $name = (fmod($i++, 2)) ? '' : 'alt_';
            
            $out .= $this->template['row_'.$name.'start'];
            $out .= $this->newline;        
            
            foreach($row as $cell_key => $cell)
            {
                //Use only non-combined cells (ie master cells, or regular cells)
                if(!$this->_merge_column($cell_key) &&
                   !$this->_hide_column($cell_key))
                {
                    $out .= $this->template['cell_'.$name.'start'];
                    
                    if($cell === "" || $cell === null)$out .= $this->empty_cells;
                    
                    $cell = $this->_format_cell($cell_key, $cell);
                    if(array_key_exists($cell_key, $this->merge_columns))
                    {
                        $cell .= $this->merged_delimiter;
                        $cell .= $this->_format_cell($cell_key, $row[$this->merge_columns[$cell_key]]);
                    }
                    $out .= $cell;
                    $out .= $this->template['cell_'.$name.'end'];
                }
            }
            
            $out .= $this->template['row_'.$name.'end'];
            $out .= $this->newline;    
        }
    }
    $out .= $this->template['table_close'];
    return $out;
}

/**
 * Helper method to format a cell using the specified format_columns array
 *
 * @access private
 * @param string
 * @return string
 **/
private function _format_cell($cell_key, $cell)
{
    if(array_key_exists($cell_key, $this->format_columns))
    {
        $cell = $this->format_columns[$cell_key]($cell);    
    }
    return $cell;
}

/**
 * Determines if the specified column value should be
 * combined with another and thusly not rendered.
 *
 * @access private
 * @param string
 * @return boolean
 **/
private function _merge_column($column)
{
    //return if this column isn't a master column or a regular column (its a merged column)
    return (array_key_exists($column, $this->merge_columns) === FALSE &&
          !(array_search($column, $this->merge_columns) === FALSE)); 
}

/**
 * Determines if the specified column value should be hidden
 *
 * @access private
 * @param string
 * @return boolean
 **/
private function _hide_column($column)
{
    return !(array_search($column, $this->hide_columns) === FALSE);
}

} ?>

/* Location: ./system/application/libraries/MY_Table.php */ [/code]

This allows you to generate the table in many different ways. When no columns are specified to be combined then it just renders the same way as CI_Table.

To call: [code] $this->load->library('table'); $table_data = array( array('abc', 'def', 'ghi'), array('jkl', 'mno', 'pqr'), array('stu', 'vwx', 'yza') ); $table1 = $this->table->generate($table_data); $this->table->set_columns_to_merge(array(0=>1), '+'); $table2 = $this->table->generate($table_data);

echo $table1; echo $table2; [/code] Would produce: [code] abc | def | ghi jkl | mno | pqr stu | vwx | yza [/code] and [code] abc | ghi jkl+mno | pqr stu+vwx | yza [/code]

This will also work with a CI SQL query result using the field names. So you can combine columns like this: [code] $this->table->set_columns_to_merge(array('id'=>'name'), '#'); [/code] Would produce a table that looks like this: [code] id | job | date 1#bob | developer | 2009-11-12 2#joe | lawyer | 2009-10-31 3#sam | teacher | 2009-09-15 [/code] Note that the merged column header does not get combined only the table cells do. The column header will always be the first merging columns' header.

To hide a column add an array to the set_columns_to_hide method passing an array with the name of the column(s) we wish to hide: [code] $this->table->set_columns_to_hide(array('job')); [/code] Using the previous example would produce a table that looks like this: [code] id | date 1#bob | 2009-11-12 2#joe | 2009-10-31 3#sam | 2009-09-15 [/code] This will also work on already merged columns.

If you would like to format a column you must first create a function that accepts the value of a table cell and always returns a value. If no operation was done on the value then you should just return it.

This function will reformat a date value using codeigniters mdate function. For the sake of simplicity lets assume I have already loaded the date helper. [code] function formatDate($value) { $newValue = mdate('%m/%d/%Y', mysql_to_unix($value)); if($newValue)$value = $newValue; return $value; } [/code] Now, still using the example above we would use the set_columns_to_format method passing an array with the name of the column as the key and the name of the format function as the value: [code] $this->table->set_columns_to_format(array('date' => 'formatDate')); [/code] Which would produce: [code] id | date 1#bob | 11/12/2009 2#joe | 10/31/2009 3#sam | 09/15/2009 [/code] Note formatting only works on merged cells after they have been merged so were you to merge the name column and the date column the format date function would fail.

Clone this wiki locally