首页 > 解决方案 > PDO json_decode 在进入类之前

问题描述

有没有办法在使用 PDO 将其作为类之前解析字符串?我不喜欢使用联合类型。

在下面的示例中,联系人是数据库中的 json 类型。

PDO

$stmt = $DB->prepare("SELECT first_name, last_name, contact FROM users");
$stmt->execute();
$stmt->fetchAll(PDO::FETCH_CLASS, 'User');

用户类

<?php
class User {
   public string $first_name;
   public string $last_name;
   public string | object $contact;

   public function __construct() {
     $this->contact = json_decode($this->contact);
   }
}

标签: php

解决方案


正如 Movahhedi 建议的那样,您可以使用PDO::FETCH_FUNC,但json_decode()应该在传递的函数中进行,而不是在构造函数中。我的建议是UserFactory使用类似的方法创建一个类createFromDbRow(),尽管将其定义为一个裸函数也可以,当然:

class User {
  public string $first_name;
  public string $last_name;
  public object $contact;
}

class UserFactory {
  public function createFromDbRow(string $first_name, string $last_name, string $contact) : User {
    $user = new User();
    $user->first_name = $first_name;
    $user->last_name = $last_name;
    $user->contact = json_decode( $contact );
    
    return $user;
  }
}

$db = new PDO('sqlite::memory:');
$db->exec('CREATE TABLE "users" ( "id" INTEGER, "first_name" TEXT, "last_name" TExT, "contact" TEXT )');
$db->exec('INSERT INTO "users" VALUES( 1, \'John\', \'Doe\', \'{"email":"johndoe@example.com"}\')');
$db->exec('INSERT INTO "users" VALUES( 2, \'Jane\', \'Doe\', \'{"email":"janedoe@example.com"}\')');

$userFactory = new UserFactory();

$stmt = $db->prepare("SELECT first_name, last_name, contact FROM users");
$stmt->execute();
$users = $stmt->fetchAll(PDO::FETCH_FUNC, [$userFactory, 'createFromDbRow' ]);

var_dump( $users );

Since the User properties are all public I left out a constructor, but you could of course define a constructor as well:

class User {
  public string $first_name;
  public string $last_name;
  public object $contact;

  public function __construct(string $first_name, string $last_name, object $contact) {
    $this->first_name = $first_name;
    $this->last_name = $last_name;
    $this->contact = $contact;
  }
}

...and then create the Users in UserFactory::createFromDbRow() by utilizing the constructor:

class UserFactory {
  public function createFromDbRow(string $first_name, string $last_name, string $contact) : User {
    return new User(
      $first_name,
      $last_name,
      json_decode( $contact )
    );
  }
}

推荐阅读