Как получить данные с PDO в класс со свойством enum?
Поскольку функция перечисления была выпущена в PHP8.1, мне было интересно, как я могу получить данные из моей базы данных с помощью PDO в объект со свойством ENUM.
У меня есть следующее перечисление:
enum UserType{
case Master: 1;
case Admin: 2;
case Manager: 3;
}
И у меня есть следующий класс:
class User{
private int $id;
private string $name;
private UserType $userType;
}
Каждый раз, когда я пытаюсь выполнить приведенный ниже код, я получаю сообщение об ошибке Невозможно назначить int свойству User :: $ userType типа UserType.
Database::getInstance()->fetchObject(sql: "SELECT id, name, userType FROM user WHERE id = 1", class_name: User::class);
Я хочу знать, есть ли способ заставить приведенный выше код работать или как лучше всего реализовать новую функцию перечисления в моем коде.
Мой код fetchObject:
public function fetchObject($sql, array $args = array(), string $class_name = "stdClass"): mixed
{
$sql = self::$instance->prepare($sql);
if(empty($args)){
$sql->execute();
} else{
$sql->execute($args);
}
$object = $sql->fetchObject($class_name);
$sql->closeCursor();
return $object;
}
1 ответ
Вы не можете сделать это с . Причина в том, что вы не можете назначить
int
к свойству типа
UserType
. Вы можете использовать волшебный метод
__set()
, но вам придется не объявлять свойство (это крайне не рекомендуется).
Вы можете использовать
__set
с ленивой инициализацией свойств и
PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE
. Если это сбивает вас с толку, это потому, что это сбивает с толку.
enum UserType:int {
case Master = 1;
case Admin = 2;
case Manager = 3;
}
class User
{
private int $id;
private string $name;
private UserType $userType;
public function __construct()
{
// unset it for lazy initialization (PDO will call __set method instead)
unset($this->userType);
}
public function __set($key, $value)
{
if ($key === 'userType') {
$this->userType = UserType::from($value);
}
}
}
// Tell PDO to call constructor first,
// then try to assign the property if it exists or call magic method __set()
$stmt->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, User::class);
$user = $stmt->fetch();
Возможно, было бы проще просто придерживаться этого в конструкторе. Затем вы можете получить строку как ассоциативный массив и распаковать ее в конструктор.
class User
{
private UserType $userType;
public function __construct(private int $id, private string $name, int $userType)
{
$this->userType = UserType::from($userType);
}
}
Тогда ваш
fetchObject()
будет выглядеть так:
public function fetchObject($sql, array $args = [], string $class_name = "stdClass"): ?object
{
$stmt = self::$instance->prepare($sql);
$stmt->execute($args ?: null);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row ? new $class_name(...$row) : null;
}
Вам нужно распаковать строку, потому что PDO не имеет возможности передавать значения конструктору.