EllisLab text mark
Advanced Search
     
AnyCase ModelNames ( Ever wanted to capitalize your models however you wished? )
Posted: 17 July 2008 08:45 AM
Joined: 2008-07-17
2 posts

I’m relatively new to CodeIgniter, but not to programming.
I was recently looking through the guide on Models ( http://ellislab.com/codeigniter/user-guide/general/models.html ) going through the general topics one by one like a good user, when I found a line that struck me as generally odd, under the heading “Anatomy of a Model.”

class Model_name extends Model {

    
function Model_name()
    
{
        parent
::Model();
    
}

Where Model_name is the name of your class. Class names must have the first letter capitalized with the rest of the name lowercase. Make sure your class extends the base Model class.

The underlined portion in particular, is what threw me for a loop. What could possibly be the cause of such a silly rule? Shouldn’t I be able to capitalize my Models however I wish?

Well I traipsed through the code to find out the reason for this rule. In all technicality, it’s an easy fix, but I’m not certain if it’s a rule based on the code, or based on a choice.

In any case, here’s what I found:

In ./system/libraries/Loader.php
lines 98 through 181

/**
 * Model Loader
 *
 * This function lets users load and instantiate models.
 *
 * @param    string    the name of the class
 * @param    string    name for the model
 * @param    bool    database connection
 * @return    void
 */    
function model($model$name ''$db_conn FALSE)
{        
    
if (is_array($model))
    
{
        
foreach($model as $babe)
        
{
            $this
->model($babe);    
        
}
        
return;
    
}

    
if ($model == '')
    
{
        
return;
    
}

    
// Is the model in a sub-folder? If so, parse out the filename and path.
    
if (strpos($model'/') === FALSE)
    
{
        $path 
'';
    
}
    
else
    
{
        $x 
explode('/'$model);
        
$model end($x);            
        unset(
$x[count($x)-1]);
        
$path implode('/'$x).'/';
    
}

    
if ($name == '')
    
{
        $name 
$model;
    
}
    
    
if (in_array($name$this->_ci_modelsTRUE))
    
{
        
return;
    
}
    
    $CI 
=& get_instance();
    if (isset(
$CI->$name))
    
{
        show_error
('The model name you are loading is the name of a resource that is already being used: '.$name);
    
}

    $model 
strtolower($model);
    
    if ( ! 
file_exists(APPPATH.'models/'.$path.$model.EXT))
    
{
        show_error
('Unable to locate the model you have specified: '.$model);
    
}
            
    
if ($db_conn !== FALSE AND ! class_exists('CI_DB'))
    
{
        
if ($db_conn === TRUE)
            
$db_conn '';
    
        
$CI->load->database($db_connFALSETRUE);
    
}

    
if ( ! class_exists('Model'))
    
{
        load_class
('Model'FALSE);
    
}

    
require_once(APPPATH.'models/'.$path.$model.EXT);

    
$model ucfirst($model);
            
    
$CI->$name = new $model();
    
$CI->$name->_assign_libraries();
    
    
$this->_ci_models[] $name;    

This is the model loading function, it’s pretty nifty for the most part, but all personal commentary aside, here are the lines in question.

lines 153 through 158

$model strtolower($model);

if ( ! 
file_exists(APPPATH.'models/'.$path.$model.EXT))
{
    show_error
('Unable to locate the model you have specified: '.$model);

and

lines 173 through 175

require_once(APPPATH.'models/'.$path.$model.EXT);

$model ucfirst($model); 

What’s happening is that we’re lowercasing $model with strtolower($model); in order to load the file, and then uppercasing the first letter with ucfirst($model);

So, here’s one simple way to bypass this behavior. Simply make a $model_file variable, while never touching the original $model’s case. grin
Here are the edits:

new lines 153 through 160

// BEGIN CUSTOM EDIT <AnyCase ModelNames>
$model_file strtolower($model);

if ( ! 
file_exists(APPPATH.'models/'.$path.$model_file.EXT))
{
    show_error
('Unable to locate the model you have specified: '.$model_file);
}
// END CUSTOM EDIT <AnyCase ModelNames> 

and

new lines 175 through 180

// BEGIN CUSTOM EDIT <AnyCase ModelNames>
require_once(APPPATH.'models/'.$path.$model_file.EXT);

// No longer needed under <AnyCase ModelNames>
// $model = ucfirst($model);
// END CUSTOM EDIT <AnyCase ModelNames> 

And there you have it! You can name your Model something like AwesomeModel now, and it should work, as long as you’re doing everything else right! grin

I have yet to look at the loaders for views or controllers, because the user guide entries for them didn’t mention any odd naming requirements.

Also, I have done a bit of testing with this, but I’m in no way familiar enough with this system to say that this is 100% error proof. I don’t know if this is something that is supposed to happen or not, or if it has other effects that I’m not aware of. If you spot something that acts up as a direct result of my code change, let me know and I’ll look into it!

However, I hope this helps you!

Regards,
Andrew

 
Posted: 17 July 2008 09:14 AM   [ # 1 ]   [ Rating: 0 ]
Joined: 2006-07-14
4237 posts

I haven’t given it much thought because i like the recommended underscore between words rule but for people who follow the camelcase rule it is a limiting factor which isn’t necessary. I would change the code slightly different

if ( ! file_exists(APPPATH.'models/'.$path.strtolower($model).EXT))

require_once(
APPPATH.'models/'.$path.strtolower($model).EXT); 

The $model variable only needs to be manipulated in those two cases so why would you create a variable only to be used in those two lines.

 
Posted: 17 July 2008 09:19 AM   [ # 2 ]   [ Rating: 0 ]
Joined: 2008-07-17
2 posts
xwero - 17 July 2008 01:14 PM

I haven’t given it much thought because i like the recommended underscore between words rule but for people who follow the camelcase rule it is a limiting factor which isn’t necessary. I would change the code slightly different

if ( ! file_exists(APPPATH.'models/'.$path.strtolower($model).EXT))

require_once(
APPPATH.'models/'.$path.strtolower($model).EXT); 

The $model variable only needs to be manipulated in those two cases so why would you create a variable only to be used in those two lines.

Aha, it figures I would still be doing something silly even with such a little edit.
I like your style better as well grin

 
Posted: 28 November 2008 03:36 PM   [ # 3 ]   [ Rating: 0 ]
Avatar
Joined: 2008-07-16
411 posts

I have a model class called “MYModel” that is in the file “MYModel.php”. On my M$ localhost I can load it with

$this->load->model('MYModel'); 

However, this fails on a webserver (linux) stating the the model can’t be found. I looked through the code and found that the name of the model is strtolower() so my question is why does it work on my local machine?

 Signature 

My Blog, C2D, PHP Videos, Résumé, Super .htaccess, Extra hooks, and MicroMVC

 
Posted: 28 November 2008 06:46 PM   [ # 4 ]   [ Rating: 0 ]
Avatar
Joined: 2006-08-03
671 posts

Windows is case-insensitive when it comes to filenames, Linux/Unix based systems are case-sensitive.

 Signature 

RapidDataMapper: My new ORM, is now released!

IgnitedRecord: Old ORM

MPTtree: A model to handle trees in a database.

YAYParser - Yet Another YAML Parser