本文说明的是如何在thinkphp5.1通过修改pdo mysql连接参数,最终实现参数绑定的时候允许使用同名参数。

pdomysql 默认不支持绑定相同的参数名

如果参数名不一样,默认配置下是没有问题的

// 预处理 SQL 并绑定参数 正确示例
$sql = 'SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour';
$sth->execute(array(':calories' => 150, ':colour' => 'red'));

如果采用同名的参数,默认配置就会报错

// 预处理 SQL 并绑定参数 默认配置下报错,可通过修改连接参数允许该操作
$sql = 'SELECT name, colour, calories
    FROM fruit
    WHERE  colourA = :colour and colourB = :colour';
$sth->execute(array(':colour' => 'red'));

添加连接参数支持绑定相同的参数名

修改连接参数的原生代码

<?php
  $db = new PDO('mysql:host=myhost;dbname=mydb', 'login', 'password', 
  array(PDO::ATTR_EMULATE_PREPARES => true));
?>

在thinkphp5.1修改连接参数

参考官方文档连接参数那一节。
在 /config/database.php 里的params增加一个项目

<?php
return [
    // 数据库类型
    'type'            => 'mysql',
    // 服务器地址
    'hostname'        => '127.0.0.1',
    // 数据库名
    'database'        => 'ihu',
    // 用户名
    'username'        => 'root',
    // 密码
    'password'        => '123456',
    // 端口
    'hostport'        => '3306',
    // 连接dsn
    'dsn'             => '',
    // 数据库连接参数
    'params'          => [
      \PDO::ATTR_EMULATE_PREPARES => true
    ],
]

应用案例

下面代码摘自我的个人项目,里面使用了model做查询,用DB原生查询也是一个道理。
这段代码使用一组geohash跟数据库中的geohash进行对比,每次都是各取前N位,用来确定他们是否属于同个区域。
关于geohash的原理,可以参考我的另一篇文章。

function filterGeohash($geohash, $geohashNeighbors, $topN)
{
  $list = DrugStoreModel::where(
    'LEFT(geohash, :topN) = LEFT(:geohash, :topN) or
      LEFT(geohash, :topN) = LEFT(:North, :topN) or
      LEFT(geohash, :topN) = LEFT(:NE, :topN) or
      LEFT(geohash, :topN) = LEFT(:East, :topN) or
      LEFT(geohash, :topN) = LEFT(:SE, :topN) or
      LEFT(geohash, :topN) = LEFT(:South, :topN) or
      LEFT(geohash, :topN) = LEFT(:SW, :topN) or
      LEFT(geohash, :topN) = LEFT(:West, :topN) or
      LEFT(geohash, :topN) = LEFT(:NW, :topN)',
    [
      'topN'    => $topN,
      'geohash' => $geohash,
      'North'   => $geohashNeighbors['North'],
      'NE'      => $geohashNeighbors['NorthEast'],
      'East'    => $geohashNeighbors['East'],
      'SE'      => $geohashNeighbors['SouthEast'],
      'South'   => $geohashNeighbors['South'],
      'SW'      => $geohashNeighbors['SouthWest'],
      'West'    => $geohashNeighbors['West'],
      'NW'      => $geohashNeighbors['NorthWest']
    ])
    ->hidden(['id', 'search_content'])->select();

  return $list;
}

哦,对了。如果你把上面代码中的:NE换成:NorthEast,或者把:SE换成:SouthEast,保证你Debug到怀疑人生。
这是thinkphp5.1标签转换的一个bug,因为已经有North这个参数,像NorthEast,NorthWest,NorthABC这些前缀一样的参数都会引起混乱。

版权声明:如无特别声明,本文版权归 一年四季 所有,转载请注明本文链接。

(采用 CC BY-NC-SA 4.0 许可协议进行授权)

本文标题:《 thinkphp5.1 pdomysql 允许使用同名的参数 》

本文链接:https://www.yucanlin.cn/develop/thinkphp5.1-pdomysql-%E5%85%81%E8%AE%B8%E4%BD%BF%E7%94%A8%E5%90%8C%E5%90%8D%E7%9A%84%E5%8F%82%E6%95%B0.html