PHP PDO: выборка данных как объектов - свойств, назначенных ПЕРЕД вызовом __construct. Это верно?
Полный вопрос должен быть "Правильно это или это ошибка, на которую я не могу рассчитывать?"
ПОЧЕМУ это правильное поведение?
Я больше работал с PDO и, в частности, играл с извлечением данных непосредственно в объекты. При этом я обнаружил это:
Если я получаю данные непосредственно в объект следующим образом:
$STH = $DBH->prepare('SELECT first_name, address from people WHERE 1');
$obj = $STH->fetchAll(PDO::FETCH_CLASS, 'person');
и иметь такой объект:
class person {
public $first_name;
public $address;
function __construct() {
$this->first_name = $this->first_name . " is the name";
}
}
Он показывает мне, что свойства присваиваются перед вызовом __construct - потому что все имена имеют "имя".
Является ли это некоторой ошибкой (в этом случае я не могу/не буду на нее рассчитывать), или это так, как должно быть. Потому что это действительно очень хорошо, как это работает в настоящее время.
Update
По-видимому, по словам одного из сопровождающих, это не ошибка. Кто-то отправил его в качестве ошибки в 2008 году, на который ответ был "не ошибкой, прочитал документы".
Однако мне бы очень хотелось знать, ПОЧЕМУ это правильное поведение.
Ответы
Ответ 1
После долгих чтений я думаю, что, наконец, наткнулся на ответ: он работает таким образом намеренно, и у вас есть возможность заставить его работать иначе.
Здесь в основном недокументированная константа PDO, называемая PDO::FETCH_PROPS_LATE
, которую вы можете использовать, чтобы заставить свойства быть загружены в объект после его создания. Например:
$obj = $STH->fetchAll(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'person');
Будет вызвано присвоение свойств ПОСЛЕ создания объекта, поэтому мой пример выше не изменит свойства вообще. Разумеется, выключение PDO::FETCH_PROPS_LATE
выключает его, как описано в моем примере в исходном вопросе.
Составители, похоже, активно считают, что оба поведения могут быть желательными и дают вам возможность сделать это. Документация даже не объясняет это - я был прочитал список констант PDO и увидел его и дал ему шанс.
Ответ 2
Причина в том, что когда вы сериализуете объект, либо в базу данных, либо в строку, вы не (обычно) хотите повторно инициализировать свойства при ее неэтериализации.
Ответ 3
Попробуйте использовать PDO:: FETCH_INTO вместо PDO:: FETCH_CLASS. Из документов:
PDO:: FETCH_INTO: обновляет существующий экземпляр запрашиваемого класса, сопоставляя столбцы набора результатов с именованными свойствами в классе
Итак, сначала создайте экземпляр, а затем передайте экземпляр в требуемый метод выборки.
Говоря, да, скорее, контр-интуитивно, чтобы FETCH_CLASS заполнялся перед вызовом __construct. Ответ, указанный в списке рассылки, является стандартным ответом "RTM" для копирования и вставки. Если FETCH_INTO работает, вы должны открыть ошибку документации с предлагаемыми улучшениями.