Включает файлы, которые не найдены через require_once ()

Bane спросил: 13 июня 2018 в 07:42 в: php

Эй, ребята, прежде чем я начну свой вопрос, я собираюсь вставить фотографию моей структуры папок, чтобы было легче визуализировать.

Итак, в 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 расположенный в моем корневом каталоге, он дает эту ошибку:

init.php, который является required_once работает. Однако он не находит файлы (которые находятся в том же каталоге, что и init.php), которые требуются в самом файле init.php. Почему это происходит?

Примечание. Все пути работают, когда я играю на моей странице admin/admin_pages/index.php.

EDIT: это скриншот содержимого в моей включаемой папке.

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

EDIT: Это то, что дает сообщение об ошибке FYI. У меня есть функция автозагрузчика. Однако файл отсутствует и должен быть загружен в любом случае.


4 ответа

Bane ответил: 13 июня 2018 в 08:18
Спасибо за ввод. Да, это странно. Я обновил свой вопрос, потому что забыл включить код функции autloader, который я реализовал. Это то, что дает сообщение об ошибке. Однако он все равно должен найти файл db_object.php, поскольку он отсутствует.
Niellles ответил: 13 июня 2018 в 10:24

EDIT:

Так как вы внесли некоторые изменения, в которых вы нам представили, помимо прочего, с наличием автозагрузчика, я перечитал ваш вопрос. Две важные вещи, которые выпрыгивают:

  1. Эта проблема возникает в вашем index.php, расположенном в корне вашего сайта.
  2. Исправленная ошибка возникает из classAutoloader().
  3. (У вас нет проблем с 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");
?>

Вы можете заметить, t имеют смысл, так как эти пути неверны при вызове из header.php. Вы можете исправить это, используя константу __DIR__:

Каталог файла. Если используется внутри include, возвращается каталог прилагаемого файла. Это эквивалентно todirname (FILE). Это имя каталога не имеет завершающего slashunless, это корневой каталог. ~ Руководство


С вышеупомянутой информацией вы, вероятно, могли бы понять это сами, но чтобы завершить мой ответ, измените код в 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";
?>

Обратите внимание:

  1. require_once - это не функция, а инструкция, поэтому вы называете ее таковой. То же самое относится к require, include и include_once.
  2. По вашему запросу может потребоваться только запрос db_object.php ... Это кажется странным.

Pro-tip (как упоминалось в комментариях AnyhonyB):

Одна из самых больших неприятностей - написать длинный список необходимых включений в начале каждого скрипта (по одному для каждого класса).

В PHP 5 это больше не требуется. Функция spl_autoload_register () регистрирует любое количество автозагрузчиков, позволяя автоматически загружать классы и интерфейсы, если они в настоящее время не определены. Регистрируя автозагрузчики, PHP получает последний шанс загрузить класс или интерфейс до сбоя с ошибкой. ~ Мануа l

AnthonyB ответил: 13 июня 2018 в 08:18
Я исправлен, потому что __DIR__ исправляет проблему, это позволяет избежать проблем с файлами, включенными в включенные файлы и прочее. Но, по моему мнению, использование __DIR__ недостаточно гибкое, решение для автозагрузчика будет хорошим. И немного утомительно использовать __DIR__ во всех include.
Niellles ответил: 13 июня 2018 в 08:21
@AnthonyB I 100% согласны с тем, что в этом случае следует использовать автозагрузчик, но это просто не ответ на вопрос , почему файлы include не найдены через require_once ()?
AnthonyB ответил: 13 июня 2018 в 08:24
@Niellles, ты прав. Ваш ответ действителен. Но обычно приходится отвечать на главный вопрос, а затем предлагать возможное решение.
Niellles ответил: 13 июня 2018 в 08:30
@AnthonyB Я новичок в ответе на вопросы о SO ... или, по крайней мере, только недавно начал делать это на регулярной основе. Я добавил совет к моему ответу в качестве дополнительной информации. Благодаря!
Есть решение
Bane ответил: 14 июня 2018 в 06:27

Привет, ребята, спасибо всем за ваш вклад. Я, наконец, нашел проблему с моим кодом. Это не из-за функции автозагрузчика.

Я не знал, что порядок файлов, вызываемых в 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");
?>
Niellles ответил: 14 июня 2018 в 05:40
Хотя это не позволяет автозагрузчику выбросить ошибку, на самом деле это не должно было вызвать ошибку. Весь смысл автозагрузчика заключается в том, что это последнее средство, если класс не может быть найден, теперь вы просто препятствуете загрузке автозагрузчика, вы не фиксируете тот факт, что он не работает для ~/index.php.
Bane ответил: 14 июня 2018 в 06:30
так вы говорите, что порядок требований require_once не имеет значения вообще? Даже если некоторые файлы, такие как user.php и photo.php, имеют классы, которые наследуются от класса в файле db_object.php? Это было странное решение, я знаю, что все еще пытаюсь понять это.
Niellles ответил: 14 июня 2018 в 07:11
Я не говорю, что это не имеет значения - ваш вопрос ясно показал, что это может иметь значение, я говорю, что это не имеет значения. Поскольку 1), если photo.php и user.php требуется db_object.php, последний должен быть required_once этими файлами. Если ваш index.php также требует этого, вы все равно можете явно вызвать require_once. И 2) вы могли (и должны) избавиться от всех операторов require_once и использовать автозагрузчик. Тем более, что у вас уже есть тот, который просто нуждается в небольшой настройке для работы из всех ваших разных мест.
Progrock ответил: 14 июня 2018 в 04:10

Это не ответ, но может помочь:

Рассмотрим следующее.

Если у нас есть три файла в одном каталоге:

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/stackoverflow/req_test2/b.php on line 3

Это показывает, что порядок имеет значение с требованием вызовов.

Если я поменяю содержимое a.php для следующего и запустить его:

<?php
spl_autoload_register();$b = new B;
var_dump($b);

Я получаю этот вывод:

object(B)#1 (0) {
}

spl_autoload_register () без параметров здесь использует стандартную реализацию spl_autoload (): ссылку на класс с именем Foo, будет выглядеть как файл foo.php из вашего пути include.

Инициализация B здесь ссылается на класс C и автозагрузчик выше, позаботится о необходимости использования соответствующих файлов.

Я бы рекомендовал поместить каждое определение класса в собственный файл. С одним отображением имени файла в класс. Вы также можете быть заинтересованы в стиле PSR-4.

Объявите свой автозагрузчик раньше. Утилиты также могут быть включены заранее.

Исправление для вашего кода будет заключаться в том, чтобы добавить вашу папку include к вашему пути include и изменить вашу строку запроса на $path = "{$class}.php";. Я лично удалил бы линию штампа внутри вашего автозагрузчика, так как вам может потребоваться зарегистрировать более одного автозагрузчика - они стекируются, как и ваши пути включения.

Дополнительное видео по вопросу: Включает файлы, которые не найдены через require_once ()

Уроки PHP 7 | Подключение файлов. Шаблон страницы. Require.Include

PHP для начинающих | #8 Подключение PHP-файлов (require, include)

Learn PHP: Include & Require