首页 > 解决方案 > 如何使用 pdo->fetchAll 和模式 PDO::FETCH_CLASS 将 GROUP_CONCAT 从字符串映射到数组

问题描述

我想知道 PDO 的 fetchAll 是如何实际实现的,以了解如何将数据库中的结果(包括 GROUP_CONCAT() 逗号分隔的列表字符串)映射到数组属性。

有一个类似的 sql

$query = "Select a.id, GROUP_CONCAT(b.name) AS referencingNames FROM a JOIN b on (a.id = b.id_a)"

会返回类似的东西

标识(整数) 引用名称 (srting)
1 马克、莫娜、山姆
2 吉姆、汤姆、萨拉、迈克
3 ...

我要映射到的对象如下所示

class someObject {
  public int $id;
  public array $referencingNames;
}

当我调用我的php代码时:

 $pdo = new PDO(....)
 $statement = $pdo->prepare($query);
 $statement->execute();

 $objects = $statement->fetchAll(PDO::FETCH_CLASS, someObject::class);

我遇到了类型错误,referencingNames显然是string.

然后我尝试的是设置$referencingNames私有并使用__set()下面的php文档中所说的魔术函数

在将数据写入不可访问(受保护或私有)或不存在的属性时运行

class someObject {
  public int $id;
  private string $referencingNames;

  public ?array $refNamesList;

  public function __set($name, $value) 
  {
    if($name == "referencingNames") {
        $this->referencingNames = $value;
        $this->refNamesList = explode(",", $value);
    } else {
        $this->$name = $value;
    }
  } 
}

坏消息:这没有成功。我得到一个 refNamesList 保持为空的对象。记录调用__set()并没有给我任何输出,所以我假设它没有被调用。

有没有人知道如何在不构建自己的解决方案的情况下映射GROUP_CONCAT到带有 PDO 的数组?fetchAll()我的意思是,获取所有内容并迭代整个内容仍然是一种选择,但我想知道我是否可以更优雅地做到这一点。

标签: phppdomagic-function

解决方案


由于您正在加载的列的名称是该类的一部分,因此无论如何它都会设置该值,而无需调用该__set方法。因此,一种方法(似乎可行)是添加一个在类中不存在的列别名 - 在本例中为 nameList ...

$query = "Select a.id, GROUP_CONCAT(b.name) AS nameList 
             FROM a 
             JOIN b on (a.id = b.id_a)"

然后这应该调用该__set方法,并且您可以在获得 nameList 时进行处理...

class someObject {
  public int $id;
  public array $referencingNames;

  public function __set($name, $value)
  {
    if($name == "nameList") {
        $this->referencingNames = explode(",", $value);
    } else {
        $this->$name = $value;
    }
  }
}

推荐阅读