#php #session
#php #сессия
Вопрос:
Прежде всего, если это уместно, это в обработчике сеанса. Эта функция выполняет запись в базу данных и передается session_set_save_handler
вместе с другими моими функциями, подобными этой
session_set_save_handler('sess_open', 'sess_close', 'sess_read', 'sess_write', 'sess_destroy', 'sess_gc');
У меня есть этот фрагмент кода…
$qid = "select count(*) as total
from zen_sessions
where sesskey = '" . $key . "'";
if(!class_exists('DB'))
require_once dirname(dirname(__FILE__)).'/class/DB.class.php';
var_dump(new DB()); //this is line 109
$total = DB::select_one($qid);
условные и var_dump
предназначены для тестирования. Как ни странно, иногда это работает нормально, в то время как другие выдают мне ошибку:
Fatal error: Class 'DB' not found in /path/to/file/session_functions.php on line 109
Я не могу понять, как это не приведет к сбою при require вместо var_dump
и почему только иногда?
Заранее спасибо за любую информацию.
редактировать — ответ на комментарий / вопрос:
Результат следующего кода
var_dump(class_exists('DB', false));
var_dump(is_file(dirname(__DIR__).'/class/DB.class.php'));
является:
bool(false) bool(true)
перед попыткой потребовать его и тот же результат после require (или true true, когда он не выдает мне ошибку)
Выглядит примерно так:
bool(true) bool(true) object(DB)#3 (0) { }
Предыдущий фрагмент кода является результатом примерно один раз из каждых 5 загрузок страницы, в то время как ошибка является результатом остальных 4.
Edit2 — новые результаты.
Еще более любопытно, что, согласно руководству, я никогда не должен видеть эти отладочные инструкции или ошибки
Примечание:
Обработчик «write» не выполняется до тех пор, пока выходной поток не будет закрыт. Таким образом, вывод из отладочных инструкций в обработчике «write» никогда не будет виден в браузере. Если требуется отладочный вывод, рекомендуется вместо этого записать отладочный вывод в файл.
Редактировать 3 — Примечание для ясности:
DB
Класс должен был быть загружен автоматически (и везде в приложении) class_exists
, и require просто существуют для целей тестирования.
Редактировать 4 — Трассировка стека
Я решил попробовать создать исключение, когда класс не найден, чтобы увидеть трассировку стека, вот что я получаю
Fatal error: Uncaught exception 'Exception' with message 'DB Class Not Found.'
in /path/to/file/session_functions.php:108
Stack trace: #0 [internal function]: sess_write('074dabb967260e9...', 'securityToken|s...')
#1 {main} thrown in /path/to/file/session_functions.php on line 108
Комментарии:
1. Что, если вы сделаете
class_exists('DB', false)
вместо этого?var_dump(is_file(dirname(dirname(__FILE__)).'/class/DB.class.php'));
__DIR__
вместоdirname(__FILE__)
2. @zerkms смотрите мою правку. Практически тот же результат.
3. внимание , ваш код уязвим для атак с использованием sql-инъекций!
4. @DanielA. Белый Это довольно большой скачок, когда вы не знаете, откуда
$key
он исходит. Спасибо за беспокойство.5. Используете ли вы «пространства имен»? Начните с первых принципов с кода, который не работает… Часто выполняйте ‘class_check’ для ‘DB’. Начиная сразу после того момента, когда, по вашему мнению, он должен был быть загружен. Затем переместите эту проверку в сторону кода, вызывающего беспокойство. Выдайте исключение, если класс ‘DB’ не найден. Всегда убедитесь, что классы явно загружены, прежде чем использовать их. Либо используйте «автозагрузчик», либо «include_once». Всегда загружайте класс безоговорочно, если он используется при большинстве запусков программы.
Ответ №1:
Единственное, что я могу придумать, что может быть причиной этого, это из уведомления в PHP docs для session_set_save_handler:
Предупреждение
Текущий рабочий каталог изменяется с помощью некоторых САПИ, если сеанс закрыт при завершении скрипта. Можно закрыть сеанс раньше с помощью session_write_close() .
Из того, что вы испытываете, я предполагаю, что текущий рабочий каталог изменен, поэтому require_once
файл не найден.
Я бы попробовал добавить session_write_close();
где-нибудь в вашу функцию и посмотреть, исправит ли это.
По общему признанию, не уверен, почему is_file
в этом случае будет возвращено true, но, возможно, стоит попробовать.
Комментарии:
1. Это сделало это! Спасибо! Все еще не уверен, почему, но убедившись, что он закрывает его, когда я знаю, что область действия заставляла его работать каждый раз.
2. Все еще не уверен, что именно происходит, стоило бы узнать, что именно вызывает это.
Ответ №2:
Хотя я не могу быть уверен, но я уверен, что ошибка где-то в другом месте, и она просто проецируется, как вы ее описали.
Для тестирования и отладки вашего кода вам необходимо использовать отладчик, подобный PDT. Но тогда проблема в том, что вам нужно отладить часть вашего кода, которая находится вне досягаемости отладчика, средства записи сеанса! Чтобы преодолеть эту проблему, вы можете использовать session_write_close . Вы можете поместить его где-нибудь в конце вашего загрузчика, или, если у вас его нет, вы можете сделать это следующим образом:
<?php
function shutdown_function()
{
session_write_close();
}
register_shutdown_function('shutdown_function');
Затем, установив точку останова, вы можете начать отладку кода сеанса отсюда. Дайте мне знать, если я выиграю пари.
Ответ №3:
попробуй:
$save_handler = new DB();
session_set_save_handler($save_handler, true);
затем сопоставьте функции чтения, записи и т. Д. Внутри вашего класса. я столкнулся с аналогичной проблемой (причудливые случайные ошибки о том, что класс не найден), реализуя обходной путь пользовательского обработчика сохранения другого пользователя для HHVM с redis, и вот как я это исправил. если вы используете HipHopVirtualMachine (или, возможно, какой-либо другой тип JIT-компилятора или кэша приложений), иногда ваш проект может кэшировать некоторые функции без обновления, создавая странные ошибки, подобные этой. обычно перезапуска демона fastcgi и добавления пробелов в один из ваших файлов достаточно, чтобы заставить его повторно интерпретировать ваш проект.
Комментарии:
1. Класс DB не является обработчиком сохранения. Он просто используется в функции для вызова базы данных. Функция, в которой находится этот код, является
sess_write
функцией.2. Спасибо за ваше понимание. Поскольку это отлично работает примерно в 6 других проектах. Это единственный, который дает мне такую подгонку. Я изучу это, а также могу провести рефакторинг, чтобы использовать реализацию класса
SessionHandlerInterface
вместо функций.