【问题标题】:Laravel 7 - Problem with unique constraint on updateLaravel 7 - 更新唯一约束的问题
【发布时间】:2020-11-07 02:23:18
【问题描述】:

我正在尝试向我的模型添加唯一验证,但是当我尝试更新数据时出现错误。

桌子:

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" = $1 and "id" <> $2 ^ (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),我改的字段完美传递。

【问题讨论】:

  • 我不认为,您会收到此错误以进行验证。因为这是一个 SQL 错误。您在使用 Elequent 之前进行了验证。不知何故,primaryKey 不起作用,如果您将 AcqMBudgets::find($id); 更改为 AcqMBudgets::where('budget_id', $id); 可能会起作用。
  • 他在忽略子句中得到它,我很确定

标签: php laravel validation unique


【解决方案1】:

我会使用 Rule 命名空间,您可以通过它调用 unique。为此,您必须使用数组、验证规则而不是字符串,这无论如何都是更好的可读性方法。

Rule::unique有方法ignore(),其中第二个参数是id列,这个可以看here

'budget_code' => [
    'required',
    Rule::unique('acq_m_budgets', 'budget_code')->ignore($id, 'budget_id'),
    'max:15'
]

【讨论】:

  • 加分项:我永远不会像这样存储您的验证规则,而是使用表单请求来存储它。
  • 感谢您的回答。使用数组实际上确实增加了可读性,但是由于 Laravel 7.x 的官方文档只提到了使用字符串,所以直到现在我才尝试过 :) 回到主题,我尝试了使用 Rule 命名空间的建议。虽然错误已解决,但当我更新 budget_name 等列时(budget_code 本身除外),它显示budget_code 已被占用的异常
  • 在填充数据之前尝试 dd($post) 以查看它是否符合预期,或者在调用 save 之前 dd() 您的模型。
  • 预算代码是否已经在数据库中?现在关于你的问题的调试信息有点稀疏,很难知道我们什么时候看不到它
  • 我不敢相信我犯的错误。其实你的答案是正确的,除了Rule::unique('acq_m_budgets', 'budget_code')->ignore($id, 'budget_code')部分,应该是Rule::unique('acq_m_budgets', 'budget_code')->ignore($id, 'budget_id'),因为主键id是budget_id
猜你喜欢
  • 2019-04-14
  • 2022-01-05
  • 2017-01-10
  • 1970-01-01
  • 2012-03-30
  • 2011-02-17
  • 1970-01-01
  • 2015-12-10
  • 2014-10-01
相关资源
最近更新 更多