PAYATHON 2026

Laravel 与 Angular 提交数据时 preg_replace() 参数不匹配

支付小周

结论

问题不在 $fillable,而是 dropdown 绑定了错误的值。

当前的 ng-options 是:

ng-options="payment.name for payment in payment"

页面显示的是 payment.name,但 ng-model="payment_post.name" 绑定的其实是整个 payment 对象。因此提交后,Laravel 收到的 name 是数组,而数据库的 name 字段需要字符串。

Eloquent 在构造 SQL、处理这个数组时,旧版 Laravel 可能会将数组传给 preg_replace() 的 replacement 参数,从而报错:

preg_replace(): Parameter mismatch, pattern is a string while replacement is an array

修正 Angular 绑定

如果数据库要保存支付方式名称,需要明确指定 option 的值为 payment.name:

<select
    class="form-control input-lg"
    ng-model="payment_post.name"
    ng-options="item.name as item.name for item in payments">
    <option value="">请选择支付方式</option>
</select>

建议把列表变量改成复数,避免集合和循环变量都使用 payment:

$http.get('/api/payment').then(function (res) {
    $scope.payments = res.data;
});

修改后提交的数据类似:

name=Cash

而不是:

name[id]=1&name[name]=Cash

如果 agent 表保存的是支付方式 ID,则应绑定 ID,并改用对应的外键字段:

<select
    class="form-control input-lg"
    ng-model="payment_post.payment_id"
    ng-options="item.id as item.name for item in payments">
    <option value="">请选择支付方式</option>
</select>

Controller 也要相应修改:

$agent->payment_id = Input::get('payment_id');

关联记录通常更适合保存 ID,而不是显示名称,具体仍要以实际数据库结构为准。

Laravel 端增加验证

不要把未经验证的输入直接赋给模型。至少要先确认 name 是字符串:

public function store()
{
    $validator = Validator::make(Input::all(), [
        'fname'     => 'required|string',
        'lname'     => 'required|string',
        'mname'     => 'nullable|string',
        'id_number' => 'required|string',
        'name'      => 'required|string',
        'gender'    => 'required|string',
        'username'  => 'required|string',
    ]);

    if ($validator->fails()) {
        return Response::json([
            'errors' => $validator->errors(),
        ], 422);
    }

    $agent = new Agent();
    $agent->fname = Input::get('fname');
    $agent->lname = Input::get('lname');
    $agent->mname = Input::get('mname');
    $agent->id_number = Input::get('id_number');
    $agent->name = Input::get('name');
    $agent->gender = Input::get('gender');
    $agent->username = Input::get('username');
    $agent->save();

    return Response::json($agent, 201);
}

nullable、string 等验证规则要根据 Laravel 版本调整,较旧版本的写法可能有所不同。

调试时,可以直接查看 Laravel 实际收到的数据:

dd(Input::all(), Input::get('name'));

修正以后,Input::get('name') 应该返回字符串,而不是下面这样的数组:

[
    'id' => 1,
    'name' => 'Cash',
]

Model 是否需要修改

当前代码是逐个给属性赋值:

$agent->name = Input::get('name');

这种写法不会用到 $fillable,所以它不是本次报错的原因。$fillable 主要用于以下批量赋值操作:

Agent::create($data);

或:

$agent->fill($data);

$fillable 可以保留,但一般不需要把 id、created_at 和 updated_at 放进允许批量赋值的字段中:

class Agent extends \Eloquent
{
    protected $table = 'agent';

    protected $fillable = [
        'fname',
        'mname',
        'lname',
        'username',
        'id_number',
        'name',
        'gender',
    ];
}

如果 agent 表没有 created_at 和 updated_at 字段,还需要在模型中关闭时间戳:

public $timestamps = false;

否则会出现另一类数据库错误,但它与当前的 preg_replace() 参数不匹配无关。

注意事项

$.param(payment_post) 会把嵌套对象序列化为嵌套的表单参数。它只是按原样提交了 dropdown 绑定的整个对象,本身没有问题。需要修正的是 ng-options 的选择值:

item.name as item.name for item in payments

或者:

item.id as item.name for item in payments

Laravel 端也应验证该字段是否为预期的标量类型,这样就能在数据进入 Eloquent 之前发现同类问题。

备注:内容仅供参考。