tags:

views:

114

answers:

4

hi again every one this is my third question so far on stackoverflow :D

i am defining files and their location on my first_run.php files, the files that i define here is those files containing classes, helper functions and any other files required

at early development, this first_run.php contains only a few lines of codes but the line is increasing gradually as i add some new classes or new files to be included

and since i group the file's location inside a particular folder, i figure that maybe i can scan the folder, put the name of the files retrieved into an array and then loop the require_once, so that i dont have to edit first_run.php every time i add a new file inside the folder.

my fisrt approach is using scandir()

before:

defined('INC_PATH') ? null : define('INC_PATH', SITE_ROOT.DS.'includes');
defined('MEMBERS') ? null : define('MEMBERS', INC_PATH.DS.'models'.DS.'members');

require_once(MEMBERS.DS.'member.php');
require_once(MEMBERS.DS.'phone.php');
require_once(MEMBERS.DS.'profile.php');
require_once(MEMBERS.DS.'talent.php');
require_once(MEMBERS.DS.'profile_picture.php');
require_once(MEMBERS.DS.'audio.php');
require_once(MEMBERS.DS.'video.php');
require_once(MEMBERS.DS.'gallery.php');
require_once(MEMBERS.DS.'statistik.php');
require_once(MEMBERS.DS.'inbox.php');
require_once(MEMBERS.DS.'comment.php');
require_once(MEMBERS.DS.'picked_stat.php');
require_once(MEMBERS.DS.'log.php');

after is something like:

$member_files = scandir(MEMBERS);
foreach($member_files as $member_file):
    require_once(MEMBERS.DS.$member_file);
endforeach;

i havent try the 'after' code though. is this possible?? or is there any other approach?? or should i just leave it that way (keep adding the lines without scanning the files)

thanks in advance

+3  A: 

Consider using Autoloading instead.

With autoloading, you do not have to bother with including files at all. Whenever you instantiate a new class that is not known to PHP at that point, PHP will trigger the registered autoload function. The function includes the required files then. This way, you only load what you need when you need it, which should increase performance.

Simple example with PHP5.3

spl_autoload_register(function($className) {
    include "/path/to/lib/and/$className.php";    
});
$foo = new Foo;

When you call new Foo, the registered autoload function will try to include the class from /path/to/lib/and/Foo.php. It is advisable to use a classname convention, like f.i. PEAR, to make finding files easier and to cut down on the amount of include_paths.

For additional security and speed, you can provide a more sophisticated Autoloader that uses an array to map from classname to filename, thus making sure only files that actually are part of your application can get included.

Further reading:

Gordon
currently reading the manual....thanks
littlechad
lotta home work to do, thanks for this valuable information
littlechad
+1  A: 

It's possible, but not recommended, like what if somebody could create a php file on that directory, you'll end up including it, besides, you can't predict the inclusion order.

Try this instead:

$includes=array(
  'member',
  'phone',
  'profile',
  'talent',
);

foreach($includes as $fname) {
  require_once(MEMBERS.DS.$fname. '.php');

}

If you were using classes, consider using autoloading, as @Gordon suggested. And if you werent using classes, consider using them :)

aularon
+1 on the inability to predict the inclusion order.
kitsched
same question asked to @NullUserException; so the best practice to do this is that i should stick to what i am currently doing (editing first_run.php if a new file is created) ??
littlechad
If these files contain classes, the best way is to use autoloading, if some of them contain some settings or bases classes (ones that are _always_ used). I believe the code you posted at first is the best way, the way I posted minimize the code and makes it a bit quicker to add a new inclusion file, to demonstrate how such thing can be done, but it's not better :)
aularon
A: 

At a first glance your code could work, although you have to ignore "." and ".." in the foreach loop. Plus I'd check, if the file ends with ".php":

$member_files = scandir(MEMBERS.DS);
foreach($member_files as $member_file) {
    // Ignore non php files and thus ".." & "."
    if (!preg_match('/\.php$/', $member_file) {
      continue;
    }
    require_once(MEMBERS.DS.$member_file);
}
softcr
A: 

create 2 functions

function GetFiles($directory,$exempt = array('.','..','.ds_store','.svn'),&$files = array()) {
    $handle = opendir($directory);
    while(false !== ($resource = readdir($handle))){
        if(!in_array(strtolower($resource),$exempt)){
            if(is_dir($directory.$resource.'/'))
                array_merge($files, self::GetFiles($directory.$resource.'/',$exempt,$files));
            else
                $files[] = $directory.$resource;
        }
    }
    closedir($handle);
    return $files;
  }


  function Autoload($includes = array()){
    $files = array();
    foreach($includes as $directory)
      $files[] = self::GetFiles($directory);

    foreach($files as $k=>$v){
      foreach($v as $k1=>$v1)
        require_once($v1);
    }
  }

to use it:
$includes = array(
    'C:WWW/project/helpers/',
    'C:WWW/project/lang/',
    'C:WWW/project/lib/',
    'C:WWW/project/mod/',
  );
Autoload($includes);