У меня есть страница с переменной и функцией:
test.php
<?php
$myVar = "myVar";
function myFunc() {
echo "myFunc()";
}
?>
Первая страница, которая его включает, может увидеть значение переменной.
<?php
echo "page1";
require_once("include/test.php");
print_r($myVar);
function GoTo2() {
$urlSite = "page2.php";
include($urlSite);
exit();
}
GoTo2();
?>
но вторая страница не видит переменную.
<?php
echo "page2\n";
require_once("include/test.php");
print_r($myVar);
?>
он генерирует PHP. Предупреждение: Undefined variable $myVar in .../page2.php on line 4
Я не могу использовать require()
на второй странице, потому что выдает ошибку - PHP Fatal error: Cannot redeclare myFunc() (previously declared in .../include/test.php) in .../include/test.php ...
Как правильно использовать PHP, чтобы обе страницы могли видеть переменную, а также использовать функцию?
Обновлено:
Именно поэтому в файле следует объявлять только глобальные имена, такие как функции и классы, а не переменные, и уж точно не оба вместе.
Это проблема масштаба. Поскольку вы включили это в функцию GoTo2
, у вас есть доступ только к переменным в области действия этой функции. $myVar
не входит в область действия этой функции, поскольку test.php
требовалось вне этой функции.
Да, речь идет об области действия и не имеет ничего общего с использованием require_once
или include
. Та же проблема возникла бы, если бы весь код внутри «page2.php» был написан непосредственно внутри function GoTo2()
. Прочтите документацию
@ADyson Да, и нет. Область действия предотвращает наследование переменной, сочетание объявления переменной и функции предотвращает повторное включение объявляющего файла.
@deceze правда. Смешение объявлений переменных и объявлений функций в «test.php» не помогает. Но в любом случае все это кажется излишне сложным и запутанным и требует переосмысления.
Какое «лучшее решение» является, зависит от того, что здесь разрешено давать. Рефакторинг того, где и как эта переменная объявляется и передается, был бы идеальным. Но может быть и много работы. Использование ключевого слова global
здесь может быть простым решением, но только удлинит спагетти.
I just discovered that page2 cannot see the variable when the site was upgraded to php8
... в более ранних версиях его тоже не было видно, но раньше предупреждение было Уведомлением, и люди иногда его отключали. Так что это не новая проблема, просто PHP8 сделал ужасный код более очевидным.
Не лучше ли было бы перенаправить на другую страницу, а не включать ее?
Первая проблема заключается в том, что второго включения не произойдет, поскольку оно уже включено.
Вторая проблема заключается в том, что вы не можете использовать переменные вне функции. Вам нужно либо отправить переменную в качестве параметра функции, либо сделать переменную глобальной.
Первое решение:
function GoTo2($myVar) {...
Второе решение:
funtion GoTo2() { global $myVar; ...
Поскольку ваш настоящий вопрос заключается не в том, «почему это происходит», а в том, «как правильно это сделать», то теоретически вся схема потребует переосмысления, как отметил @ADyson.
По сути, у вас есть page1.php
, включающий test.php
и page2.php
, который затем снова включает test.php
. Но логика includes
в том, что файлы следует включать только один раз.
Нет ничего плохого в том, чтобы include
определять переменные, как вы это делаете, например, в случае с файлом конфигурации. Но опять же: вы include
конфигурируете только один раз; если это происходит дважды, скорее всего, это ошибка или заблуждение. То же самое относится и к библиотекам функций.
На самом деле не существует «единственно правильного способа сделать это». Это будет зависеть от того, что вам доступно и что вы намереваетесь. При этом идеальным вариантом было бы собрать все конфигурации в одном файле; функции, собранные в одном или нескольких файлах, в зависимости от их специфики; и у вас есть основной файл, содержащий include
файлы, необходимые для конкретной операции. Например, такая структура:
Если вам нужно включить много файлов, вы можете создать файл конфигурации прокси:
конфигурация.php
<?php
require_once('/confs/display_config.php');
require_once('/confs/parameters_config.php');
require_once('/functions/encryption_routines.php');
require_once('/functions/processing_routines.php');
require_once('/functions/math_routines.php');
?>
Тогда ваш page1.php
будет:
<?php
require_once('configuration.php');
// ... and other stuff
?>
Концепция «подстраниц» (например, page2.php
, вызываемая внутри page1.php
) также не обязательно неверна, хотя она может оказаться сложной: вам придется иметь в виду, что этот фрагмент кода предназначен для того, чтобы всегда вызываться другим странице и предполагают все настройки, которые были выполнены до вызова.
Итак, дело в том, что данная страница (в вашем случае page2.php
) в идеале не должна вызываться как напрямую, так и с другой страницы (в вашем случае page1.php
).
Либо page1.php
и page2.php
всегда вызываются напрямую и, таким образом, загружаются отдельно свои собственные конфигурации (page1.php
включает test.php
и page2.php
включает test.php
), либо page2.php
всегда загружается page1.php
, а затем использует его для своих собственных конфигураций (page1.php
включает test.php
, тогда page2.php
: здесь page2.php
будет иметь доступ к конфигурациям test.php
, уже загруженным page1.php
).
Вы включаете одно в другое, так почему же вы с самого начала называете их обе «страницами»?