253

In PHP can I include a directory of scripts?

i.e. Instead of:

include('classes/Class1.php');
include('classes/Class2.php');

is there something like:

include('classes/*');

Couldn't seem to find a good way of including a collection of about 10 sub-classes for a particular class.

Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
occhiso
  • 3,161
  • 4
  • 22
  • 16
  • If you are using php 5 you might want to use [autoload](http://www.php.net/autoload) instead. – SorinV Mar 01 '09 at 11:44

15 Answers15

478
foreach (glob("classes/*.php") as $filename)
{
    include $filename;
}
Karsten
  • 14,572
  • 5
  • 30
  • 35
  • 6
    I thought there would be a cleaner looking way using include(). But this will do just fine. Thanks everyone. – occhiso Mar 01 '09 at 11:46
  • 5
    I would build a proper module system with a configuration file, but that's just because I find that much more flexible than just including *everything*. :-) – staticsan Mar 02 '09 at 00:01
  • 4
    Attention, only works for including files in the current directory. It would be possible to iterate through get_include_path(), but this get tedious quickly. – nalply Nov 18 '11 at 11:13
  • thats very slick... nice one.. just what I was after – Alex Feb 01 '13 at 06:14
  • 24
    This method is not good when requiring classes that are extending a base class: eg if BaseClass shows up in the array AFTER ExtendedClass, it wont work! – Carmageddon May 13 '13 at 16:12
  • @Carmageddon correct. For this case, I have to "require_once" the base class first, then other classes that depend on it. Suggest to use `require_once()` or `include_once()` instead of `include` – Raptor Jul 12 '13 at 06:49
  • 2
    @nalply `get_include_path()` still cannot auto determine the loading order ( base class may be loaded AFTER extended class , resulting errors ) – Raptor Jul 12 '13 at 06:51
  • it's not really "fraught with problems", you just don't have much control over the order that files are included in. This won't matter for many people in many situations. As is mentioned elsewhere on this page, if you need something more complex, you might want to consider auto loading. – David Meister Jun 21 '14 at 12:22
  • @nalply There are use cases for this. A config folder for example in which case this is the perfect futureproof way to handle loading config (rather than having to always name your config files a particular way). This answer helped me greatly, so +1. – lassombra Oct 20 '14 at 18:01
  • if you're using classes then use autoloading – Ejaz Feb 17 '16 at 15:01
  • 2
    I would change glob to "glob( _ _DIR_ _ ."/src/**/*.php")" – Kanaris007 Jul 14 '17 at 05:27
  • Perfect comment, @nalply !! This solution DOES NOT enter sub directories in the folder that may contain php files. Get only php files in the current folder. My solution for a full recursive include *.php is in a post bellow this. Search this page for "NO dependencies" – Sergio Abreu May 16 '21 at 15:07
  • @Carmageddon that why I used subfolder for child class after included all parents class. – fdrv Nov 24 '21 at 14:17
  • @fdrv its been years since I worked on PHP tech stack, but I believe today, you are supposed to build your solution on one of the established frameworks such as Laravel etc., and class loading would be handled inside. No need to reinvent the wheel anymore unless you are still working with legacy code. – Carmageddon Nov 25 '21 at 15:26
  • @Carmageddon in wordpress we do not have any frame work =) – fdrv Nov 26 '21 at 16:02
48

Here is the way I include lots of classes from several folders in PHP 5. This will only work if you have classes though.

/*Directories that contain classes*/
$classesDir = array (
    ROOT_DIR.'classes/',
    ROOT_DIR.'firephp/',
    ROOT_DIR.'includes/'
);
function __autoload($class_name) {
    global $classesDir;
    foreach ($classesDir as $directory) {
        if (file_exists($directory . $class_name . '.php')) {
            require_once ($directory . $class_name . '.php');
            return;
        }
    }
}
Cheekysoft
  • 35,194
  • 20
  • 73
  • 86
Marius
  • 57,995
  • 32
  • 132
  • 151
  • 4
    Autoload is not relevant because this question was about including everything in a directory - usually this would be in different directories: eg DataClass defined in BE directory and BL.class.php defined in BL directory. – Carmageddon May 13 '13 at 15:52
  • 1
    Using globals is not a solution – Peter Nov 21 '14 at 15:34
  • I would advise using composer (https://getcomposer.org/) if you need autoloading instead of a customized autoloading solution like what is shown here. – Kelt Feb 16 '17 at 20:08
  • This does not include any file in the directory that does not contain a class – Nico Haase Jul 04 '20 at 10:42
  • As of https://www.php.net/manual/en/function.autoload.php. "This function has been DEPRECATED as of PHP 7.2.0, and REMOVED as of PHP 8.0.0. Relying on this function is highly discouraged." – Maciek Semik Jan 03 '23 at 19:24
33

I realize this is an older post BUT... DON'T INCLUDE YOUR CLASSES... instead use __autoload

function __autoload($class_name) {
    require_once('classes/'.$class_name.'.class.php');
}

$user = new User();

Then whenever you call a new class that hasn't been included yet php will auto fire __autoload and include it for you

Banning
  • 2,279
  • 2
  • 16
  • 20
  • 1
    While this was a solid answer when it was posted, as of PHP7.2.0 this method has been deprecated and shouldn't be used. Instead, use [spl_autoload_register](http://php.net/manual/en/function.spl-autoload-register.php). – Josh Aug 13 '18 at 11:28
  • 1
    This is a way better answer if the purpose is to include CLASSES. – Blackbam Nov 13 '18 at 16:32
  • This does not include any file in the directory that does not contain a class – Nico Haase Jul 04 '20 at 10:42
  • 1
    As of https://www.php.net/manual/en/function.autoload.php. "This function has been DEPRECATED as of PHP 7.2.0, and REMOVED as of PHP 8.0.0. Relying on this function is highly discouraged." – Maciek Semik Jan 03 '23 at 19:25
21

this is just a modification of Karsten's code

function include_all_php($folder){
    foreach (glob("{$folder}/*.php") as $filename)
    {
        include $filename;
    }
}

include_all_php("my_classes");
foobar
  • 235
  • 2
  • 2
20

How to do this in 2017:

spl_autoload_register( function ($class_name) {
    $CLASSES_DIR = __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR;  // or whatever your directory is
    $file = $CLASSES_DIR . $class_name . '.php';
    if( file_exists( $file ) ) include $file;  // only include if file exists, otherwise we might enter some conflicts with other pieces of code which are also using the spl_autoload_register function
} );

Recommended by PHP documentation here: Autoloading classes

Sorin C
  • 984
  • 10
  • 8
  • 4
    This doesn't answer a question, because `autoload` will come in play only when someone tries i.e. to create object of the class which was not yet loaded. – The Godfather Jun 08 '19 at 10:44
  • This does not include any file in the directory that does not contain a class, and it only includes those files that contain a class that is used – Nico Haase Jul 04 '20 at 10:42
10

You can use set_include_path:

set_include_path('classes/');

http://php.net/manual/en/function.set-include-path.php

talha2k
  • 24,937
  • 4
  • 62
  • 81
albanx
  • 6,193
  • 9
  • 67
  • 97
  • 14
    It doesn't include automatically all the php-files in the directory, just enables to omit `classes/` when using `include`/`require` – Gherman Feb 27 '14 at 08:50
  • Please explain how that could work if any of these files would not contain a class – Nico Haase Jul 04 '20 at 10:41
4

If there are NO dependencies between files... here is a recursive function to include_once ALL php files in ALL subdirs:

$paths = [];

function include_recursive( $path, $debug=false){
  foreach( glob( "$path/*") as $filename){        
    if( strpos( $filename, '.php') !== FALSE){ 
       # php files:
       include_once $filename;
       if( $debug) echo "<!-- included: $filename -->\n";
    }  elseif( is_dir($filename)) { # dirs
       $paths[] = $filename; 
    }
  }
  # Time to process the dirs:
  for( $i=count($paths)-1; $i>=0; $i--){
    $path = $paths[$i];
    unset( $paths[$i]);
    include_recursive( $path, $debug);
  }
}

include_recursive( "tree_to_include");
# or... to view debug in page source:
include_recursive( "tree_to_include", 'debug');
Sergio Abreu
  • 2,686
  • 25
  • 20
  • Cannot edit this answer due to too many pending edits on SO, but the `$i>0` should be `$i>=0` and the `else { #dirs` should be `elseif (is_dir($filename)) { #dirs` . – Roemer Feb 17 '23 at 16:40
  • 1
    Thanks. When I dit it almost 14 years ago I thought about a directory with ONLY php files and directories containing php files, so, if the file name didn't have '.php' would be a dir. – Sergio Abreu Feb 18 '23 at 17:15
  • 1
    After 14 years it is still found and used! – Roemer Feb 18 '23 at 20:54
  • 1
    There you go. Upvote after 14 years. – Roemer Feb 20 '23 at 15:05
3
<?php
//Loading all php files into of functions/ folder 

$folder =   "./functions/"; 
$files = glob($folder."*.php"); // return array files

 foreach($files as $phpFile){   
     require_once("$phpFile"); 
}
Mr Genesis
  • 170
  • 3
  • Please add some more explanation to your code, especially as this question already has a lot of upvoted answers – Nico Haase May 23 '19 at 11:09
2

If you want include all in a directory AND its subdirectories:

$dir = "classes/";
$dh  = opendir($dir);
$dir_list = array($dir);
while (false !== ($filename = readdir($dh))) {
    if($filename!="."&&$filename!=".."&&is_dir($dir.$filename))
        array_push($dir_list, $dir.$filename."/");
}
foreach ($dir_list as $dir) {
    foreach (glob($dir."*.php") as $filename)
        require_once $filename;
}

Don't forget that it will use alphabetic order to include your files.

  • 3
    "Don't forget that it will use alphabetic order" Wrong... `The entries are returned in the order in which they are stored by the filesystem.` - http://php.net/manual/en/function.readdir.php – NemoStein Jul 17 '15 at 03:47
  • 1
    This might not work if the files are dependent on each other and the order doesn't match the dependency – Amanuel Nega May 07 '16 at 08:21
1

If your looking to include a bunch of classes without having to define each class at once you can use:

$directories = array(
            'system/',
            'system/db/',
            'system/common/'
);
foreach ($directories as $directory) {
    foreach(glob($directory . "*.php") as $class) {
        include_once $class;
    }
}

This way you can just define the class on the php file containing the class and not a whole list of $thisclass = new thisclass();

As for how well it handles all the files? I'm not sure there might be a slight speed decrease with this.

patstuart
  • 1,931
  • 1
  • 19
  • 29
Scott Dawson
  • 791
  • 1
  • 6
  • 15
1

Answer ported over from another question. Includes additional info on the limits of using a helper function, along with a helper function for loading all variables in included files.

There is no native "include all from folder" in PHP. However, it's not very complicated to accomplish. You can glob the path for .php files and include the files in a loop:

foreach (glob("test/*.php") as $file) {
    include_once $file;
}

In this answer, I'm using include_once for including the files. Please feel free to change that to include, require or require_once as necessary.

You can turn this into a simple helper function:

function import_folder(string $dirname) {
    foreach (glob("{$dirname}/*.php") as $file) {
        include_once $file;
    }
}

If your files define classes, functions, constants etc. that are scope-independent, this will work as expected. However, if your file has variables, you have to "collect" them with get_defined_vars() and return them from the function. Otherwise, they'd be "lost" into the function scope, instead of being imported into the original scope.

If you need to import variables from files included within a function, you can:

function load_vars(string $path): array {
    include_once $path;
    unset($path);
    return get_defined_vars();
}

This function, which you can combine with the import_folder, will return an array with all variables defined in the included file. If you want to load variables from multiple files, you can:

function import_folder_vars(string $dirname): array {
    $vars = [];
    foreach (glob("{$dirname}/*.php") as $file) {

        // If you want to combine them into one array:
        $vars = array_merge($vars, load_vars($file)); 

        // If you want to group them by file:
        // $vars[$file] = load_vars($file);
    }
    return $vars;
}

The above would, depending on your preference (comment/uncomment as necessary), return all variables defined in included files as a single array, or grouped by the files they were defined in.

On a final note: If all you need to do is load classes, it's a good idea to instead have them autoloaded on demand using spl_autoload_register. Using an autoloader assumes that you have structured your filesystem and named your classes and namespaces consistently.

Markus AO
  • 4,771
  • 2
  • 18
  • 29
0

I suggest you use a readdir() function and then loop and include the files (see the 1st example on that page).

Stiropor
  • 453
  • 3
  • 7
0

Try using a library for that purpose.

That is a simple implementation for the same idea I have build. It include the specified directory and subdirectories files.

IncludeAll

Install it via terminal [cmd]

composer install php_modules/include-all

Or set it as a dependency in the package.json file

{
  "require": {
    "php_modules/include-all": "^1.0.5"
  }
}

Using

$includeAll = requires ('include-all');

$includeAll->includeAll ('./path/to/directory');
0

This is a late answer which refers to PHP > 7.2 up to PHP 8.

The OP does not ask about classes in the title, but from his wording we can read that he wants to include classes. (btw. this method also works with namespaces).

By using require_once you kill three mosquitoes with one towel.

  • first, you get a meaningful punch in the form of an error message in your logfile if the file doesn't exist. which is very useful when debugging.( include would just generate a warning that might not be that detailed)
  • you include only files that contain classes
  • you avoid loading a class twice
spl_autoload_register( function ($class_name) {
    require_once  '/var/www/homepage/classes/' . $class_name . '.class.php';
} );

this will work with classes

new class_name;

or namespaces. e.g. ...

use homepage\classes\class_name;
-1

Do no write a function() to include files in a directory. You may lose the variable scopes, and may have to use "global". Just loop on the files.

Also, you may run into difficulties when an included file has a class name that will extend to the other class defined in the other file - which is not yet included. So, be careful.

bimal
  • 37
  • 2
    What do you mean by "lose the variable scopes" ? – piyush Sep 25 '12 at 09:21
  • 3
    You should always use a function if you are going to reuse, or just simply to make the code more "self-documenting". The issue of "global scope" I think is a red-herring. Any time you are using "global scope" you want to think seriously about rewriting your code to avoid it. – Stave Escura Feb 11 '13 at 15:03