包括通过 require_once() 找不到的文件
Posted
技术标签:
【中文标题】包括通过 require_once() 找不到的文件【英文标题】:includes files not being found through require_once() 【发布时间】:2018-12-16 01:04:57 【问题描述】:大家好,在我开始提问之前,我将粘贴一张我的文件夹结构的照片,以便更容易可视化。
好的,在上面突出显示的header.php
中,我有这行代码:
<?php require_once("admin/admin_pages/includes/init.php"); ?>
在那个 init.php 文件中:
<?php
require_once("functions.php");
require_once("db_config.php");
require_once("database.php");
require_once("user.php");
require_once("session.php");
require_once("photo.php");
require_once("db_object.php");
?>
但是,当我尝试打开位于我的根目录中的 index.php
文件时,会出现以下错误:
required_once
的 init.php 正在工作。但是,它似乎没有找到 init.php
文件本身所需的文件(与 init.php 位于同一目录中)。为什么会这样?
注意:当我在admin/admin_pages/index.php
页面中玩耍时,所有路径都有效。
编辑:这是我包含文件夹中内容的屏幕截图。
<?php
//Just in case an includes file is not called in the init.php file.
function classAutoloader($class)
$class = strtolower($class);
$path = "includes/$class.php";
if (file_exists($path))
require_once($path);
else
die("The file named $class.php was not found.");
spl_autoload_register('classAutoloader');
function redirect($location)
header("Location: $location");
?>
编辑:这就是给出 错误消息仅供参考。我已经设置了自动加载器功能。但是,该文件并没有丢失,应该以任一方式加载。
【问题讨论】:
如果错误仅针对db_object.php
显示,则意味着您之前需要的其他文件存在。可以显示文件夹dmin/admin_pages/includes/
的内容吗?
很难使用已包含文件的路径。使用__DIR__
或基本目录更容易。 db_object
在 admin/admin_pages/includes/
中吗?
如果您的所有文件都包含类,我建议您使用自动加载器而不是自己要求它们。
@Bane,使用自动加载器很棒!但我建议将你的自动加载器包含在你的主 index.php 中,然后只使用自动加载器,不需要手动。如果需要,请仅在自动加载器中使用__DIR__
。
只是关于How to ask a good question的注释,因为一开始的结构有点难以理解。
【参考方案1】:
编辑:
由于您进行了一些编辑,其中您向我们展示了 - 除其他外 - 存在自动加载器,因此我重新阅读了您的问题。两件重要的事情跳出来:
-
此问题出现在您网站根目录下的
index.php
中。
打印的错误来自classAutoloader()
。
(admin/admin_pages/index.php
没有任何问题。)
看起来这仍然是一个类似于下面提到的路径问题。当从~/index.php
调用自动加载器时,它会检查您的根目录是否包含includes/db_object.php
,但事实并非如此。
您可以通过指定相对于自动加载器文件的包含文件夹的路径来解决此问题,如下所示:
$path = __DIR__ ."/path/to/includes/$class.php";
虽然我没有看到这个解决方案有任何问题,但对我来说它看起来不是很优雅。或者,您可以从根目录指定路径。
您的 init.php 文件存在问题。
通过要求admin/admin_pages/includes/init.php
,您正在从需要它的文件中运行init.php
中的代码。如果这是有道理的。您可以在header.php
中编写以下内容,其行为与要求init.php
相同:
<?php
require_once("functions.php");
require_once("db_config.php");
require_once("database.php");
require_once("user.php");
require_once("session.php");
require_once("photo.php");
require_once("db_object.php");
?>
您可能会注意到这没有意义,因为从 header.php
调用时这些路径不正确。您可以使用__DIR__
常量来解决此问题:
文件的目录。如果在包含内使用,则目录 返回包含的文件。这相当于 目录名(文件)。此目录名称没有尾部斜杠 除非它是根目录。 ~The Manual
有了前面提到的信息,你自己大概就能猜出来了,但是为了让我的回答更完整,请将init.php
中的代码更改为:
<?php
require_once __DIR__ . "/functions.php";
require_once __DIR__ . "/db_config.php";
require_once __DIR__ . "/database.php";
require_once __DIR__ . "/user.php";
require_once __DIR__ . "/session.php";
require_once __DIR__ . "/photo.php";
require_once __DIR__ . "/db_object.php";
?>
请注意:
require_once
不是函数而是语句,因此您可以这样称呼它。 require
、include
和 include_once
也是如此。
根据您的问题,只有 db_object.php
的要求失败...这似乎有点奇怪。
专业提示(如 AnyhonyB 在 cmets 中所述):
最大的烦恼之一是不得不写一长串需要的东西 包括在每个脚本的开头(每个类一个)。
在 PHP 5 中,这不再是必需的。 spl_autoload_register() 函数注册任意数量的自动加载器,启用类和 如果当前未加载接口,则自动加载 定义。通过注册自动加载器,PHP 获得了最后的机会 在类或接口因错误而失败之前加载它。 ~The Manual
【讨论】:
感谢您的意见。是的,这很奇怪。我已经更新了我的问题,因为我忘记包含我已经实现的 autloader 功能代码。这就是给出错误消息的原因。但是它仍然应该找到 db_object.php 文件,因为它没有丢失。 我投了赞成票,因为__DIR__
解决了这个问题,它避免了包含在包含文件中的文件和类似的东西的问题。但据我说,使用__DIR__
不够灵活,自动加载器解决方案会很好。而且在所有包含中使用__DIR__
有点乏味。
@AnthonyB 我 100% 同意在这种情况下应该使用自动加载器,但这根本不是问题的答案为什么无法通过 require_once() 找到包含文件?我>
@Niellles 你确实是对的。你的回答是有效的。但通常先回答主要问题,然后提出可能更好的解决方案。
@AnthonyB 我对回答关于 SO 的问题有点陌生……或者至少最近才开始定期这样做。我已将提示添加到我的答案中作为附加信息。谢谢!【参考方案2】:
把db_object.php文件放在init.php文件中users.php文件上面就可以找到了。我正在学习同一门课程,这就是解决方案
【讨论】:
【参考方案3】:大家好,谢谢大家的意见。我终于找到了我的代码的问题。不是因为自动加载功能。
我不知道init.php
中调用文件的顺序很重要。我只是重新订购了require_once()
语句。
db_object.php
文件实际上是包含我的对象(照片和用户)的父类的文件。 photo.php
和 users.php
包含从 db_object.php
继承的类。这对于为什么我们需要首先找到db_object.php
是有道理的。
之前:
<?php
require_once("functions.php");
require_once("db_config.php");
require_once("database.php");
require_once("user.php");
require_once("session.php");
require_once("photo.php");
require_once("db_object.php");
?>
之后:
<?php
require_once("functions.php");
require_once("db_config.php");
require_once("database.php");
require_once("db_object.php");
require_once("user.php");
require_once("session.php");
require_once("photo.php");
?>
【讨论】:
虽然这可以防止您的自动加载器抛出错误,但它一开始就不应该抛出错误。自动加载器的全部意义在于它是万一找不到类的最后手段,您现在只是阻止自动加载器是必要的,您没有解决它不适用于~/index.php
的事实。
所以你是说 require_once 语句的顺序根本不重要?即使某些文件(例如 user.php 和 photo.php)具有继承自 db_object.php 文件中的类的类?这是一个奇怪的修复,我知道我仍在努力理解它。
我并不是说这无关紧要——您的问题已经清楚地表明它可能很重要,我是说它不应该重要。因为 1) 如果 photo.php
和 user.php
require db_object.php
,后者实际上应该是 required_once
这些文件。如果您的index.php
也需要它,您仍然可以从那里显式调用require_once
。 2) 您可以(并且应该)摆脱所有require_once
语句并使用自动加载器。更是如此,因为您已经有了一个只需稍加调整即可在所有不同位置工作的设备。【参考方案4】:
这不是答案,但可能会有所帮助:
考虑以下内容。
如果我们在同一个目录下有三个文件:
a.php:
<?php
require_once 'b.php';
require_once 'c.php';
b.php:
<?php
class B extends C
c.php:
<?php
class C
如果我运行 a.php,我会得到以下输出:
Fatal error: Class 'C' not found in /var/www/***/req_test2/b.php on line 3
这表明订单对 require 调用很重要。
如果我将 a.php 的内容换成以下内容并运行它:
<?php
spl_autoload_register();
$b = new B;
var_dump($b);
我得到这个输出:
object(B)#1 (0)
此处不带参数的spl_autoload_register() 使用spl_autoload() 的默认实现:对名为Foo 的类的引用,将查找包含路径中的文件foo.php。
这里 B 的初始化引用了 C 类,上面的自动加载器会根据需要处理需要适当的文件。
我建议将每个类定义放在自己的文件中。文件名到类的一对一映射。您可能还对PSR-4 样式感兴趣。
尽早声明您的自动加载器。也可以预先包含实用功能。
您的代码的修复方法是将您的包含文件夹添加到您的包含路径,并将您的需求行更改为$path = "$class.php";
。我会亲自移除自动加载器中的模具线,因为您可能需要注册多个自动加载器 - 这些是可堆叠的,您的包含路径也是如此。
【讨论】:
以上是关于包括通过 require_once() 找不到的文件的主要内容,如果未能解决你的问题,请参考以下文章
有人可以指出为啥我的 require_once() 函数找不到路径吗? php