Laravel Eloquent无法向SQL Server的NVARCHAR列插入Unicode(表情符号),仅查询构建器可正常工作
我之前也碰到过一模一样的问题,在SQL Server和Laravel Eloquent搭配处理Unicode字符时,这种"Query Builder正常、Eloquent乱码"的情况真的挺让人头疼的。咱们一步步拆解问题,给你几个可行的解决方案:
先回答你的几个核心问题
Laravel Eloquent或PDO SQLSRV驱动是否支持NVARCHAR的Unicode绑定?
理论上是完全支持的,但实际环境中经常因为驱动版本、连接参数配置的问题掉链子。关键在于PDO连接是否强制启用了UTF-8编码传输,以及驱动是否为微软官方版本。能不能让Eloquent自动给NVARCHAR字段加
N'...'前缀?
当然可以!通过自定义模型Trait、重写Eloquent的属性赋值逻辑,或者自定义查询构建器,都能实现自动给指定字段的字符串加上N前缀,模拟SSMS里的写法。根源是不是驱动过时或非官方?
大概率是!非第三方编译的驱动或者旧版本的sqlsrv/pdo_sqlsrv,对SQL Server的Unicode字段兼容有明显bug,尤其是Windows Server环境下,微软官方驱动的兼容性要好得多。切换官方驱动是不是唯一可靠方案?
是最推荐的方案,但如果暂时没法切换,也有临时workaround可以用。
优先推荐的解决方案:升级/更换为微软官方驱动
这是从根源解决问题的办法:
- 卸载现有非官方驱动:先移除服务器上当前的sqlsrv/pdo_sqlsrv扩展,确保清理干净php.ini里的加载配置。
- 下载匹配版本的官方驱动:去微软官网下载对应PHP 7.4.9的驱动包(注意区分线程安全/非线程安全,要和你的PHP环境完全匹配)。
- 配置Laravel连接参数:在
config/database.php的sqlsrv连接数组里,添加强制UTF-8编码的选项:
这个选项会强制驱动用UTF-8编码和SQL Server通信,是解决Unicode乱码的核心配置。'sqlsrv' => [ 'driver' => 'sqlsrv', // ... 其他配置(host、database等) 'charset' => 'utf8', 'options' => [ PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8, ], ],
临时Workaround:让Eloquent自动给NVARCHAR字段加N前缀
如果暂时没法更换驱动,可以用自定义Trait的方式,在模型保存前自动处理指定字段:
创建一个Trait文件
app/Traits/NvarcharUnicodeTrait.php:<?php namespace App\Traits; use Illuminate\Support\Facades\DB; trait NvarcharUnicodeTrait { protected static function bootNvarcharUnicodeTrait() { static::saving(function ($model) { // 这里列出你的所有NVARCHAR字段,比如['kodecabang', 'nama_cabang'] $nvarcharColumns = ['kodecabang']; foreach ($nvarcharColumns as $column) { if (isset($model->$column) && is_string($model->$column)) { // 转义单引号避免SQL注入,然后用DB::raw包装成N前缀形式 $escapedValue = str_replace("'", "''", $model->$column); $model->attributes[$column] = DB::raw("N'{$escapedValue}'"); } } }); } }在你的
Cabang模型里引入这个Trait:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use App\Traits\NvarcharUnicodeTrait; class Cabang extends Model { use NvarcharUnicodeTrait; // ... 其他模型代码($fillable、关联等) }这样每次调用
$cabang->save()时,指定的NVARCHAR字段就会自动带上N前缀,和你用Query Builder写N'✅'的效果一致。
补充排查点
你提到本地正常、服务器异常,除了驱动问题,还可以检查:
- 服务器的PHP环境是否开启了
mbstring扩展,且mbstring.internal_encoding设置为UTF-8; - Windows Server 2012 R2的系统区域设置是否为UTF-8(虽然SQL Server的NVARCHAR本身是Unicode存储,但系统编码可能影响驱动的传输)。
内容来源于stack exchange

