Backpack for Laravel创建产品时报1364错误:produit_type_id无默认值
produit_type_id 未提交导致数据库错误 Illuminate\Database\QueryException
PHP 8.2.0
10.23.1
SQLSTATE[HY000]: General error: 1364 Field 'produit_type_id' doesn't have a default value
INSERT INTOproduits(nom,description,quantite,updated_at,created_at) VALUES (TEtrdesfddfsdf, dsfdfsdf, 10, 2023-09-26 14:39:57, 2023-09-26 14:39:57)
即使设置了$fillable或$guarded = [],请求中仍未携带produit_type_id字段,仅手动填写ID(比如用select_from_array)时才能正常工作。数据库中该字段不允许为NULL,需要排查字段未正确提交的原因。
提供的代码文件
迁移文件
produits表迁移
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. */ public function up(): void { Schema::create('produits', function (Blueprint $table) { $table->id(); $table->string('nom')->nullable(false); $table->string('quantite')->default(0); $table->longText('description')->nullable(); $table->unsignedBigInteger('produit_type_id')->nullable(false); $table->foreign('produit_type_id')->references('id')->on('produit_types'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('produits'); } };
produit_types表迁移
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. */ public function up(): void { Schema::create('produit_types', function (Blueprint $table) { $table->id(); $table->string('nom')->nullable(false); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('produit_types'); } };
模型文件
Produits模型
<?php namespace App\Models; use Backpack\CRUD\app\Models\Traits\CrudTrait; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; class Produits extends Model { use CrudTrait; use HasFactory; protected $guarded = []; protected $table = 'produits'; public function produitType(): HasOne { return $this->hasOne(ProduitTypes::class, 'id', 'produit_type_id'); } }
ProduitTypes模型
<?php namespace App\Models; use Backpack\CRUD\app\Models\Traits\CrudTrait; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasOne; class ProduitTypes extends Model { use CrudTrait; use HasFactory; protected $guarded = []; protected $table = 'produit_types'; public function produits(): BelongsToMany { return $this->belongsToMany(Produits::class); } }
CRUD控制器
<?php namespace App\Http\Controllers\Admin; use App\Http\Requests\ProduitsRequest; use App\Models\ProduitTypes; use Backpack\CRUD\app\Http\Controllers\CrudController; use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD; /** * Class ProduitsCrudController * @package App\Http\Controllers\Admin * @property-read \Backpack\CRUD\app\Library\CrudPanel\CrudPanel $crud */ class ProduitsCrudController extends CrudController { use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation; use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation; use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation; use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation; use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation; /** * Configure the CrudPanel object. Apply settings to all operations. * * @return void */ public function setup() { CRUD::setModel(\App\Models\Produits::class); CRUD::setRoute(config('backpack.base.route_prefix') . '/produits'); CRUD::setEntityNameStrings('produit', 'produits'); } /** * Define what happens when the List operation is loaded. * * @see https://backpackforlaravel.com/docs/crud-operation-list-entries * @return void */ protected function setupListOperation() { CRUD::setFromDb(); // set columns from db columns. /** * Columns can be defined using the fluent syntax: * - CRUD::column('price')->type('number'); */ } /** * Define what happens when the Create operation is loaded. * * @see https://backpackforlaravel.com/docs/crud-operation-create * @return void */ protected function setupCreateOperation() { $this->crud->addField([ 'name' => 'nom', 'label' => 'Nom', 'type' => 'text', 'placeholder' => 'Nom du produit', 'validationRules' => 'required|min:3' ]); $this->crud->addField([ 'label' => 'Type de produit', 'type' => 'select', 'name' => 'produit_type_id', 'entity' => 'produitType', 'attribute' => 'nom', 'model' => "App\Models\ProduitTypes", ]); $this->crud->addField([ 'name' => 'description', 'label' => 'Description', 'type' => 'textarea', 'placeholder' => 'Description du produit', 'validationRules' => 'required' ]); $this->crud->addField([ 'name' => 'quantite', 'label' => 'Quantité', 'type' => 'number', 'value' => '0', 'validationRules' => 'required' ]); } /** * Define what happens when the Update operation is loaded. * * @see https://backpackforlaravel.com/docs/crud-operation-update * @return void */ protected function setupUpdateOperation() { $this->setupCreateOperation(); } }
问题排查与修复步骤
1. 修正模型关联关系
模型关联定义错误会导致Backpack无法正确识别关联字段:
- Produits模型:
produitType应为BelongsTo关联(产品属于一个类型),而非HasOne:
// 替换原produitType方法 public function produitType(): \Illuminate\Database\Eloquent\Relations\BelongsTo { return $this->belongsTo(ProduitTypes::class, 'produit_type_id'); }
- ProduitTypes模型:
produits应为HasMany关联(一个类型对应多个产品),而非BelongsToMany:
// 替换原produits方法 public function produits(): \Illuminate\Database\Eloquent\Relations\HasMany { return $this->hasMany(Produits::class, 'produit_type_id'); }
2. 给CRUD的select字段添加必填验证
在setupCreateOperation的produit_type_id字段配置中添加验证规则,确保用户必须选择:
$this->crud->addField([ 'label' => 'Type de produit', 'type' => 'select', 'name' => 'produit_type_id', 'entity' => 'produitType', 'attribute' => 'nom', 'model' => "App\Models\ProduitTypes", 'validationRules' => 'required|exists:produit_types,id' // 添加此行 ]);
3. 检查ProduitsRequest类
确保App\Http\Requests\ProduitsRequest中包含produit_type_id的验证规则,且授权逻辑正常:
public function rules() { return [ 'nom' => 'required|min:3', 'produit_type_id' => 'required|exists:produit_types,id', 'description' => 'required', 'quantite' => 'required|numeric' ]; } public function authorize() { return backpack_auth()->check(); }
4. 验证字段渲染
检查创建页面的HTML源码,确认produit_type_id的select元素存在且name属性正确。若字段未渲染,大概率是模型关联错误导致Backpack无法加载选项。
内容的提问来源于stack exchange,提问作者edouard dragon

