对 PDO FETCH 指令使用闭包

Use a closure for the PDO FETCH instructions

我想给我的 PDO 结果提供有关如何在稍后迭代时将其自身实例化为对象的说明,但我不想在那之前执行逻辑。

我一直在寻找是否存在此 PDO 功能,但找不到。我想做的基本上是这样的:

public function getUsers()
{
    $sql = 'select first_name, last_name, phone, address from users';

    return $this->pdo->query($sql, PDO::FETCH_ASSOC, function($row) {
        $user = new User();
        $user->setName($row['first_name'] . ' ' .$row['last_name'])
             ->setPhoneNumber($row['phone'])
             ->setMailingAddress($row['address']);
        return $user;
    });
}

是否有使用 PHP 尤其是 PDO 实现此目的的好方法?遍历迭代器不是一个可接受的答案。我只想在执行期间迭代此记录集一次。

大概是这样的:

$result = $this->pdo->query($sql, PDO::FETCH_CLASS, 'User');
return $result->fetch();

您可以通过 yield 为此使用生成器。只有当内部指针在某个迭代时,才会产生具体对象。

class User {
    public $picture;

    public function __construct($pic) {
        $this->picture = $pic;
    }
}

function getUsers() {
    $pdo = new PDO('mysql:host=localhost;dbname=users', 'root', '');
    $query = "SELECT * FROM votesusers";
    $res = $pdo->query($query);
    while ($row = $res->fetch()) {
        yield new User($row['picture_id']);
    }
}

foreach (getUsers() as $user) {
    var_Dump($user);
}

输出:

object(User)[5]
  public 'picture' => string '2' (length=1)

object(User)[6]
  public 'picture' => string '9' (length=1)

object(User)[5]
  public 'picture' => string '6' (length=1)

object(User)[6]
  public 'picture' => string '1' (length=1)

您可以创建实现 Iterator 接口的自定义延迟加载集合。这是一个例子:

class LazyCollection implements Iterator
{
    private $stmt;
    private $callback;

    public function __construct(PDOStatement $stmt, Closure $callback)
    {
        $this->stmt = $stmt;
        $this->callback = $callback;
    }

    public function current()
    {
        $callback = $this->callback; // required because PHP is silly
        return $callback($this->stmt->fetch());
    }

    /* rest of interface implementation */
}

你会像这样使用它:

$stmt = $this->pdo->query($sql, PDO::FETCH_ASSOC)
$result = new LazyCollection($stmt, function($row) {
    return new User($row['name'], $row['phone'], $row['address']);
});

foreach($result as $user)
{
    // $user is an instance of User
}