【问题标题】:How to map GROUP_CONCAT with pdo->fetchAll and mode PDO::FETCH_CLASS from string to an array如何使用 pdo->fetchAll 和模式 PDO::FETCH_CLASS 将 GROUP_CONCAT 从字符串映射到数组
【发布时间】:2021-05-24 14:41:47
【问题描述】:

我想知道 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)"

会返回类似的东西

id (int) referencingNames (srting)
1 Mark, Mona, Sam
2 Jim, Tom, Sara, Mike
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()? 我的意思是,获取所有内容并迭代整个内容仍然是一种选择,但我想知道我是否可以更优雅地做到这一点。

【问题讨论】:

    标签: php pdo magic-function


    【解决方案1】:

    由于您正在加载的列的名称是该类的一部分,因此无论如何它都会设置该值,而无需调用__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;
        }
      }
    }
    

    【讨论】:

    • 那么这里的 php 文档有问题吗?似乎没有为私有财产调用 set?
    • @helle,使用 FETCH_CLASS 似乎绕过了访问修饰符。当大多数类使用私有数据并希望 FETCH_CLASS 仍然能够正确填充它们时,这是有道理的。
    • 感谢您的提示。我稍后会尝试并接受答案。很高兴有一个解决方案
    • 不错!!这真的很好,现在节省了我很多时间!
    猜你喜欢
    • 2011-12-24
    • 2013-08-20
    • 2011-08-28
    • 2018-06-22
    • 2020-04-06
    • 2021-11-15
    • 1970-01-01
    • 1970-01-01
    • 2012-03-15
    相关资源
    最近更新 更多