Что происходит со статическими переменными в PHP?

Сегодня я обнаружил неожиданное поведение PHP. Я экспериментировал с классом настроек, который также включает информацию о подключении к базе данных. Класс выглядит примерно так:

class Config
{
    static $dbHost = 'localhost';
    static $dbName = 'name';
    static $dbUser = 'user';
    static $dbPass = 'pass';
}

В «локаторе услуг» я настраиваю функцию для создания соединения PDO, когда это необходимо. Код выглядит так:

$this->configService('db', function (ServiceLocator $context) {
    return new \PDO(
        'mysql:host=' . Config::$dbHost . ';dbname=' . Config::$dbName . ';charset=utf8',
        Config::$dbUser,
        Config::$dbPass
    );
});

Тогда я подумал: в случае ошибки трассировка стека может раскрыть содержимое класса конфигурации. Поэтому я сниму пароль, когда будет установлено соединение с базой данных:

$this->configService('db', function (ServiceLocator $context) {
    $password = Config::$dbPass;
    Config::$dbPass = '';

    return new \PDO(
        'mysql:host=' . Config::$dbHost . ';dbname=' . Config::$dbName . ';charset=utf8',
        Config::$dbUser,
        $password
    );
});

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

Итак, мой вопрос: что здесь происходит? Будет ли PHP устанавливать переменную $ password в тот момент, когда она нужна PDO (и Config :: $ dbPass === '')?

Обновлено: PHP v7.0.23

вроде работает, может дважды звонить configService?

Alexandre Painchaud 26.07.2018 09:46

Я не думал о том, чтобы проверять, вызывается ли код дважды. И да, это так! :( Роутер программы дважды включает файл ... а я этого не заметил.

Thomas Huijzer 26.07.2018 09:53

Поэтому вам следует использовать Шаблон синглтона. это гарантирует, что ваш PDO будет создан только один раз!

Alexandre Painchaud 26.07.2018 09:55

Я не думаю, что шаблон Singleton - это ответ для маршрутизатора, который дважды выполняет один и тот же маршрут.

Thomas Huijzer 26.07.2018 10:01

Итак, вам нужно несколько экземпляров PDO? Синглтон должен быть в управлении PDO. Один экземпляр PDO не означает, что вы не можете вызывать его дважды или больше. если хочешь пример подскажи.

Alexandre Painchaud 26.07.2018 10:04

Да, я понимаю, что шаблон Singleton имеет некоторые преимущества. Но это не решает проблему, когда маршрутизатор выполняет один и тот же маршрут дважды.

Thomas Huijzer 26.07.2018 10:07

Может быть, но это другая проблема. без кода мы не сможем вам помочь

Alexandre Painchaud 26.07.2018 10:13
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать 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
7
44
2

Ответы 2

Александр Пиншо намекнул, что код может запускаться дважды. И да, это так.

Маршрутизатор включает ServiceLocator дважды :(

Это не имеет ничего общего с поздним связыванием.

вместо очистки пароля использовать геттер для получения значения из класса? Базовая трассировка стека не должна отображать частное свойство класса.

<?php
final class Config
{
    private $dbHost = 'localhost';
    private $dbName = 'name';
    private $dbUser = 'user';
    private $dbPass = 'pass';

    public function getPassword(): string
    {
        return $this->dbPass;
    }
}

var_dump((new Config())->getPassword());

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