php pdo mysql多表查询重名字段被覆盖修复方案

作者:zarte    发布时间: 2021-03-15

phpmysqlpdo

问题

pdo fetchAll 关联数组形式返回数据时,同名字段后面的会覆盖前面的数据

SELECT
    test1.id,
    test1.name,
    test2.id
FROM
    test1,
    test2
WHERE
    test1.id = test2.id

Img

解决方案

  1. 最简单的方案就是修改查询语句,使用as alias区分相同名字段。

    SELECT
     test1.id,
     test1.name,
     test2.id as id2
    FROM
     test1,
     test2
    WHERE
     test1.id = test2.id
    

    Img

  2. 但是有的人很懒,所以就有了下面的程序自动处理方案。(存在bug,推荐方式3)

    private function autoalias($osql){
         $sql =  (new SqlFormatter())->format($osql,"",false);
         $mparr =  explode("\n",$sql);
         $searchArr = array();
         $count = 1;
         foreach ($mparr as $k=>$v){
             if(strtolower($v)=="from"){
                 $mparr[$k-1] = trim($mparr[$k-1],",").' ';
                 break;
             }
             if(strtolower($v)=="select")continue;
             if(strpos(strtolower($v)," as ")!==false)continue;
             $tmp = explode('.',$v);
             $tstr = trim((isset($tmp[1])?$tmp[1]:$tmp[0]),',');
             if(in_array($tstr,$searchArr)){
                 //重复
                 $mparr[$k]= trim($v,',').' as '.$tstr.$count.',';
                 $count++;
             }else{
                 $searchArr[]=$tstr;
             }
         }
    
         $sql = implode(' ',$mparr);
         return $sql;
     }
    

    使用doctrine/sql-formatter库对sql语句格式后处理。但是需要修改以下部分

    Doctrine\SqlFormatterSql\Formatter.php
    原:
    public function format(string $string, string $indentString = '  ') : string
    ...
    while ($token = $cursor->next(Token::TOKEN_TYPE_WHITESPACE)) {
             $highlighted = $this->highlighter->highlightToken(
                 $token->type(),
                 $token->value()
             );
    改为:
    public function format(string $string, string $indentString = '  ',$hightlightflag = true) : string
    ...
    while ($token = $cursor->next(Token::TOKEN_TYPE_WHITESPACE)) {
             if($hightlightflag){
                 $highlighted = $this->highlighter->highlightToken(
                     $token->type(),
                     $token->value()
                 );
             }else{
                 $highlighted = $token->value();
             }
    

    原方法默认对sql进行高亮处理增添了不可识别字符。

  3. PDO::FETCH_NAMED
    强烈建议查资料时查看原版文档避免搬运缺失。英文文档
    设置该参数返回结果示例如下:
    Img
    代码示例
    $result = array();
    //循环处理别名
    while($res=$sth->fetch(\PDO::FETCH_NAMED)){
     $row = array();
     foreach ($res as $k=>$v){
         if(is_array($v)){
             foreach ($v as $kk=>$vv){
                 if($kk){
                     $row[$k.$kk]=$vv;
                 }else{
                     $row[$k]=$vv;
                 }
             }
         }else{
             $row[$k]=$v;
         }
     }
     $result[]=$row;
    }
    unset($res);
    

上一篇:  consul使用

下一篇:  form表单无法提交动态新增的元素

加载更多