草庐IT

php - 简化的递归 PHP

coder 2024-05-03 原文

我一直在研究一种使用 php 中的 __autoload() 函数递归包含文件的方法。这样,您可以将您的类放在“classes”文件夹中的任何位置,并按子目录组织它们,但 __autoload 函数仍然能够找到它们。这是我到目前为止所得到的,并且想知道是否有人可以帮助我简化它以便它不会那么冗长。 它目前功能完备,工作起来很有魅力。我只是想让它更短。

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

?>

最佳答案

这是我为您自动加载的尝试。 我稍微修改了 Emil Condrea's Answer .

首先,我将向您展示我的类的文件结构:

正如您在上面看到的,这些类被设置到单独的文件中,以便显示。

现在采用 Emil 的回答并稍微修改一下: (前提是文件名类似于上面文件结构中的“Class.php”)

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

将保证返回文件数组,如以下 [FILE_NAME] => [PATH_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(__FILE__)) . '/model')

允许我们像下面这样运行 __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 但对我来说这似乎是一个比在 __autoload( ) 函数。

如果其他人有任何补充,请随意!我只是尝试了我自己的小方法,它没有错误!

注意:

我之前使用的是file_exists(),我认为上面的方法是;快多了。


更新

就在前几天晚上,我灵机一动,想到; “为什么不扫描应用程序根目录并获取所有 php 文件,然后运行一个函数来检查所述文件是否实际包含一个类,以使其尽可能通用......

所以我做了一些研究并从 php 中发现了这个漂亮的小函数:token_get_all()

现在,在深入了解 SO 之后,我找到了这个答案:Determine class in file...

经过一些修改,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) 并遍历它们。

缺点:每个类都必须具有唯一的类名/文件名。除非有人可以帮助进行修改以允许。

关于php - 简化的递归 PHP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23646989/

有关php - 简化的递归 PHP的更多相关文章

  1. ruby - 递归地将所有数字字符串转换为 Ruby 哈希中的整数 - 2

    我有一个随机大小的散列,它可能有类似"100"的值,我想将其转换为整数。我知道我可以使用value.to_iifvalue.to_i.to_s==value来做到这一点,但我不确定我将如何在我的散列中递归地做到这一点,考虑到一个值可以是一个字符串,或一个数组(哈希或字符串),或另一个哈希。 最佳答案 这是一个非常简单的递归实现(尽管必须同时处理数组和散列会增加一些技巧)。deffixnumifyobjifobj.respond_to?:to_i#IfwecancastittoaFixnum,doit.obj.to_ielsifobj

  2. Ruby:标准递归模式 - 2

    我经常迷上ruby​​的一件事是递归模式。例如,假设我有一个数组,它可能包含无限深度的数组作为元素。所以,例如:my_array=[1,[2,3,[4,5,[6,7]]]]我想创建一个方法,可以将数组展平为[1,2,3,4,5,6,7]。我知道.flatten可以完成这项工作,但这个问题是作为我经常遇到的递归问题的一个例子-因此我试图找到一个更可重用的解决方案。简而言之-我猜这种事情有一个标准模式,但我想不出任何特别优雅的东西。任何想法表示赞赏 最佳答案 递归是一种方法,它不依赖于语言。您在编写算法时要考虑两种情况:再次调用函数的情

  3. ruby - 为什么我用递归得到 "stack level too deep"? - 2

    我有这个ruby代码:defget_sumnreturn0ifn似乎正在为999之前的值工作。当我尝试9999时,它给了我这个:stackleveltoodeep(SystemStackError)所以,我添加了这个:RubyVM::InstructionSequence.compile_option={:tailcall_optimization=>true,:trace_instruction=>false}但什么也没发生。我的ruby版本是:ruby1.9.3p392(2013-02-22revision39386)[x86_64-darwin12.2.1]我还增加了机器的堆栈大

  4. ruby - 构建网络蜘蛛时,应该使用递归吗? - 2

    构建一个深度优先的网络蜘蛛,这意味着它将访问第一页上的所有链接,然后转到每个链接,并访问所有第二页上的链接...你应该使用递归吗?我发现这是CPU密集型的。defrecursion()linkz_on_first_page.eachdo|link|recursion(link)endendrecursion(firstpage) 最佳答案 绝对不是,由于万维网的实际性质,您很快就会遇到问题。当您访问带有主导航部分的网站时,每个页面都链接到其他页面,您就进入了一个无限循环。您可以跟踪您处理了哪些链接,但即便如此,递归循环并不真正适合万

  5. ruby-on-rails - 如何以递归方式将 YAML 文件扁平化为 JSON 对象,其中键是点分隔的字符串? - 2

    例如,如果我有YAML文件en:questions:new:'NewQuestion'other:recent:'Recent'old:'Old'这最终会变成一个json对象,例如{'questions.new':'NewQuestion','questions.other.recent':'Recent','questions.other.old':'Old'} 最佳答案 由于问题是关于在Rails应用程序上使用YAML文件进行i18n,因此值得注意i18ngem提供了一个辅助模块I18n::Backend::Flatten完全像

  6. ruby-on-rails - 这个 C 和 PHP 程序员如何学习 Ruby 和 Rails? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它

  7. ruby - 为什么尾递归 gcd 比 rubinius 的 while 循环更快 - 2

    我有这两个gcd函数的实现:defgcd1(a,b)ifa==baelsifa>bif(a%b)==0belsegcd1(a%b,b)endelseif(b%a)==0aelsegcd1(a,b%a)endendenddefgcd2(a,b)if(a==b)returnaelsifb>amin,max=a,belsemin,max=b,aendwhile(max%min)!=0min,max=max%min,minendminend函数gcd1是尾递归的,而gcd2使用while循环。我已经验证rubinius通过对阶乘函数进行基准测试来执行TCO,只有阶乘函数基准测试显示递归版本和迭

  8. ruby-on-rails - 为什么我的 helper 递归方法不返回每个值? - 2

    我想显示一个由gem祖先管理的类别树。我想使用一个助手,它会递归地遍历树并一个一个地返回类别,暂时没有html标签或内容。moduleCategoriesHelperdefdisplay_tree(category)ifcategory.has_children?category.children.eachdo|sub_category|display_tree(sub_category)puts(sub_category.name)#tocheckifitgoeshereendendcategory.nameendendcategory参数是根类别之一。它应该返回什么?在网页中:它仅

  9. ruby - 如何处理树顶左递归 - 2

    我有一个grammarfile对于我正在尝试构建的一种新的通用编程语言。我正在努力使该语言健壮且易于使用(它深受Ruby等启发),为此我引入了一些左递归规则。我看到一些例子似乎表明了以下左递归规则:rulel_recursel_recurse/'somethingelse'end可以通过将其更改为非左递归:ruler_recurse'somethingelse'/r_recurseend对我来说,这看起来会有不同的问题并且仍然会失败。我是对的,还是这会“奏效”?我试图(查找和)消除的特定左递归可以在这个grammarfile中找到.我不确定哪些规则受到影响,但至少somewerepoi

  10. ruby - 如何递归 rake ? -- 或合适的替代品 - 2

    我希望我的项目的顶级Rakefile使用树中更深的rakefile来构建东西;即顶层rakefile说明如何构建项目(大图),而较低层的rakefile说明如何构建特定模块(本map片)。当然有一组共享的配置,用于在任务之间共享时执行的详细信息:所以它主要是关于保持对需要构建的内容的描述,尽可能接近正在构建的源。例如。/Source/Module/code.foo和cie应该使用/Source/Module/Rakefile中的指令构建;并且/Rakefile了解模块之间的依赖关系。我不关心它是否使用多个rake进程(ala递归make),或者只是创建单独的构建环境。无论哪种方式,它都

随机推荐