简化递归PHP
我一直在研究一种在php中使用_autoload()函数递归包含文件的方法。这样,您可以将类放到“classes”文件夹中的任何位置,并按子目录组织它们,但是_autoload函数仍然能够找到它们。这就是我到目前为止所得到的,我想知道是否有人能帮我简化它,这样它就不会那么长了它目前功能齐全,工作起来很有魅力。我只是想把它缩短。简化递归PHP,php,class,recursion,include,include-path,Php,Class,Recursion,Include,Include Path,我一直在研究一种在php中使用_autoload()函数递归包含文件的方法。这样,您可以将类放到“classes”文件夹中的任何位置,并按子目录组织它们,但是_autoload函数仍然能够找到它们。这就是我到目前为止所得到的,我想知道是否有人能帮我简化它,这样它就不会那么长了它目前功能齐全,工作起来很有魅力。我只是想把它缩短。 <?php function readRecursive($path){ if(!is_dir($path)){ return false;
<?php
function readRecursive($path){
if(!is_dir($path)){
return false;
}
$dir = glob($path ."/*");
$retArr = array();
foreach($dir as $f){
if(is_dir($f)){
$m = readRecursive($f);
foreach($m as $n){
$retArr[] = $n;
}
}else{
$retArr[] = $f;
}
}
return $retArr;
}
function endsWith($haystack, $needle){
return $needle === "" || substr($haystack, -strlen($needle)) === $needle;
}
/* Set up AutoLoading for object classes */
function __autoload($class_name){
$classes = readRecursive("classes");
foreach($classes as $class){
if(endsWith(strtolower($class), strtolower($class_name.".class.php"))){
include_once ($class);
}
}
}
您可以使用
递归地遍历目录。这可能会简化您的功能
function getRecursive($path){
$files = array();
$dir_iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS),RecursiveIteratorIterator::SELF_FIRST);
foreach ($dir_iterator as $item) {
$subPath = $dir_iterator->getSubPathName();
if($item->isDir())
$files[$subPath] = array();
else
$files[$subPath][] = $subPath;
}
return $files;
}
这是我为你尝试的自动加载。
我稍微修改了
首先,我将向您展示我的类的文件结构:
正如您在上面所看到的,这些类被设置为单独的文件,以便显示
现在接受埃米尔的答案并稍加修改:
(如果文件名类似于上面在文件结构中看到的“Class.php”)
将保证返回如下文件数组[FILE\u NAME]=>[PATH\u NAME]
:
Array
(
[Error.php] => /home2/DERP/public_html/something.com/watch/model/Site/Error.php
[Form.php] => /home2/DERP/public_html/something.com/watch/model/Site/Form.php
[Site.php] => /home2/DERP/public_html/something.com/watch/model/Site/Site.php
[Db.php] => /home2/DERP/public_html/something.com/watch/model/Database/Db.php
[Db_pdo.php] => /home2/DERP/public_html/something.com/watch/model/Database/Db_pdo.php
[Session.php] => /home2/DERP/public_html/something.com/watch/model/Security/Session.php
[Auth.php] => /home2/DERP/public_html/something.com/watch/model/Security/Auth.php
[Input.php] => /home2/DERP/public_html/something.com/watch/model/Security/Input.php
[Postcode.php] => /home2/DERP/public_html/something.com/watch/model/Postcode.php
[Rep.php] => /home2/DERP/public_html/something.com/watch/model/User/Rep.php
[User.php] => /home2/DERP/public_html/something.com/watch/model/User/User.php
[Notifications.php] => /home2/DERP/public_html/something.com/watch/model/User/Notifications.php
[Log.php] => /home2/DERP/public_html/something.com/watch/model/Log/Log.php
[Hook.php] => /home2/DERP/public_html/something.com/watch/model/Hook.php
)
现在,它将被以下内容调用:
getClasses(realpath(dirname(\uu文件))./model')
function getClasses($path) {
$files = array();
$dir_iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST);
foreach ($dir_iterator as $item) {
$pathname = $item->getPathName();
$filename = $item->getFileName();
if ($item->isDir()) {
getClasses($item);
} else {
$files[$filename] = $pathname;
}
}
return $files;
}
允许我们运行\uuu autoload()
,如下所示:
$model_classes = getClasses(realpath(dirname(__FILE__)) . '/model');
function __autoload($class_name) {
global $model_classes;
$filename = ucfirst($class_name) . '.php';
$model = $filename;
if (!isset($model_classes[$model])) {
// dead
return false;
} else {
// include first file (model)
include($model_classes[$model]);
}
}
现在
显然,您不应该使用global
,但对我来说,它似乎是在\uu autoload()
函数中每次运行getClasses()
函数的更好选择
function getRecursive($path){
$files = array();
$dir_iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS),RecursiveIteratorIterator::SELF_FIRST);
foreach ($dir_iterator as $item) {
$subPath = $dir_iterator->getSubPathName();
if($item->isDir())
$files[$subPath] = array();
else
$files[$subPath][] = $subPath;
}
return $files;
}
如果其他人有什么要补充的,请随意!我只是尝试了一下我自己的小方法,它没有缺点
注意:我以前使用的是file_exists()
,我认为上面的方法是;快多了
更新
就在前几天晚上,我有一个脑波,我在想;
“为什么不扫描应用程序根并获取所有php文件,然后运行一个函数来检查所述文件是否确实包含一个类,以使其尽可能通用…”
所以我做了一点研究,从php中发现了这个漂亮的小函数:
现在经过一点挖掘,我找到了这个答案:
经过一些修改后,getClasses()
函数现在如下所示:
function getClasses($path) {
$files = array();
$dir_iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST);
foreach ($dir_iterator as $item) {
$pathname = $item->getPathName();
$filename = $item->getFileName();
if ($item->isDir()) {
get_classes($item);
} else {
if (substr($filename, -4) === '.php') {
if (get_php_classes(file_get_contents($pathname))) {
$files[$filename] = $pathname;
}
}
}
}
return $files;
}
通过添加上述问题中的新功能:
function get_php_classes($php_code) {
$tokens = token_get_all($php_code);
$class_token = false;
foreach ($tokens as $token) {
if (is_array($token)) {
if ($token[0] == T_CLASS) {
$class_token = true;
} else if ($class_token && $token[0] == T_STRING) {
$classes[] = $token[1];
// $class_token = false;
}
}
}
return $class_token;
}
现在,您只需运行一个$classes=getClasses(ROOTPATH)
,并对它们进行编辑
失败:每个类都必须具有唯一的类名和/或文件名。除非有人能帮忙修改以允许。举个例子,请看你的函数将加载以$name..class.php“
结尾的每个文件,不管整个目录树中有多少这样的文件。如果这是有意的,那么(对那些将要使用的人来说)Behavior为什么不使用composer autoloader是非常奇怪和不清楚的?begin的类映射。@AlmaDo否,它将只包括自动加载函数所需的特定文件。@AlmaDo它将包括两个foo类。然而,为什么任何开发人员都会有多个同名的类呢?。。如果这真的成为了一个问题,for循环中总会有一个中断,只包含函数出现的第一个循环。