Is there a way to json parse string before making it a class with PDO? I don’t like using union types.
In the example below contact is of type json in the database.
PDO
$stmt = $DB->prepare("SELECT first_name, last_name, contact FROM users"); $stmt->execute(); $stmt->fetchAll(PDO::FETCH_CLASS, 'User');
User class
<?php class User { public string $first_name; public string $last_name; public string | object $contact; public function __construct() { $this->contact = json_decode($this->contact); } }
Advertisement
Answer
As Movahhedi suggested you could use PDO::FETCH_FUNC
, but the json_decode()
should take place in the passed function, not in the constructor. My suggestion would be to create a UserFactory
class with a method like createFromDbRow()
, although just defining it as a bare function would work just as well too, of course:
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 User
s 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 ) ); } }