Ошибка PHP: невозможно получить доступ к частной собственности

У меня есть такой класс:

class Session {
    private Session_Database $db;

    public function __construct(){
        // Instantiate new Database object
        $this->db = new Session_Database();

        // Set handler to overide SESSION
        session_set_save_handler(
            [$this, '_open'],
            [$this, '_close'],
            [$this, '_read'],
            [$this, '_write'],
            [$this, '_destroy'],
            [$this, '_gc']
        );

        // Start the session
        session_start();
    }

    /* ... */

    public function _close(): bool {
        // Close the database connection
        $this->db->close();
        return true;
    }

    /* ... */
}

Я вижу эту ошибку в журналах:

Неустранимая ошибка PHP: необнаруженная ошибка: невозможно получить доступ к частной собственности Session::$db в [номер строки $this->db->close()]

Трассировка стека:
#0 [внутренняя функция]: Session->_close()
#1 {main}\n добавлено...

Однако когда я тестирую код, проходя через xdebug, он работает так, как ожидалось.

Что происходит?

С помощью session_set_save_handler() вы делаете определенные методы из вашего класса сеанса вызываемыми, но когда они вызываются, они не вызываются из объекта сеанса. Взгляните на Заметки, предоставленные пользователями.

KIKO Software 27.02.2024 20:33

С помощью быстрого теста я не могу получить никаких ошибок: 3v4l.org/WfN3S

Chris Haas 27.02.2024 20:41

@KIKOSoftware, можете ли вы уточнить, какие комментарии в примечаниях пользователей вы имеете в виду? Я предполагаю, что класс уничтожается еще до того, как _close() вызывается, но когда я тестирую, на самом деле этого не происходит.

tvanc 27.02.2024 20:45

@ChrisHaas Я тоже не могу, но в журнале ошибок появляются эти ошибки.

tvanc 27.02.2024 20:46

Хотя это и не очень полезно, глядя на код Symfony, они получают доступ к частным переменным в методе close своего обработчика PDO. Мне ваш код кажется правильным.

Chris Haas 27.02.2024 20:51

Просто хочу спросить (извините), возможно ли, что вместо этого он жалуется на что-то внутри Session_Database?

Chris Haas 27.02.2024 20:52

@ChrisHaas разумная мысль, и спасибо, что посмотрели на другую кодовую базу для справки, но нет. В сообщении об ошибке конкретно говорится Session::$db. Метод Session_Database::close() является общедоступным, нестатическим и имеет только одну строку: $this->dbh = null;. Это поле является частным, но оно также должно быть доступно в контексте этого метода.

tvanc 27.02.2024 21:12

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

miken32 28.02.2024 00:53

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

tvanc 28.02.2024 19:10
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
9
221
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Что касается вашего вопроса: «Что происходит?»

Похоже, это происходит, если память исчерпана во время запроса PDO. Я считаю, что это как-то связано с памятью, используемой буферизованными запросами PDO, и тем, как внутренний код PHP освобождает память после ее исчерпания.

Я могу воспроизвести состояние, с которым вы столкнулись, с помощью следующего кода (примечание: здесь используется register_shutdown_function. И код session_close, и register_shutdown_function запускаются после ошибки исчерпания памяти):

<?php

class TestingClass
{
    private int $something_private;

    public function getThisDone(): void
    {
        $this->something_private = 0;
    }
}

// get a reference to the testing class
$obj = new TestingClass();

register_shutdown_function(fn() => $obj->getThisDone());

// get a pdo connection and run a query that returns a lot of data
$pdoConnection = get_db_read_connection();
$pdoStatement = $pdoConnection->prepare('SELECT * FROM your_table_with_a_lot_of_records LIMIT 100000');
$results = $pdoStatement->fetchAll(PDO::FETCH_CLASS, '\stdClass');

И в результате фатальная ошибка:

Примечание:

Я не могу воспроизвести ошибку, если просто вызываю ошибку нехватки памяти при конкатенации строк, как показано ниже.

// use code above but replace pdo connection and query with this
while(true)
{
    $data .= str_repeat('#', PHP_INT_MAX);
}

Что касается «почему это происходит?»

Я не думаю, что так должно быть. Похоже, это хороший кандидат для отчета об ошибках PHP.

Другие вопросы по теме

Как отправить 2 массива в $_SESSION?
Ошибка пакета сеанса Gorilla: «securecookie: хэш-ключ не установлен»
Как очистить все сеансы с помощью ProtectedSessionStorage в серверном приложении blazor?
Сеанс аутентификации ведет себя не так, как предполагалось, когда он завернут в «authenticate(»auth-session») в моем приложении
Предотвращение использования токена обновления для обновления токена доступа после завершения сеанса
Пользовательский обработчик сеансов с JSON в PHP уничтожает сеанс по ошибке
Поведение сеанса Firefox 115: почему страницы не могут найти существующие идентификаторы сеанса для загрузки?
Как я могу перезагрузить все открытые страницы моего сайта, когда я нажимаю кнопку
Хранение пользовательских данных в сеансе пользователя и сохранение данных после успешного выхода из системы
Может ли моя диаграмма классов обрабатывать переключение между ролями покупателя и продавца для вошедших в систему клиентов?