gpt4 book ai didi

php - 简化的递归 PHP

转载 作者:可可西里 更新时间:2023-11-01 01:01:38 24 4
gpt4 key购买 nike

我一直在研究一种使用 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 .

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

Classes structure

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

现在采用 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com