Baked Enums

By John Zimmerman (jzimmerman)
Moving this snippet over from CakeForge.

This is a preliminary solution to solve the problem of baking your Models's, View's and Controller's with enum keys in the database.

It is not completely automatic and I can only tell you that it works with PHP5 and MySQL 4/5.

As PHPNut stated in trac, the enum columns are too different across databases to make this standard (at least for now).

So if you are using something other than MySQL you will have to change the code in app_model.php accordingly.

Model Class:

Download code <?php 
<?php
class AppModel extends Model
{

    
/**
     * Get Enum Values
     * Snippet v0.1.3
     * http://cakeforge.org/snippet/detail.php?type=snippet&id=112
     *
     * Gets the enum values for MySQL 4 and 5 to use in selectTag()
     * Tested with PHP 4/5 and CakePHP 1.1.8
     */ 
    
function getEnumValues($columnName=null)
    {
        if (
$columnName==null) { return array(); } //no field specified


        //Get the name of the table
        
$db =& ConnectionManager::getDataSource($this->useDbConfig);
        
$tableName $db->fullTableName($thisfalse);


        
//Get the values for the specified column (database and version specific, needs testing)
        
$result $this->query("SHOW COLUMNS FROM {$tableName} LIKE '{$columnName}'");

        
//figure out where in the result our Types are (this varies between mysql versions)
        
$types null;
        if     ( isset( 
$result[0]['COLUMNS']['Type'] ) ) { $types $result[0]['COLUMNS']['Type']; } //MySQL 5
        
elseif ( isset( $result[0][0]['Type'] ) )         { $types $result[0][0]['Type'];         } //MySQL 4
        
else   { return array(); } //types return not accounted for

        //Get the values
        
$values explode("','"preg_replace("/(enum)\('(.+?)'\)/","\\2"$types) );

        
//explode doesn't do assoc arrays, but cake needs an assoc to assign values
        
$assoc_values = array();
        foreach ( 
$values as $value ) {
            
//leave the call to humanize if you want it to look pretty
            
$assoc_values[$value] = Inflector::humanize($value);
        }

        return 
$assoc_values;

    } 
//end getEnumValues

}
?>
?>

Controller Class:

Download code <?php 
<?php
/**
 * example code for your controller
 */
class ExamplesController extends AppController
{
    var 
$name "Examples";

    function 
add() {

        
/*
         * This is the addition to this action.  I have an enum column called
         * 'active' which I want the values for.  Bake already puts a variable
         * in the view called 'enumcolArray' to hold the values.  This is 
         * just setting the values for that for that variable using the code
         * we defined in app_model.php above.
         */
        
$this->set('activeArray',    $this->Example->getEnumValues('active'));

        if(empty(
$this->data)) {
            
$this->set('examples'null);
        } else {
            
$this->cleanUpFields();
            if(
$this->Example->save($this->data)) {
                if(
is_object($this->Session)) {
                    
$this->Session->setFlash('The Example has been saved');
                    
$this->redirect('/examples/index');
                } else {
                    
$this->flash('Example saved.''/examples/index');
                }
            } else {
                if(
is_object($this->Session)) {
                    
$this->Session->setFlash('Please correct errors below.');
                }
                
$data $this->data;
                
$this->set('examples'$data);
            }
        }
    }

}

?>
?>

 

Comments 72

CakePHP Team Comments Author Comments
 

Comment

1 Updating This Code

Originally posted by John Zimmerman Tue, Sep 26th 2006, 19:29
If you update this code please keep in mind not to break existing functionality. I.E. if you update for a different version of the database, make sure that it does not break functionality for databases currently supported.
Posted Oct 8, 2006 by Matt Keller
 

Comment

2 Look in the model propeties

I think you are using an extra query here to get the columns, when Cake already has this data and caches it. Check out __tableInfo or some of the other model properties to get the data without using the extra query.
Posted Oct 12, 2006 by gwoo
 

Comment

3 followup solution to Baked Enums...

I have created a similar solution to this problem, with a few improvements. It is similar in functionality to this snippet, but it doesn't make another call to the database for enum values, and it works with bake.php to automate the process. Thanks to John and gwoo for inspiration...
http://cakeforge.org/snippet/detail.php?type=snippet&id=143
Posted Oct 30, 2006 by Shawn Cook
 

Comment

4 Backticks to wrap TableName

I would recommend changing the query string to:

$result = $this->query("SHOW COLUMNS FROM `{$tableName}` LIKE '{$columnName}'");

Backticks prevent ill-conceived tableNames from breaking the MySQL query.
Posted Dec 8, 2006 by Ryan Overbey