自动装载机的function

上周我了解到,通过编写__autoload()函数,类可以包含在您的项目中。 然后我了解到使用自动加载器不仅是一种技术,而且是一种模式。

现在我在我的项目中使用自动加载器,我发现它非常有用。 我想知道是否可以用function做同样的事情。 忘记在其中包含正确的PHP文件是非常有用的。

那么,是否可以创build一个函数自动加载器?

function没有自动装载function。 你有四个现实的解决scheme:

  1. 将所有函数包装到名称空间类(适当的上下文)中。 假设你有一个叫做string_get_letters的函数。 您可以将其添加到名为StringFunctions的类作为静态函数。 所以不要调用string_get_letters() ,而是调用StringFunctions::get_letters() 。 然后你会__autoload这些名称空间的类。

  2. 预加载所有function。 既然你正在使用类,你不应该有这么多的function,所以只要预先加载它们。

  3. 在使用它们之前加载函数。 在每个文件中, require_once将在该文件中使用的函数文件。

  4. 首先不要使用函数。 如果你正在开发OOP代码(看起来好像你是这样),那么根本不需要任何function。 所有你需要的function(或多个),你可以build立一个面向对象的方式,并避免function的需要。

就个人而言,我会build议1,2或4取决于您的确切需要和您的代码库的质量和大小…

如果您在项目中使用Composer,则可以将文件指令添加到自动载入部分。

这实际上会在自动加载器中生成一个require_once,但感觉就像是真正的自动加载,因为你不需要照顾它。
它不是懒加载。

来自Assetic的示例 :

 "autoload": { "psr-0": { "Assetic": "src/" }, "files": [ "src/functions.php" ] } 

我读了一些关于一个丑恶的黑客攻击致命错误,试图包括和执行缺失的function,但我绝对不会走这条路。

你最接近的是__call() 魔术方法 ,这是方法而不是函数的__autoload() 。 这可能足够满足您的需求; 如果你有能力打电话给一个class,并分别要求每个不同的function。 从PHP 5.3.0开始,你也有__callStatic()

一个使用__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); 

这将调用./path/to/functions/functionToLoad.php中定义的functionToLoad()函数。

那么像往常一样,有一个PECL的延伸:

  • 自动映射PECL

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

它应该自动加载函数以及类。 然而,哪一个不适用于当前的PHP解释器。

(一个替代选项btw,正在生成存根函数,加载和运行命名空间对应。)

话虽如此。 自动加载不被普遍认为是一种好的做法。 它导致了过分破碎的阶级等级和对象的幸福。 而PHP自动加载的真正原因是因为包含和依赖pipe理系统不成熟。

 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); } } 

使用命名空间,我们可以这样做: Fn::myFunc()spl_autoload_register() 。 我已经在https://goo.gl/8dMIMj的例子中使用了这段代码;

这是另一个相当复杂的例子,根据这个讨论的build议。 代码也可以在这里看到: 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); } } 

虽然你不能自动加载函数和常量,你可以使用jesseschalken / autoload生成器 ,它会自动检测哪些文件包含不能被自动加载和急切加载的东西。

将所有function文件包含在一个文件中,然后包含它

//文件1
db_fct.php

//文件2
util_fct.php

//在一个functions.php中包含所有其他文件

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

包含functions.php,每当你需要function..

尝试这个

 if ($handle = opendir('functions')) { while (false !== ($entry = readdir($handle))) { if (strpos($entry, '.php') !== false) { include("functions/$entry"); } } closedir($handle); }