Changeset 1245

Show
Ignore:
Timestamp:
02/07/09 17:49:17 (1 year ago)
Author:
bermi
Message:

Refactoring Active Record schema cache.

Fixes #249

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/lib/AkActiveRecord.php

    r1243 r1245  
    3232defined('AK_ACTIVE_RECORD_ENABLE_CALLBACK_SETTERS') ? null : define('AK_ACTIVE_RECORD_ENABLE_CALLBACK_SETTERS', AK_ACTIVE_RECORD_ENABLE_AUTOMATIC_SETTERS_AND_GETTERS); 
    3333defined('AK_ACTIVE_RECORD_ENABLE_CALLBACK_GETTERS') ? null : define('AK_ACTIVE_RECORD_ENABLE_CALLBACK_GETTERS', AK_ACTIVE_RECORD_ENABLE_AUTOMATIC_SETTERS_AND_GETTERS); 
    34  
    35 // Forces loading database schema on every call 
    36 if(AK_DEV_MODE) { 
    37     AkDbSchemaCache::doRefresh(true); 
    38 } else if (AK_ENVIRONMENT == 'testing') { 
    39     AkDbSchemaCache::doRefresh(true); 
    40     define('AK_ACTIVE_RECORD_CACHE_DATABASE_SCHEMA',true); 
    41 } 
    4234 
    4335defined('AK_ACTIVE_RECORD_ENABLE_PERSISTENCE') ? null : define('AK_ACTIVE_RECORD_ENABLE_PERSISTENCE', AK_ENVIRONMENT != 'testing'); 
     
    24202412    function setTableName($table_name = null, $check_for_existence = AK_ACTIVE_RECORD_VALIDATE_TABLE_NAMES, $check_mode = false) 
    24212413    { 
    2422         !AK_TEST_MODE && $static_cached_tables = Ak::getStaticVar('available_tables'); 
    2423          
    24242414        if(empty($table_name)){ 
    24252415            $table_name = AkInflector::tableize($this->getModelName()); 
    24262416        } 
    24272417        if($check_for_existence){ 
    2428             if(!isset($available_tables) || $check_mode){ 
    2429                 if(!isset($this->_db)){ 
    2430                     $this->setConnection(); 
    2431                 } 
    2432                 if (!AK_ACTIVE_RECORD_CACHE_DATABASE_SCHEMA ||  
    2433                     ($available_tables = AkDbSchemaCache::getAvailableTables()) === false) { 
    2434                     if(!empty($static_cached_tables)){ 
    2435                         $available_tables = $static_cached_tables; 
    2436                     }else{ 
    2437                         $available_tables = $this->_db->availableTables(); 
    2438                     } 
    2439                     if (AK_ACTIVE_RECORD_CACHE_DATABASE_SCHEMA) { 
    2440                         AkDbSchemaCache::setAvailableTables($available_tables); 
    2441                     } 
    2442                     !AK_TEST_MODE && Ak::setStaticVar('available_tables', $available_tables); 
    2443                 } 
    2444             } 
    2445             if(!in_array($table_name,(array)$available_tables)){ 
     2418            !isset($this->_db) && $this->setConnection(); 
     2419            if(!$this->_db->tableExists($table_name, true)){ 
    24462420                if(!$check_mode){ 
    24472421                    trigger_error(Ak::t('Unable to set "%table_name" table for the model "%model".'. 
     
    25422516    function _databaseTableInternals($table) 
    25432517    { 
    2544         if (!AK_ACTIVE_RECORD_CACHE_DATABASE_SCHEMA || ($cache = AkDbSchemaCache::getDbTableInternals($table))===false) { 
     2518        if (!$cache = AkDbSchemaCache::get('table_internals_for_'.$table)) { 
    25452519            $cache = $this->_db->getColumnDetails($table); 
    2546             if (AK_ACTIVE_RECORD_CACHE_DATABASE_SCHEMA) { 
    2547                 AkDbSchemaCache::setDbTableInternals($table,$cache); 
    2548             } 
     2520            AkDbSchemaCache::set('table_internals_for_'.$table, $cache); 
    25492521        } 
    25502522        return $cache; 
     
    26162588            $this->setConnection(); 
    26172589        } 
    2618         $this->_columnsSettings = $force_reload ? null : $this->_getPersistedTableColumnSettings(); 
    2619  
    2620         if(empty($this->_columnsSettings) || !AK_ACTIVE_RECORD_ENABLE_PERSISTENCE){ 
     2590        $this->_columnsSettings = ($force_reload ? null : $this->_getPersistedTableColumnSettings()); 
     2591        if(empty($this->_columnsSettings)){ 
    26212592            if(empty($this->_dataDictionary)){ 
    26222593                $this->_dataDictionary =& $this->_db->getDictionary(); 
     
    26262597 
    26272598            if( !isset($this->_avoidTableNameValidation) && 
    2628             !is_array($column_objects) && 
    2629             !$this->_runCurrentModelInstallerIfExists($column_objects)){ 
    2630                 trigger_error(Ak::t('Ooops! Could not fetch details for the table %table_name.', array('%table_name'=>$this->getTableName())), E_USER_ERROR); 
    2631                 return false; 
     2599                !is_array($column_objects) && 
     2600                !$this->_runCurrentModelInstallerIfExists($column_objects)){ 
     2601                    trigger_error(Ak::t('Ooops! Could not fetch details for the table %table_name.', array('%table_name'=>$this->getTableName())), E_USER_ERROR); 
     2602                    return false; 
    26322603            }elseif (empty($column_objects)){ 
    26332604                $this->_runCurrentModelInstallerIfExists($column_objects); 
     
    26382609                } 
    26392610            } 
    2640             if(!empty($this->_columnsSettings) && AK_ACTIVE_RECORD_CACHE_DATABASE_SCHEMA){ 
     2611            if(!empty($this->_columnsSettings)){ 
    26412612                $this->_persistTableColumnSettings(); 
    26422613            } 
     
    26912662    } 
    26922663 
     2664 
    26932665    /** 
    26942666    * @access private 
    26952667    */ 
    2696     function _getColumnsSettings() 
    2697     { 
    2698         return AkDbSchemaCache::getColumnsSettings(); 
     2668    function _getModelColumnSettings() 
     2669    { 
     2670        return AkDbSchemaCache::get($this->getModelName().'_column_settings'); 
     2671         
    26992672    } 
    27002673 
     
    27022675    * @access private 
    27032676    */ 
    2704     function _getModelColumnSettings() 
    2705     { 
    2706         return AkDbSchemaCache::getModelColumnSettings($this->getModelName()); 
    2707          
     2677    function _persistTableColumnSettings() 
     2678    { 
     2679        AkDbSchemaCache::set($this->getModelName().'_column_settings', $this->_columnsSettings); 
    27082680    } 
    27092681 
     
    27112683    * @access private 
    27122684    */ 
    2713     function _persistTableColumnSettings() 
    2714     { 
    2715         AkDbSchemaCache::setModelColumnSettings($this->getModelName(), $this->_columnsSettings); 
    2716     } 
    2717  
    2718     /** 
    2719     * @access private 
    2720     */ 
    27212685    function _getPersistedTableColumnSettings() 
    27222686    { 
    2723         return AkDbSchemaCache::getModelColumnSettings($this->getModelName()); 
    2724          
     2687        return AkDbSchemaCache::get($this->getModelName().'_column_settings');         
    27252688    } 
    27262689 
     
    45164479            }elseif (is_array($this->act_as)){ 
    45174480                foreach ($this->act_as as $type=>$options){ 
    4518                                        if(is_numeric($type)){ 
    4519                            $this->actsAs($options, array()); 
    4520                                        }else{ 
    4521                            $this->actsAs($type, $options);                                             
    4522                                        
    4523                                
     4481                    if(is_numeric($type)){ 
     4482                        $this->actsAs($options, array()); 
     4483                    }else{ 
     4484                        $this->actsAs($type, $options);                                                
     4485                   
     4486               
    45244487            } 
    45254488        } 
  • trunk/lib/AkActiveRecord/AkDbAdapter.php

    r1185 r1245  
    374374     * @return unknown 
    375375     */ 
    376     function availableTables() 
    377     { 
    378         return $this->connection->MetaTables(); 
    379     } 
     376    function availableTables($force_lookup = false) 
     377    { 
     378        $available_tables = array(); 
     379        !AK_TEST_MODE && $available_tables = Ak::getStaticVar('available_tables'); 
     380        if(!$force_lookup && empty($available_tables)){ 
     381            if (($available_tables = AkDbSchemaCache::get('avaliable_tables')) === false) { 
     382                if(empty($available_tables)){ 
     383                    $available_tables = $this->connection->MetaTables();                 
     384                } 
     385                AkDbSchemaCache::set('avaliable_tables', $available_tables); 
     386                !AK_TEST_MODE && Ak::setStaticVar('available_tables', $available_tables); 
     387            } 
     388        } 
     389        $available_tables = $force_lookup ? $this->connection->MetaTables() : $available_tables; 
     390        $force_lookup && !AK_TEST_MODE && Ak::setStaticVar('available_tables', $available_tables); 
     391        return $available_tables; 
     392    } 
     393     
     394    function tableExists($table_name) 
     395    { 
     396        // First try if cached 
     397        $available_tables = $this->availableTables(); 
     398        if(!in_array($table_name,(array)$available_tables)){ 
     399            // Force lookup and refresh cache 
     400           $available_tables = $this->availableTables(true); 
     401           return in_array($table_name,(array)$available_tables); 
     402        } 
     403        return true; 
     404    } 
     405     
    380406    /** 
    381407     * caching the meta info 
     
    384410     * @return unknown 
    385411     */ 
     412     
    386413    function getColumnDetails($table_name) 
    387414    { 
  • trunk/lib/AkActiveRecord/AkDbAdapters/AkMysqlDbAdapter.php

    r1233 r1245  
    6969    } 
    7070     
    71     function availableTables() 
    72     { 
    73         return $this->selectValues('SHOW TABLES'); 
    74     } 
    75      
    7671    /* QUOTING */  
    7772     
  • trunk/lib/AkActiveRecord/AkDbSchemaCache.php

    r1196 r1245  
    11<?php 
     2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 
    23 
     4// +----------------------------------------------------------------------+ 
     5// | Akelos Framework - http://www.akelos.org                             | 
     6// +----------------------------------------------------------------------+ 
     7// | Copyright (c) 2008-2009, Bermi Ferrer Martinez                       | 
     8// | Released under the GNU Lesser General Public License, see LICENSE.txt| 
     9// +----------------------------------------------------------------------+ 
     10 
     11/** 
     12 * @package ActiveRecord 
     13 * @subpackage Base 
     14 * @component DbSchemaCache 
     15 * @author Arno Schneider 2008 
     16 * @author Bermi Ferrer 2009 
     17 * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html> 
     18 */ 
     19  
    320class AkDbSchemaCache 
    421{ 
    5     function doRefresh($set = null) 
     22    function shouldRefresh($set = null) 
    623    { 
    7         static $refresh = false; 
    8         if ($set === false) { 
    9             $refresh = false; 
    10         } else if ($set === true) { 
    11             $refresh = true; 
     24        static $refresh; 
     25        if(!isset($refresh)){ 
     26            $refresh = !AK_ACTIVE_RECORD_CACHE_DATABASE_SCHEMA; 
    1227        } 
     28        $refresh = is_null($set) ? $refresh : $set; 
    1329        return $refresh; 
    1430    } 
    15     function _generateCacheFileName($table, $environment = AK_ENVIRONMENT) 
     31 
     32    function getCacheFileName($environment = AK_ENVIRONMENT) 
    1633    { 
    17         $namespace = Ak::sanitize_include($table, 'high'); 
    18         $cacheDir = AK_CONFIG_DIR; 
     34        return AkDbSchemaCache::getCacheDir().DS.$environment.'.serialized'; 
     35    } 
     36     
     37    function getCacheDir() 
     38    { 
     39        $cache_dir = AK_CONFIG_DIR; 
    1940        if (defined('AK_CONFIG_CACHE_TMP') && AK_CONFIG_CACHE_TMP) { 
    20             $cacheDir  = AK_TMP_DIR.DS.'ak_config'; 
     41            $cache_dir  = AK_TMP_DIR.DS.'ak_config'; 
    2142        } 
    22         $cacheFile = $cacheDir.DS.'cache'.DS.'activerecord'.DS.$environment.DS.$table.'.php'; 
    23         return $cacheFile; 
     43        return $cache_dir.DS.'cache'.DS.'activerecord'; 
    2444    } 
    2545     
    2646    function clear($table, $environment = AK_ENVIRONMENT) 
    2747    { 
    28          
    29         $modelName = AkInflector::singularize(AkInflector::classify($table)); 
    30         $cacheFileName = AkDbSchemaCache::_generateCacheFileName($modelName, $environment); 
    31         //echo "Cleaning cache: $cacheFileName\n"; 
    32         if (file_exists($cacheFileName)) { 
    33             @unlink($cacheFileName); 
    34         } 
    35         AkDbSchemaCache::_get($modelName,$environment,false,false); 
    36         $tableName = AkInflector::tableize($table); 
    37         $databaseInternalsFileName = AkDbSchemaCache::_generateCacheFileName('database_table_internals_'.$tableName); 
    38         //echo "Cleaning cache: $databaseInternalsFileName\n"; 
    39         if (file_exists($databaseInternalsFileName)) { 
    40             @unlink($databaseInternalsFileName); 
    41         } 
    42          
    43         AkDbSchemaCache::_get('database_table_internals_'.$tableName,$environment,false,false); 
    44     } 
    45      
    46     function clearAll($environment = AK_ENVIRONMENT) 
    47     { 
    48         $dummy = AkDbSchemaCache::_generateCacheFileName('dummy', $environment); 
    49         $dir = dirname($dummy); 
    50         $files = Ak::dir($dir); 
    51         foreach ($files as $file) { 
    52             if (is_file($dir.DS.$file)) { 
    53                 @unlink($dir.DS.$file); 
    54             } 
     48        AkDbSchemaCache::_config($table, null, $environment, true); 
     49        AkDbSchemaCache::_config('database_table_internals_'.$table, null, $environment, true); 
     50        AkDbSchemaCache::_updateCacheFileAfterExecution($environment); 
     51        if(AK_LOG_EVENTS){ 
     52            $Logger =& Ak::getLogger(); 
     53            $Logger->message('Clearing database settings cache for '.$table); 
    5554        } 
    5655    } 
    5756     
    58     function getAvailableTables($environment = AK_ENVIRONMENT
     57    function clearAll(
    5958    { 
    60         return AkDbSchemaCache::_get('available_tables', $environment); 
     59        if(AK_LOG_EVENTS){ 
     60            $Logger =& Ak::getLogger(); 
     61            $Logger->message('Clearing all database settings from cache'); 
     62        } 
     63        Ak::directory_delete(AkDbSchemaCache::getCacheDir()); 
    6164    } 
    6265     
    63     function setAvailableTables($tables, $environment = AK_ENVIRONMENT) 
     66    function get($key, $environment = AK_ENVIRONMENT) 
    6467    { 
    65         AkDbSchemaCache::_set('available_tables',$tables, $environment); 
    66     } 
    67     function setModelColumnSettings($model, $config, $environment = AK_ENVIRONMENT) 
    68     { 
    69         return AkDbSchemaCache::_set($model, $config, $environment, false, true); 
    70          
    71     } 
    72     function setDbTableInternals($table, $internals, $environment = AK_ENVIRONMENT) 
    73     { 
    74         return AkDbSchemaCache::_set('database_table_internals_'.$table, $internals, $environment); 
    75     } 
    76     function getDbTableInternals($table, $environment = AK_ENVIRONMENT) 
    77     { 
    78         return AkDbSchemaCache::_get('database_table_internals_'.$table,$environment); 
    79     } 
    80     function getColumnsSettings($environment = AK_ENVIRONMENT) 
    81     { 
    82         return AkDbSchemaCache::_get(true,$environment); 
    83          
    84     } 
    85     function getModelColumnSettings($model, $environment = AK_ENVIRONMENT) 
    86     { 
    87         return AkDbSchemaCache::_get($model, $environment, false, null, true); 
    88     } 
    89     function &_get($type, $environment = AK_ENVIRONMENT, $uncached = false, $set = null, $var_export = false) 
    90     { 
    91         $false = false; 
    92         if (AkDbSchemaCache::doRefresh() && $set === null) return $false; 
    93         $null = null; 
    94         static $configs = array(); 
    95         if ($set !== null) { 
    96             if (!isset($configs[$environment])) { 
    97                 $configs[$environment] = array(); 
    98             } 
    99             if ($set === false) { 
    100                 unset($configs[$environment][$type]); 
    101             } else { 
    102                 $configs[$environment][$type] = $set; 
    103             } 
    104             return $null; 
    105         } 
    106          
    107         if ($type === true) { 
    108             return isset($configs[$environment]) ? $configs[$environment] : array(); 
    109         } 
    110         if (!$uncached && isset($configs[$environment]) && isset($configs[$environment][$type])) { 
    111             return $configs[$environment][$type]; 
    112         } 
    113         if ($uncached || !($config = AkDbSchemaCache::_readCache($type, $environment, false, $var_export))) { 
    114             return $false; 
    115         } 
    116         if (!isset($configs[$environment])) { 
    117             $configs[$environment] = array($type=>$config); 
    118         } else { 
    119             $configs[$environment][$type] = $config; 
    120         } 
    121         return $configs[$environment][$type]; 
     68        return AkDbSchemaCache::_config($key, null, $environment, false);    
    12269    } 
    12370     
    124     function _readCache($table, $environment = AK_ENVIRONMENT, $force = false, $var_export = false
     71    function set($key, $value, $environment = AK_ENVIRONMENT
    12572    { 
    126         $cacheFileName = AkDbSchemaCache::_generateCacheFileName($table,$environment); 
    127         if (file_exists($cacheFileName)) { 
    128             if ($var_export === false) { 
    129                 $config = unserialize(file_get_contents($cacheFileName)); 
    130             } else { 
    131                 $config = include $cacheFileName; 
    132             } 
    133         } else { 
    134             $config = false; 
    135         } 
    136         return $config; 
     73        AkDbSchemaCache::_updateCacheFileAfterExecution($environment); 
     74        return AkDbSchemaCache::_config($key, $value, $environment, !is_null($value)); 
    13775    } 
    13876     
    139     function _set($type, $config, $environment = AK_ENVIRONMENT, $force = false, $var_export = false
     77    function _updateCacheFileAfterExecution($environment = null
    14078    { 
    141         if ($var_export === false) { 
    142             $cache = serialize($config); 
    143         } else { 
    144             $cacheStr = var_export($config,true); 
    145             $cache = <<<EOF 
    146 <?php 
    147 \$cache = $cacheStr; 
    148 return \$cache; 
     79        static $called = false, $_environment; 
     80        if($called == false && !AkDbSchemaCache::shouldRefresh()){ 
     81            register_shutdown_function(array('AkDbSchemaCache','_updateCacheFileAfterExecution')); 
     82            $called =  !empty($environment) ? $environment : AK_ENVIRONMENT; 
     83        }elseif(empty($environment)){ 
     84            $config = AkDbSchemaCache::_config(null, null, $called); 
     85            $file_name = AkDbSchemaCache::getCacheFileName($called); 
     86            if(AK_LOG_EVENTS){ 
     87                $Logger =& Ak::getLogger(); 
     88                $Logger->message('Updating database settings on '.$file_name); 
     89            } 
     90            /** 
     91            * @todo On PHP5 var_export requires objects that implement the __set_state magic method. 
     92            *       As see on stangelanda at arrowquick dot benchmarks at comhttp://php.net/var_export 
     93            *       serialize works faster without opcode caches. We should do our benchmarks with  
     94            *       var_export VS serialize using APC once we fix the __set_state magic on phpAdoDB 
     95            */ 
     96            Ak::file_put_contents($file_name, serialize($config)); 
     97        } 
     98    } 
     99     
     100    function _config($key = null, $value = null, $environment = AK_ENVIRONMENT, $unset = false) 
     101    { 
     102        if(AkDbSchemaCache::shouldRefresh()){ 
     103            return false; 
     104        } 
     105        static $config; 
     106        if(!isset($config[$environment])){ 
     107            $file_name = AkDbSchemaCache::getCacheFileName($environment); 
     108            $config[$environment] = file_exists($file_name) ? unserialize(Ak::file_get_contents($file_name)) : array(); 
     109            if(AK_LOG_EVENTS){ 
     110                $Logger =& Ak::getLogger(); 
     111                $Logger->message('Loading cached database settings'); 
     112            } 
     113        } 
     114        if(!is_null($key)){ 
     115            if(!is_null($value)){ 
     116                $config[$environment][$key] = $value; 
     117            }elseif($unset){ 
     118                unset($config[$environment][$key]); 
     119            } 
     120            return isset($config[$environment][$key]) ? $config[$environment][$key] : false; 
     121        } 
     122        return $config[$environment]; 
     123    } 
     124
     125 
    149126?> 
    150 EOF; 
    151         } 
    152         $cacheFileName = AkDbSchemaCache::_generateCacheFileName($type,$environment); 
    153         $cacheDir = dirname($cacheFileName); 
    154          
    155         if (!file_exists($cacheDir)) { 
    156             $oldumask = umask(); 
    157             umask(0); 
    158             $res = @mkdir($cacheDir,0777,true); 
    159             if (!$res) { 
    160                 trigger_error(Ak::t('Could not create config cache dir %dir',array('%dir'=>$cacheDir)),E_USER_ERROR); 
    161             } 
    162             umask($oldumask); 
    163         } 
    164         $fh = fopen($cacheFileName,'w+'); 
    165         if ($fh) { 
    166             fputs($fh,$cache); 
    167             fclose($fh); 
    168             @chmod($cacheFileName,0777); 
    169         } else { 
    170             trigger_error(Ak::t('Could not create dbschema cache file %file',array('%file'=>$cacheFileName)),E_USER_ERROR); 
    171         } 
    172         AkDbSchemaCache::_get($type, $environment, false, $config); 
    173     } 
    174  
    175 } 
    176 ?> 
  • trunk/lib/AkConfig.php

    r1196 r1245  
    171171        return $config; 
    172172    } 
     173     
    173174    function _writeCache($config, $namespace, $environment = AK_ENVIRONMENT, $force = false) 
    174175    { 
     
    207208        $this->_setCacheValidity($namespace,$environment); 
    208209    } 
     210     
    209211    function _generateConfigFileName($namespace,$environment = AK_ENVIRONMENT) 
    210212    { 
     
    273275    function _getConstant($name) 
    274276    { 
    275         return defined($name[1])?constant($name[1]):''; 
     277        return defined($name[1]) ? constant($name[1]) : ''; 
    276278    } 
    277279     
  • trunk/lib/AkInstaller.php

    r1223 r1245  
    8989            $this->db =& $db_connection; 
    9090        } 
    91  
     91        AkDbSchemaCache::clearAll();         
    9292        $this->data_dictionary =& $this->db->getDictionary(); 
    9393        $this->available_tables = $this->getAvailableTables(); 
  • trunk/test/unit/lib/AkActiveRecord/_AkActiveRecord_1.php

    r1185 r1245  
    5757        $this->assertEqual($AkTestUser->getModelName(), 'AkTestUser'); 
    5858        $this->assertEqual($AkTestUser->getTableName(), 'ak_test_users'); 
    59         $this->assertErrorPattern('/ak_test_user/',$AkTestUser->setTableName('ak_test_user')); 
     59        $this->assertErrorPattern('/ak_test_user/', $AkTestUser->setTableName('ak_test_user')); 
    6060 
    6161        //$this->_createNewTestingModel('AkTestUnavailableDatabase'); 
     
    130130    function Test_of_loadColumnsSettings() 
    131131    { 
     132        AkDbSchemaCache::shouldRefresh(false); 
    132133        $AkTestField = new AkTestField(); 
    133134        $AkTestField->loadColumnsSettings(); 
    134135        // Testing database settings cache on session (this might be changed in a future 
    135         AkDbSchemaCache::doRefresh(false); 
    136         $this->assertEqual($AkTestField->_columnsSettings,AkDbSchemaCache::getModelColumnSettings('AkTestField')); 
    137         AkDbSchemaCache::doRefresh(true); 
     136        $this->assertEqual($AkTestField->_columnsSettings, AkDbSchemaCache::get('AkTestField_column_settings')); 
     137        AkDbSchemaCache::shouldRefresh(true); 
    138138    } 
    139139 
     
    569569    } 
    570570 
    571     function Test_of_getSerializedAttributes_and_setSerializeAttribute() 
    572     { 
    573         $User = new AkTestUser(); 
    574         $User->addCombinedAttributeConfiguration('name', "%s %s", 'first_name', 'last_name'); 
    575         $User->setSerializeAttribute('user_name'); 
    576         $User->setSerializeAttribute('name'); 
    577         $User->setSerializeAttribute('not_valid'); 
    578         $User->setSerializeAttribute('email','MimeEmail'); 
    579         $expected = array('user_name' => null, 'email' => 'MimeEmail'); 
    580         $this->assertEqual($expected, $User->getSerializedAttributes()); 
    581  
    582     } 
    583  
    584571    function Test_of_setAccessibleAttributes() 
    585572    {