ThinkPHP中文字段问题

博客介绍了在Thinkphp5中使用PDO操作包含中文字段的SQL语句时遇到的问题,以及解决方案。作者发现由于绑定机制导致中文字段在预处理时出错,并分享了修改Thinkphp5源码以支持中文字段的方法,包括修改`thinkdbBuilder.php`文件中的预处理绑定部分。此外,还提到了对于Thinkphp6框架,如何修改`Mysql.php`和`Template.php`以支持中文字段和模板变量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:
https://www.baidu.com/link?url=Ohc9epgQgkNYLwnHqP-jZ9RfIQWW50-iz8-ZMIPLdtCIJHnUpYwQnDLmXzi7Fa110o_fej06HBQC2fJpNwXLP_&wd=&eqid=e71449f60000ca22000000025dfb2fc9

Thinkphp5 PDO操作mysql预处理中文字段出错问题

Thinkphp5手册上建议不用中文表明和中文字段名

今天发现中文字出问题的地方了

$pdo = new PDO('mysql:host=localhost;dbname=xsfm_master', 'root','root' );
$pre = $pdo->prepare('UPDATE `ep购买`  SET `支付宝`=:data__111  WHERE  `id` = :where_id  ');
$arr = [':data__111'=>'852',':where_id'=>'1'];
$pre->execute($arr);

中文字段是完全支持的

官网是这么说的

tp5中使用中文字段后不能插入和保存数据 - ThinkPHP框架

但是 Thinkphp5中绑定是这么干的

"UPDATE `ep购买`  SET `支付宝`=:data__支付宝  WHERE  `id` = :where_id  "
  ["data__支付宝"] => array(2) {
    [0] => string(3) "998"
    [1] => int(2)
  }
  ["where_id"] => array(2) {
    [0] => int(1)
    [1] => int(1)
  }

测试一下果然出错

$pre = $pdo->prepare('UPDATE `ep购买`  SET `支付宝`=:data__支付宝  WHERE  `id` = :where_id  ');
$arr = [':data__支付宝'=>'852',':where_id'=>'1'];
$pre->execute($arr);

知道错误原因就容易解决了

我是这么干的

Thinkphp5.1 \thinkphp\library\think\db\Builder.php

P:103

elseif (is_scalar($val)) {
                // 过滤非标量数据
                if (0 === strpos($val, ':') && $query->isBind(substr($val, 1))) {
                    $result[$item] = $val;
                } else {
                    $key = str_replace('.', '_', $key);
                    if (preg_match("/[\x7f-\xff]/", $key)) {    //add_判断字符串中是否有中文
                        $query->bind('data__' . md5($key), $val, isset($bind[$key]) ? $bind[$key] : PDO::PARAM_STR);//add
                        $result[$item] = ':data__' . md5($key);  //add
                    } else {                      //add
                        $query->bind('data__' . $key, $val, isset($bind[$key]) ? $bind[$key] : PDO::PARAM_STR);
                        $result[$item] = ':data__' . $key;
                    }                           //add
                }
            }

公司有人改这里用的是 base64_encode方法

想到Thinkphp5 Model返回的都是implement ArrayAccess 的对象,虽然可以以数组的方式访问,但是作者建议用$obj->id的方式访问,如果中文字段 $obj->数量,不优雅

20180112

thinkphp5.1.3我是这么干的

http://www.thinkphp.cn/topic/64753.html

让TP6支持数据库中文字段,模板中文变量,不喜勿喷

浏览:586 发布日期:2019/07/16 分类:ThinkPHP6专区

试了Laravel的框架支持各种中文,好生羡慕,尝试修改了下
负面BUG未知,不喜勿喷,有新发现再来更新吧
对正则表达式不是很懂,改的可能不完美,希望能有大神能改改吧

1.让TP6支持MYSQL中文字段,注释下面3行正则判断
tp\vendor\topthink\think-orm\src\db\builder\Mysql.php 336行
//if ($strict && !preg_match('/^[\w\.\*]+$/', $key)) {
// throw new Exception('not support data:' . $key);
//}
--------------------- 例子 ---------------------
$this->setAttr('name','aa');
$this->setAttr('备注','aa');
$this->save();

2.让VIEW模板支持中文变量
tp\vendor\topthink\think-template\src\Template.php 函数:getRegex中的
if (strlen(ltrim($begin, '\\')) == 1 && strlen(ltrim($end, '\\')) == 1) {
$regex = $begin . '((?:[\$]{1,2}[a-wA-w_]|[\:\~][\$a-wA-w_]|[+]{2}[\$][a-wA-w_]|[-]{2}[\$][a-wA-w_]|\/[\*\/])(?>[^' . $end . ']*))' . $end;
} else {
$regex = $begin . '((?:[\$]{1,2}[a-wA-w_]|[\:\~][\$a-wA-w_]|[+]{2}[\$][a-wA-w_]|[-]{2}[\$][a-wA-w_]|\/[\*\/])(?>(?:(?!' . $end . ').)*))' . $end;
}
改成下面的
if (strlen(ltrim($begin, '\\')) == 1 && strlen(ltrim($end, '\\')) == 1) {
$regex = $begin . '((?:[\$]{1,2}[\S]|[\:\~][\$a-wA-w_]|[+]{2}[\$][a-wA-w_]|[-]{2}[\$][a-wA-w_]|\/[\*\/])(?>[^' . $end . ']*))' . $end;
} else {
$regex = $begin . '((?:[\$]{1,2}[\S]|[\:\~][\$a-wA-w_]|[+]{2}[\$][a-wA-w_]|[-]{2}[\$][a-wA-w_]|\/[\*\/])(?>(?:(?!' . $end . ').)*))' . $end;
}
这个正则有点复杂看不很懂只改了{$变量A}这种的
--------------------- 例子 ---------------------
控制器如下:
View::assign('name','我是name');
View::assign('名称','我是名称');
$数组 = ['name'=>'我是中文[name]','名称'=>'我是中文[名称]'];
View::assign('中文',$数组);
return View();

模板HTML如下:
{$name}<br>
{$名称}<br>
{$中文['name']}<br>
{$中文['名称']}<br>

3.让模板继承支持中文
tp\vendor\topthink\think-template\src\Template.php 函数:getRegex中的

    1. if ($single) {
    2.   /*$regex = $begin . '(?:' . $tagName . '\b\s+(?>(?:(?!name=).)*)\bname=([\'\"])(?P<name>[\$\w\-\/\.]+)\\1(?>[^' . $end . ']*)|\/' . $tagName . ')' . $end;*/
    3.   $regex = $begin . '(?:' . $tagName . '\b\s+(?>(?:(?!name=).)*)\bname=([\'\"])(?P<name>[\S]+)\\1(?>[^' . $end . ']*)|\/' . $tagName . ')' . $end;
    4. } else {
    5.   /*$regex = $begin . '(?:' . $tagName . '\b\s+(?>(?:(?!name=).)*)\bname=([\'\"])(?P<name>[\$\w\-\/\.]+)\\1(?>(?:(?!' . $end . ').)*)|\/' . $tagName . ')' . $end;*/
    6.   $regex = $begin . '(?:' . $tagName . '\b\s+(?>(?:(?!name=).)*)\bname=([\'\"])(?P<name>[\S]+)\\1(?>(?:(?!' . $end . ').)*)|\/' . $tagName . ')' . $end;
    7. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值