Skip to content

CodeIgniter HTML Table Extension

Derek Jones edited this page Jul 5, 2012 · 13 revisions

Category:Contributions::Libraries::Table

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.

<?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 && !$this->auto_heading);
                $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($this->merge_columns[$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) &&
       is_callable($this->format_columns[$cell_key]))
        {
            $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) &&
              in_array($column, $this->merge_columns); 
    }
    
    /**
     * Determines if the specified column value should be hidden
     *
     * @access private
     * @param string
     * @return boolean
     **/
    private function _hide_column($column)
    {
        return in_array($column, $this->hide_columns);
    }
}
?&gt;

/* Location: ./system/application/libraries/MY_Table.php */ 

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:

$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;

Would produce:

abc | def | ghi
jkl | mno | pqr
stu | vwx | yza

and

abc     | ghi
jkl+mno | pqr
stu+vwx | yza

This will also work with a CI SQL query result using the field names. So you can combine columns like this:

$this->table->set_columns_to_merge(array('id'=>'name'), '#');

Would produce a table that looks like this:

id    | job       | date
1#bob | developer | 2009-11-12
2#joe | lawyer    | 2009-10-31
3#sam | teacher   | 2009-09-15

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:

$this->table->set_columns_to_hide(array('job'));

Using the previous example would produce a table that looks like this:

id    | date
1#bob | 2009-11-12
2#joe | 2009-10-31
3#sam | 2009-09-15

If you would like to format a column you must first create a function that accepts the value of the table cell you wish to change. Make sure the function always returns a value. If no operation was done on the value then you will most likely want to 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.

function formatDate($value)
{
    $newValue = mdate('%m/%d/%Y', mysql_to_unix($value));
    if($newValue)$value = $newValue;
    return $value;
}

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:

$this->table->set_columns_to_format(array('date' => 'formatDate'));

Which would produce:

id    | date
1#bob | 11/12/2009
2#joe | 10/31/2009
3#sam | 09/15/2009

Note formatting only works on individual columns.We could not combine the name and date columns then use a single formatting function to change them both. We would need two formatting functions one that changed the name and one that changed the date then merge them.

Clone this wiki locally