code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
<?php function loadModel($model) { $exclude = array ( '.', '..', 'index.html' ); $handle = opendir(APPPATH.'models/'); while(false !== ($files = readdir($handle))) { if(!in_array($file, $exclude)) $modelArray[] = $files; } closedir($handle); if(in_array($model.EXT, $modelArray)) { require_once(APPPATH.'models/'.$model.EXT); } else { throw new Exception('Attempting to call unknown Model'); } } ?>
usage
1 2 3 4 5 6
<?php //... loadModel('blog');//Load blog model $posts = blog_model::getRecent; //... ?>
what I really want to be able to do
1 2 3 4 5 6 7 8
<?php //... $blogObject = loadModel('blog'); //assign object to a variable $posts = $blogObject::getRecent(); //... ?>
sidenotes
1 2 3
So far i've managed to get errors about my use of extraneous double colons, so im betting that php doesnt let me call methods statically like that. Any thoughts would be helpful.
Refactorings
No refactoring yet !
Eineki
August 22, 2008, August 22, 2008 01:12, permalink
You can't use a variable to reference a static metod using the static selector (::) until version 5.3 (see http://www.php.net/manual/it/language.oop5.paamayim-nekudotayim.php). In 5.3 the variable should contains the name of the class, not an instance of an object of the class.
Maybe, you can use the arrow operator on a not static method to solve your problem or use eval (ugly solution)
I don't know BareboneMVC but it seems to me there are some upgrade to your function.
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
<?php function loadModel($model) { // assume that the $model is an object declared in the file $model.EXT in the dir APPPATH.'/models/' $exclude = array ( '.', '..', 'index.html' ); if (!in_array($model, $exclude)) { if file_exists(APPPATH.'models/'.$model.EXT)) { require_once(APPPATH.'models/'.$model.EXT); // need to find a better solution for returning an instance of class $model eval "\$result= new $model();"; return $result; } } // if you get there you should throw an exception throw new Exception('Attempting to call unknown Model'); } ?>
More compact version
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
<?php function loadModel($model) { // assume that the $model is an object declared in the file $model.EXT in the dir APPPATH.'/models/' $exclude = array ('.', '..', 'index.html'); if (!in_array($model, $exclude) || file_exists(APPPATH.'models/'.$model.EXT)) { require_once(APPPATH.'models/'.$model.EXT); // need to find a better solution for returning an instance of class $model eval "\$result= new $model();"; return $result; } else { throw new Exception('Attempting to call unknown Model'); } } ?>
usage
1 2 3 4 5 6 7
<?php //... $blogObject = loadModel('blog'); //assign object to a variable $posts = $blogObject->getRecent(); // this works if getRecent is not a static method //... ?>
Ishkur
August 22, 2008, August 22, 2008 20:07, permalink
Wow, that refactoring is nifty. I have PHP 5.2.4 at the moment, and I'm working on installing 5.3. Hopefully I'll get something put together soon. Thanks a million for the input.
Tim
August 22, 2008, August 22, 2008 21:43, permalink
This will also work. You don't need to add the list of denied files, since $model will never equal it (. and .. and folders, and $model + EXT won't be a .html).
1 2 3 4 5 6 7 8 9 10 11 12 13
<?php function loadModel($model){ if (file_exists(APPPATH.'models/'.$model.EXT)) { require_once APPPATH.'models/'.$model.EXT; return new $model(); } else { throw new Exception('Attempting to call unknown Model'); } } $blogObject = loadModel('blog'); $posts = $blogObject->getRecent();
Eineki
August 23, 2008, August 23, 2008 13:49, permalink
If you use php 5.2 you can use the __autoload function (see http://www.php.net/manual/it/language.oop5.autoload.php) to load dinamically the class of the object may need. The only condition you have to fulfill is naming the file according to the class it contains (but you already do this).
1 2 3 4 5 6 7 8 9 10 11
<?php function __autoload($class_name) { $include_dirs = array('models/', 'generic/' ); // fill the array with appropiate dirs foreach ($include_dirs as $cur_dir) { if (file_exists(APPPATH.$cur_dir.$class_name.EXT)) { require_once APPPATH.$cur_dir.$class_name.EXT; return; } } ?>
#usage
1 2 3 4 5 6 7
<?php //... $blogObject = new blog() // was $blogObject = loadModel('blog'); $posts = $blogObject->getRecent(); // this works if getRecent is not a static method //... ?>
Ishkur
August 24, 2008, August 24, 2008 04:01, permalink
Very interesting ways of going about this, but I think I like the __autoload() approach a little more. I removed the loop (only because I have but one path I want to specify), but other than that it seems to work perfectly.
The problem with the other methods is that they mess up the inheritance of the model. getAll() is extended from a parent controller, and so when you simple 'return new $model();', it interferes with that for some reason, but the __autoload() seems to keep my inheritance in tact.
But still, thanks everyone!
I'm doing a lot of work with BareBonesMVC lately, and I've begun to see a need to add some more meat to it. One of the thing's that I'm trying to add is a method for loading models. The method itself is fairly straight forward, and works, but not the way I would really like for it to.