6dc0e9a07bcff97ac9b111f36e12f1f6

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.

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 !

5a00a3a98dcf6f9cd717440fd2b606e5

Eineki

August 22, 2008, August 22, 2008 01:12, permalink

No rating. Login to rate!

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
	//...
?>
6dc0e9a07bcff97ac9b111f36e12f1f6

Ishkur

August 22, 2008, August 22, 2008 20:07, permalink

No rating. Login to rate!

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.

441c4f02db55ef2cbe96027af7012e01

Tim

August 22, 2008, August 22, 2008 21:43, permalink

No rating. Login to rate!

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();
5a00a3a98dcf6f9cd717440fd2b606e5

Eineki

August 23, 2008, August 23, 2008 13:49, permalink

No rating. Login to rate!

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
	//...
?>
6dc0e9a07bcff97ac9b111f36e12f1f6

Ishkur

August 24, 2008, August 24, 2008 04:01, permalink

No rating. Login to rate!

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!

Your refactoring





Format Copy from initial code

or Cancel