MySQL collation behavior

by prond
A simple behavior that sets proper collation for order by SQL statements based on the current localization.
Whenever you write multilangual apps you have to deal with many many problems. One of them is setting a proper collation for order by SQL statements so that results are ordered properly. The following behavior adds a proper collation to every SQL statement based on current localization.
Included behavior includes yet only polish collation. However you can include more collations very quickly.

Usage :

Model Class:

<?php 
class ArticleModel extends AppModel {
  
$actsAs = array ('Collation'=>array('title','contents'));
}
?>

Code :

Behavior Class:

<?php 
/**
* MySQL collation Behavior class file.
*
* Model Behavior to support Polish typography.
*
* @filesource
* @package    app
* @subpackage    models.behaviors
*/

/**
* Add MySQL collation behavior
*
* @author    Pawel Gasiorowski <p.gasiorowski@axent.pl>
* @package    app
* @subpackage     models.behaviors
*/
class CollationBehavior extends ModelBehavior {
    
    
/**
    * Initiate behaviour for the model using specified settings.
    *
    * @param object $model        Model using the behaviour
    * @param array $settings    Settings to override for model.
    *
    * @access public
    */
    
function setup(&$model$settings) {
        
#
        #    get current language
        #
        
$i18n = &I18n::getInstance();
        
$language $i18n->l10n->map($i18n->l10n->lang);
        
        
#
        #    get collation by language
        #
        
switch ($language) {
            case 
'pl':
            
$collation 'utf8_polish_ci';
            default:
            
$collation 'utf8_general_ci';
            break;
        }
        
        
#
        #    read settings
        #
        
if (!isset($this->settings[$model->name]['fields'])) {
            
$this->settings[$model->name]['fields'] = array();
        }
        
$this->settings[$model->name]['fields'] = array_unique(array_merge($this->settings[$model->name]['fields'], ife(is_array($settings), $settings, array())));
        
$this->settings[$model->name]['search'] = array();
        
$this->settings[$model->name]['replace'] = array();
        
        
#
        #    setup replacements for columns
        #
        
foreach ($this->settings[$model->name]['fields'] as &$field) {
            if (
strpos($field,".") === false) {
                
$this->settings[$model->name]['search'][] = "/({$model->name}.{$field})/";
            } else {
                
$this->settings[$model->name]['search'][] = "/({$field})/";
            }
            
$this->settings[$model->name]['replace'][] = '$1'." COLLATE {$collation}";
        }
    }
    
    
/**
    * Run before model is queried
    *
    * @param object $model        Model
    * @param array $query        Model query data
    *
    * @access public
    * @since 1.0
    */
    
function beforeFind (&$model, &$query) {
        if (!empty(
$query['order'])) {
            if (
is_string($query['order'])) {
                
$query['order'] = preg_replace($this->settings[$model->name]['search'],$this->settings[$model->name]['replace'],$query['order']);
            } else if (
is_array($query['order'])) {
                foreach (
$query['order'] as $i => $order) {
                    if (
is_array($order)) {
                        
$_order "";
                        foreach (
$order as $field => $direction) {
                            
$_order .= {$field} {$direction}";
                        }
                        
$order trim ($_order);
                    }
                    
$order preg_replace($this->settings[$model->name]['search'],$this->settings[$model->name]['replace'],$order);
                    
$query['order'][$i] = $order;
                }
                
$query['order'] = implode(" ",$query['order']);
            }
        }
        
        return 
$query;
    }
}
?>

Report

More on Behaviors

Advertising

Comments

  • naonak posted on 04/14/08 04:28:04 AM

            switch ($language) {

                case 'cs': /* Czech */
                    $collation = 'utf8_czech_ci';
                case 'da': /* Danish */
                       $collation = 'utf8_danish_ci';
                case 'et': /* Estonian */
                    $collation = 'utf8_estonian_ci';
                case 'hu': /* Hungarian */
                    $collation = 'utf8_hungarian_ci';
                case 'is': /* Icelandic */
                    $collation = 'utf8_icelandic_ci';
                case 'lv': /* Latvian */
                       $collation = 'utf8_latvian_ci';
                case 'lt': /* Lithuanian */
                    $collation = 'utf8_lithuanian_ci';
                case 'pl': /* Polish */
                    $collation = 'utf8_polish_ci';
                case 'ro': /* Romanian */
                    $collation = 'utf8_romanian_ci';
                case 'sk': /* Slovack */
                    $collation = 'utf8_slovak_ci';
                case 'sl': /* Slovenian */
                    $collation = 'utf8_slovenian_ci';
                case 'es': /* Spanish (Spain - Traditional) */
                    $collation = 'utf8_spanish2_ci';
                case 'sv': /* Swedish */
                    $collation = 'utf8_swedish_ci';
                case 'tr': /* Turkish */
                    $collation = 'utf8_turkish_ci';
                default:
                    $collation = 'utf8_general_ci';
                break;

            }
login to post a comment.