Сегодня я обнаружил неожиданное поведение 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
Я не думал о том, чтобы проверять, вызывается ли код дважды. И да, это так! :( Роутер программы дважды включает файл ... а я этого не заметил.
Поэтому вам следует использовать Шаблон синглтона. это гарантирует, что ваш PDO будет создан только один раз!
Я не думаю, что шаблон Singleton - это ответ для маршрутизатора, который дважды выполняет один и тот же маршрут.
Итак, вам нужно несколько экземпляров PDO? Синглтон должен быть в управлении PDO. Один экземпляр PDO не означает, что вы не можете вызывать его дважды или больше. если хочешь пример подскажи.
Да, я понимаю, что шаблон Singleton имеет некоторые преимущества. Но это не решает проблему, когда маршрутизатор выполняет один и тот же маршрут дважды.
Может быть, но это другая проблема. без кода мы не сможем вам помочь






Александр Пиншо намекнул, что код может запускаться дважды. И да, это так.
Маршрутизатор включает 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());
вроде работает, может дважды звонить
configService?