PDO fetchObject по какому принципу работает

Была зача осуществить подмену значений при вызове fetchObject, есть таблица (mysql) у которой один столбец с типом json, думал при создании объекта через fetchObject строку json превратить в массив, решения не нашел. Логично вызвать самому объект и заполнить его, конвертируя значения из базы как угодно.

UPD:

Была зача осуществить подмену значений при вызове `fetchObject...

@LaukhinAndrey помог с решением. Однако вопрос ниже актуален


Свойства целевого объекта приватные, и вот тут не понимаю как именно работает fetchObject, тк в объекте есть методы __set, __clone и не один из них не срабатывает, и возник вопрос, как fetchObject возвращает заполненый класс с приватными свойствами в обход магических методов?

UPD:

Вызвал все методы

class User
{

  private ?string $name = null;
  private ?string $surname = null;
  private ?string $lastname = null;
  private ?string $email = null;
  private int     $phone = 0;
  private ?string $address = null;
  private $time_register = 0;
  private ?string $pass = null;
  private $service = '';

  function __construct(...$arg)
  {
    var_dump(__METHOD__);
    var_dump($arg);

    $this->service = json_decode($this->service, true);
  }
  function __destruct()
  {
    var_dump(__METHOD__);
  }
  function __call($arg1, $arg2)
  {
    var_dump(__METHOD__);
    var_dump($arg1);
    var_dump($arg2);
  }
  static function __callStatic($arg1, $arg2)
  {
    var_dump(__METHOD__);
    var_dump($arg1);
    var_dump($arg2);
  }
  function __get($arg)
  {
    var_dump(__METHOD__);
    var_dump($arg);
  }
  function __set($arg1, $arg2)
  {
    var_dump(__METHOD__);
    var_dump($arg1);
    var_dump($arg2);
  }
  function __isset($arg)
  {
    var_dump(__METHOD__);
    var_dump($arg);
  }
  function __unset($arg)
  {
    var_dump(__METHOD__);
    var_dump($arg);
  }
  function __sleep()
  {
    var_dump(__METHOD__);
  }
  function __wakeup()
  {
    var_dump(__METHOD__);
  }
  function __serialize()
  {
    var_dump(__METHOD__);
  }
  function __unserialize()
  {
    var_dump(__METHOD__);
  }
  function __toString()
  {
    var_dump(__METHOD__);
  }
  function __invoke()
  {
    var_dump(__METHOD__);
  }
  function __set_state()
  {
    var_dump(__METHOD__);
  }
  function __clone()
  {
    var_dump(__METHOD__);
  }
}

# ---------------------------------

$PDO = DB::Connect();
$PDOSt = $PDO->query('SELECT * FROM service_users');

var_dump($PDOSt->fetchObject('SCCT\Model\User'));

Результат:

string(28) "SCCT\Model\User::__construct"
array(0) {
}

object(SCCT\Model\User)#51 (9) {
  ["name":"SCCT\Model\User":private]=>
  string(4) "Jonh"
  ["surname":"SCCT\Model\User":private]=>
  string(3) "Doe"
  ["lastname":"SCCT\Model\User":private]=>
  NULL
  ["email":"SCCT\Model\User":private]=>
  string(11) "[email protected]"
  ["phone":"SCCT\Model\User":private]=>
  int(71000010203)
  ["address":"SCCT\Model\User":private]=>
  NULL
  ["time_register":"SCCT\Model\User":private]=>
  string(19) "2022-05-20 13:36:18"
  ["pass":"SCCT\Model\User":private]=>
  NULL
  ["service":"SCCT\Model\User":private]=>
  array(1) {
    ["hello"]=>
    string(5) "world"
  }
}

string(27) "SCCT\Model\User::__destruct"

Ответы (1 шт):

Автор решения: Laukhin Andrey

Независимо от модификатора доступа, если свойство существует, то будет присвоено значение, если не существует, то будет попытка вызвать магический метод __set. Если он не определён, то свойство будет создано.

Таким образом, мы можем определить __set, чтобы предотвратить автоматическое создание свойств, но он никогда не будет вызван для существующих свойств.

С учетом того, что свойства закрытые, один из вариантов решения: сделать необходимые преобразования в конструкторе класса, передаваемого в fetchObject. Конструктор будет вызван после того, как свойства заполнятся значениями соответствующих столбцов. Это порядок по умолчанию, если не установлен PDO::FETCH_PROPS_LATE.

Другой подход – предусмотреть метод prepareProps, который вызывать при получении очередного объекта из базы.

Изменить приватный метод из вне можно при помощи класса ReflectionProperty.

→ Ссылка