Autoloader for functions

Last week, I found out that classes can be included in your project by writing the __autoload() function. Then I found out that using the autoloader is not only a technique, but also a template.

Now I use autoloader in my project, and I found it very useful. I was wondering if you can do the same with functions. It would be very useful to forget about including the right PHP file with functions inside it.

So, is it possible to create an autoloader function?

+51
function php class autoloader
Jan 19 '11 at 15:36
source share
11 answers

There is no autoloader function for functions. You have four realistic solutions:

  • Wrap all functions in name classes (appropriate context). So, let's say you have a function called string_get_letters . You can add this to a class called StringFunctions as a static function. So instead of calling string_get_letters() you call StringFunctions::get_letters() . Then you would have to __autoload those classes with names.

  • Preload all features. Since you use classes, you should not have such functions, so just load them.

  • Download functions before using them. In each require_once file, the function files that will be used in this file.

  • Do not use functions first. If you are developing OOP code (which, it seems to you, in any case), it does not need any functions at all. All that you need a function for (or several) for, you could create an OO method and avoid the need for functions.

Personally, I offer you 1, 2, or 4, depending on your specific need and the quality and size of your code base ...

+57
Jan 19 '11 at 15:43
source share

If you use Composer in your project, you can add the files directive to the startup section.

This will not lead to the creation of require_once in the autoloader, but it seems like a real autoload because you do not need to do this.
Its not lazy loading though.

Example from Assetic :

 "autoload": { "psr-0": { "Assetic": "src/" }, "files": [ "src/functions.php" ] } 
+32
Jul 29 '13 at 13:31 on
source share

I read something about an ugly hack that caused fatal errors and tried to enable and perform the missing functions, but I would definitely not go down this road.

The closest thing you have is the magic __call() method , which is a kind of __autoload() for methods, not functions. This may be enough for your needs; if you can afford to call a class and require each individual function separately. Starting with PHP 5.3.0, you also have __callStatic() .

Example using __callStatic() :

 class Test { public function __callStatic($m, $args) { if (function_exists($m) !== true) { if (is_file('./path/to/functions/' . $m . '.php') !== true) { return false; } require('./path/to/functions/' . $m . '.php'); } return call_user_func_array($m, $args); } } Test::functionToLoad(1, 2, 3); 

This will call the functionToLoad() defined in. / Path / to / functions / functionToLoad.php.

+15
Jan 19 '11 at 16:07
source share

Well, as usual, there is a PECL extension for this:

(via: http://phk.tekwire.net/joomla/support/doc/automap.htm )

It should perform startup functions, as well as classes. What else does not work with the current PHP interpreter.

(An alternative to btw, generates stub functions that load and run associated instance instances.)

It is said. Autostart is not always considered good practice. This leads to overly fragmented class hierarchies and an object of happiness. And the real reason PHP has autoload is because inclusion and dependency management systems are inmature.

+7
Jan 19 '11 at 16:15
source share
 namespace MyNamespace; class Fn { private function __construct() {} private function __wakeup() {} private function __clone() {} public static function __callStatic($fn, $args) { if (!function_exists($fn)) { $fn = "YOUR_FUNCTIONS_NAMESPACE\\$fn"; require str_replace('\\', '/', $fn) . '.php'; } return call_user_func_array($fn, $args); } } 

And using namespaces, we can do: Fn::myFunc() and spl_autoload_register() . I used this code with examples: https://goo.gl/8dMIMj

+2
Mar 15 '14 at 3:03
source share

new Functions \ Debug () will load functions into the root namespace.

 namespace Functions
 {

     class debug
     {
     }
 }
 namespace
 {

     if (! function_exists ('printr')) {

         / **
          *
          * @param mixed $ expression
          * /
         function printr ()
         {
             foreach (func_get_args () as $ v) {
                 if (is_scalar ($ v)) {
                     echo $ v.  "\ n";
                 } else {
                     print_r ($ v);
                 }
             }
             exit ();
         }
     }
 }
+1
Nov 28 '17 at 13:02
source share

I use class and __invoke . The __invoke method __invoke called when the script calls the class as a function. I often do something like this:

 <?php namespace API\Config; class Slim { function __invoke() { return [ 'settings' => [ 'displayErrorDetails' => true, 'logger' => [ 'name' => 'api', 'level' => Monolog\Logger\Logger::DEBUG, 'path' => __DIR__ . '/../../logs/api.log', ], ] ]; } } 

Then I can call as a function:

 $config = API\Config\Slim; $app = Slim\App($config()) 
+1
Sep 24 '18 at 22:39
source share

Here is another pretty complicated example based on the suggestions in this discussion. The code can also be seen here: lib / btr.php

 <?php /** * A class that is used to autoload library functions. * * If the function btr::some_function_name() is called, this class * will convert it into a call to the function * 'BTranslator\some_function_name()'. If such a function is not * declared then it will try to load these files (in this order): * - fn/some_function_name.php * - fn/some_function.php * - fn/some.php * - fn/some/function_name.php * - fn/some/function.php * - fn/some/function/name.php * The first file that is found will be loaded (with require_once()). * * For the big functions it makes more sense to declare each one of them in a * separate file, and for the small functions it makes more sense to declare * several of them in the same file (which is named as the common prefix of * these files). If there is a big number of functions, it can be more * suitable to organize them in subdirectories. * * See: http://stackoverflow.com/questions/4737199/autoloader-for-functions */ class btr { /** * Make it TRUE to output debug info on '/tmp/btr.log'. */ const DEBUG = FALSE; /** * The namespace of the functions. */ const NS = 'BTranslator'; /** * Relative directory where the functions are located. */ const FN = 'fn'; private function __construct() {} private function __wakeup() {} private function __clone() {} /** * Return the full name (with namespace) of the function to be called. */ protected static function function_name($function) { return self::NS . '\\' . $function; } /** * Return the full path of the file to be loaded (with require_once). */ protected static function file($fname) { return dirname(__FILE__) . '/' . self::FN . '/' . $fname . '.php'; } /** * If a function does not exist, try to load it from the proper file. */ public static function __callStatic($function, $args) { $btr_function = self::function_name($function); if (!function_exists($btr_function)) { // Try to load the file that contains the function. if (!self::load_search_dirs($function) or !function_exists($btr_function)) { $dir = dirname(self::file($fname)); $dir = str_replace(DRUPAL_ROOT, '', $dir); throw new Exception("Function $btr_function could not be found on $dir"); } } return call_user_func_array($btr_function, $args); } /** * Try to load files from subdirectories * (by replacing '_' with '/' in the function name). */ protected static function load_search_dirs($fname) { do { self::debug($fname); if (file_exists(self::file($fname))) { require_once(self::file($fname)); return TRUE; } if (self::load_search_files($fname)) { return TRUE; } $fname1 = $fname; $fname = preg_replace('#_#', '/', $fname, 1); } while ($fname != $fname1); return FALSE; } /** * Try to load files from different file names * (by removing the part after the last undescore in the functin name). */ protected static function load_search_files($fname) { $fname1 = $fname; $fname = preg_replace('/_[^_]*$/', '', $fname); while ($fname != $fname1) { self::debug($fname); if (file_exists(self::file($fname))) { require_once(self::file($fname)); return TRUE; } $fname1 = $fname; $fname = preg_replace('/_[^_]*$/', '', $fname); } return FALSE; } /** * Debug the order in which the files are tried to be loaded. */ public static function debug($fname) { if (!self::DEBUG) { return; } $file = self::file($fname); $file = str_replace(DRUPAL_ROOT, '', $file); self::log($file, 'Autoload'); } /** * Output the given parameter to a log file (useful for debugging). */ public static function log($var, $comment ='') { $file = '/tmp/btr.log'; $content = "\n==> $comment: " . print_r($var, true); file_put_contents($file, $content, FILE_APPEND); } } 
0
02 Sep '14 at
source share

As long as you cannot autoload functions and constants, you can use something like jesseschalken / autoload-generator , which will automatically determine which files contain things that can "autoload and download with impatience."

0
Jul 29 '15 at 12:37
source share

Include all function files in one file and then include it

// File 1
db_fct.php

// File 2
util_fct.php

// All other files are included in functions.php

 <?php require_once 'db_fct.php'; require_once 'util_fct.php'; ?> 

Turn on functions.php when you need functions.

0
Oct 21 '16 at 9:25
source share

try it

 if ($handle = opendir('functions')) { while (false !== ($entry = readdir($handle))) { if (strpos($entry, '.php') !== false) { include("functions/$entry"); } } closedir($handle); } 
-3
May 20 '15 at 19:26
source share



All Articles