Laravel 7 - 更新的唯一约束问题
Laravel 7 - Problem with unique constraint on update
我正在尝试向我的模型添加唯一验证,但是当我尝试更新数据时出现错误。
table:
acq_m_budgets
==================================
budget_id serial NOT NULL,
budget_code character varying(15) NOT NULL,
budget_name character varying(100) NOT NULL,
ma_code character varying(10),
start_period timestamp without time zone NOT NULL,
end_period timestamp without time zone NOT NULL,
budget numeric(16) DEFAULT 0,
credit numeric(16) DEFAULT 0,
debet numeric(16) DEFAULT 0,
balance numeric(16) DEFAULT 0,
reserve numeric(16) DEFAULT 0,
created_by character varying(100) NOT NULL,
created_on timestamp without time zone DEFAULT now(),
updated_by character varying(100) NOT NULL,
updated_on timestamp without time zone DEFAULT now(),
CONSTRAINT PK_AcqMBudgets PRIMARY KEY (budget_id),
CONSTRAINT UN_AcqMBudgets UNIQUE (budget_code)
我的模型:AcqMBudgets.php
class AcqMBudgets extends Model
{
public $timestamps = false;
protected $primaryKey = 'budget_id';
public $sortable = ['budget_code', 'budget_name', 'ma_code', 'balance', 'updated_on'];
protected $fillable = ['budget_code', 'budget_name', 'ma_code', 'start_period', 'end_period', 'budget', 'credit', 'debet', 'balance', 'reserve', 'created_by', 'created_on', 'updated_by', 'updated_on'];
protected $attributes = [
'budget' => 0,
'credit' => 0,
'debet' => 0,
'balance' => 0,
'reserve' => 0,
];
public static function createRules()
{
return [
'budget_code' => 'required|unique:acq_m_budgets,budget_code|max:15',
'budget_name' => 'required|max:100',
'ma_code' => 'max:10',
'start_period' => 'required',
'end_period' => 'required',
];
}
public static function updateRules($id)
{
return [
'budget_code' => 'required|unique:acq_m_budgets,budget_code,' . $id . '|max:15',
'budget_name' => 'required|max:100',
'ma_code' => 'max:10',
'start_period' => 'required',
'end_period' => 'required',
];
}
}
我的控制器:BudgetController.php
...
public function create(Request $request)
{
$validateData = $request->validate(AcqMBudgets::createRules());
$model = new AcqMBudgets;
$post = $request->only($model->getFillable());
$post['start_period'] = (!empty($post['start_period'])) ? date('Y-m-d', strtotime(str_replace('/', '-', $post['start_period']))) : null;
$post['end_period'] = (!empty($post['end_period'])) ? date('Y-m-d', strtotime(str_replace('/', '-', $post['end_period']))) : null;
$model->fill($post);
$model->save();
return redirect()->route('acq.view.master.budget', ['id' => $model->budget_id, 'rf' => 'a']);
}
...
public function update($id, Request $request)
{
$validateData = $request->validate(AcqMBudgets::updateRules($request->input('budget_id')));
$model = AcqMBudgets::find($id);
$post = $request->only($model->getFillable());
$post['start_period'] = (!empty($post['start_period'])) ? date('Y-m-d', strtotime(str_replace('/', '-', $post['start_period']))) : null;
$post['end_period'] = (!empty($post['end_period'])) ? date('Y-m-d', strtotime(str_replace('/', '-', $post['end_period']))) : null;
$model->fill($post);
$model->save();
return redirect()->route('acq.view.master.budget', ['id' => $model->budget_id, 'rf' => 'e']);
}
...
在模型上,我已经分离了创建和更新方法的规则。区别在于updateRules(),规则数组中需要一个主键参数。
在控制器上,在 update
功能上,有一个错误指出:SQLSTATE[42703]: Undefined column: 7 ERROR: column "id" does not exist LINE 1: ...from "acq_m_budgets" where "budget_code" = and "id" <> ^ (SQL: select count(*) as aggregate from "acq_m_budgets" where "budget_code" = N01 and "id" <> )
。
我用的主键是整型递增的,但是由于某些情况,主键的名称不能只是id
,所以我改成了budget_id
并且已经声明了在模型的开头。根据错误消息,似乎 Laravel 一直在尝试与此 id
字段而不是我声明的字段进行比较。需要做什么来解决这个问题?
代码更新:
我在 createRules 上使用了 Rule
命名空间,在模型上使用了 updateRules:
public static function createRules()
{
return [
'budget_code' => ['required', Rule::unique('acq_m_budgets', 'budget_code'), 'max:15'],
'budget_name' => ['required', 'max:100'],
'ma_code' => ['max:10'],
'start_period' => ['required'],
'end_period' => ['required'],
];
}
public static function updateRules($id)
{
return [
'budget_code' => ['required', Rule::unique('acq_m_budgets', 'budget_code')->ignore($id, 'budget_code'), 'max:15'],
'budget_name' => ['required', 'max:100'],
'ma_code' => ['max:10'],
'start_period' => ['required'],
'end_period' => ['required'],
];
}
当我尝试更新数据时,我对 budget_code
以外的某些字段进行了更改。如果我不更改 budget_code
字段,则不会保存更改,因为它总是给出错误:"budget_code" has already been taken
。我用的是dd($post)
,我改的字段完美传递
我会使用 Rule 命名空间,您可以在其中调用 unique。为此,您必须使用数组来验证规则而不是字符串,无论如何这是提高可读性的更好方法。
Rule::unique
有方法ignore()
其中第二个参数是id列,这个可以看here.
'budget_code' => [
'required',
Rule::unique('acq_m_budgets', 'budget_code')->ignore($id, 'budget_id'),
'max:15'
]
我正在尝试向我的模型添加唯一验证,但是当我尝试更新数据时出现错误。
table:
acq_m_budgets
==================================
budget_id serial NOT NULL,
budget_code character varying(15) NOT NULL,
budget_name character varying(100) NOT NULL,
ma_code character varying(10),
start_period timestamp without time zone NOT NULL,
end_period timestamp without time zone NOT NULL,
budget numeric(16) DEFAULT 0,
credit numeric(16) DEFAULT 0,
debet numeric(16) DEFAULT 0,
balance numeric(16) DEFAULT 0,
reserve numeric(16) DEFAULT 0,
created_by character varying(100) NOT NULL,
created_on timestamp without time zone DEFAULT now(),
updated_by character varying(100) NOT NULL,
updated_on timestamp without time zone DEFAULT now(),
CONSTRAINT PK_AcqMBudgets PRIMARY KEY (budget_id),
CONSTRAINT UN_AcqMBudgets UNIQUE (budget_code)
我的模型:AcqMBudgets.php
class AcqMBudgets extends Model
{
public $timestamps = false;
protected $primaryKey = 'budget_id';
public $sortable = ['budget_code', 'budget_name', 'ma_code', 'balance', 'updated_on'];
protected $fillable = ['budget_code', 'budget_name', 'ma_code', 'start_period', 'end_period', 'budget', 'credit', 'debet', 'balance', 'reserve', 'created_by', 'created_on', 'updated_by', 'updated_on'];
protected $attributes = [
'budget' => 0,
'credit' => 0,
'debet' => 0,
'balance' => 0,
'reserve' => 0,
];
public static function createRules()
{
return [
'budget_code' => 'required|unique:acq_m_budgets,budget_code|max:15',
'budget_name' => 'required|max:100',
'ma_code' => 'max:10',
'start_period' => 'required',
'end_period' => 'required',
];
}
public static function updateRules($id)
{
return [
'budget_code' => 'required|unique:acq_m_budgets,budget_code,' . $id . '|max:15',
'budget_name' => 'required|max:100',
'ma_code' => 'max:10',
'start_period' => 'required',
'end_period' => 'required',
];
}
}
我的控制器:BudgetController.php
...
public function create(Request $request)
{
$validateData = $request->validate(AcqMBudgets::createRules());
$model = new AcqMBudgets;
$post = $request->only($model->getFillable());
$post['start_period'] = (!empty($post['start_period'])) ? date('Y-m-d', strtotime(str_replace('/', '-', $post['start_period']))) : null;
$post['end_period'] = (!empty($post['end_period'])) ? date('Y-m-d', strtotime(str_replace('/', '-', $post['end_period']))) : null;
$model->fill($post);
$model->save();
return redirect()->route('acq.view.master.budget', ['id' => $model->budget_id, 'rf' => 'a']);
}
...
public function update($id, Request $request)
{
$validateData = $request->validate(AcqMBudgets::updateRules($request->input('budget_id')));
$model = AcqMBudgets::find($id);
$post = $request->only($model->getFillable());
$post['start_period'] = (!empty($post['start_period'])) ? date('Y-m-d', strtotime(str_replace('/', '-', $post['start_period']))) : null;
$post['end_period'] = (!empty($post['end_period'])) ? date('Y-m-d', strtotime(str_replace('/', '-', $post['end_period']))) : null;
$model->fill($post);
$model->save();
return redirect()->route('acq.view.master.budget', ['id' => $model->budget_id, 'rf' => 'e']);
}
...
在模型上,我已经分离了创建和更新方法的规则。区别在于updateRules(),规则数组中需要一个主键参数。
在控制器上,在 update
功能上,有一个错误指出:SQLSTATE[42703]: Undefined column: 7 ERROR: column "id" does not exist LINE 1: ...from "acq_m_budgets" where "budget_code" = and "id" <> ^ (SQL: select count(*) as aggregate from "acq_m_budgets" where "budget_code" = N01 and "id" <> )
。
我用的主键是整型递增的,但是由于某些情况,主键的名称不能只是id
,所以我改成了budget_id
并且已经声明了在模型的开头。根据错误消息,似乎 Laravel 一直在尝试与此 id
字段而不是我声明的字段进行比较。需要做什么来解决这个问题?
代码更新:
我在 createRules 上使用了 Rule
命名空间,在模型上使用了 updateRules:
public static function createRules()
{
return [
'budget_code' => ['required', Rule::unique('acq_m_budgets', 'budget_code'), 'max:15'],
'budget_name' => ['required', 'max:100'],
'ma_code' => ['max:10'],
'start_period' => ['required'],
'end_period' => ['required'],
];
}
public static function updateRules($id)
{
return [
'budget_code' => ['required', Rule::unique('acq_m_budgets', 'budget_code')->ignore($id, 'budget_code'), 'max:15'],
'budget_name' => ['required', 'max:100'],
'ma_code' => ['max:10'],
'start_period' => ['required'],
'end_period' => ['required'],
];
}
当我尝试更新数据时,我对 budget_code
以外的某些字段进行了更改。如果我不更改 budget_code
字段,则不会保存更改,因为它总是给出错误:"budget_code" has already been taken
。我用的是dd($post)
,我改的字段完美传递
我会使用 Rule 命名空间,您可以在其中调用 unique。为此,您必须使用数组来验证规则而不是字符串,无论如何这是提高可读性的更好方法。
Rule::unique
有方法ignore()
其中第二个参数是id列,这个可以看here.
'budget_code' => [
'required',
Rule::unique('acq_m_budgets', 'budget_code')->ignore($id, 'budget_id'),
'max:15'
]