必须确保表单enctype正确、模型接收UploadedFile实例、控制器完成保存并写回路径,否则字段为空或文件未落地;数据库用VARCHAR(255)字段,模型声明public $image并配置file和string验证规则;视图启用multipart表单并绑定fileInput;控制器依次获取实例、判空、生成唯一路径、创建目录、保存文件、写入相对路径后保存模型。

要在Yii2中实现图片上传并自动将路径存入数据库字段,必须确保表单 enctype 正确、模型能接收 UploadedFile 实例、控制器完成保存逻辑且路径写回模型属性——缺一不可,否则数据库字段为空或文件未落地。
准备数据库字段与模型验证规则
在数据表中为图片路径预留 【VARCHAR(255)】 类型字段(如 image_path),不要用 TEXT,避免迁移时被 Yii 自动转为 longtext 导致索引失效。
在 Model 类中声明 public $image;并在 rules() 方法里加入 [['image'], 'file', 'extensions' => 'jpg, jpeg, png, gif', 'maxFiles' => 1];这一步不加,$model->validate() 会直接跳过文件校验,上传后模型仍认为无错误。
同时追加 [['image_path'], 'string', 'max' => 255] 验证规则,防止 saveAs 生成的长路径超出字段长度导致 SQL 报错。
视图层:启用 multipart 表单并绑定 fileInput
使用 ActiveForm::begin() 时必须传入 ['options' => ['enctype' => 'multipart/form-data']],否则浏览器根本不会发送二进制文件流,后台收到的永远是空 $_FILES。
调用 $form->field($model, 'image')->fileInput(['accept' => 'image/*']),注意这里绑定的是临时上传属性 $model->image,不是数据库字段 image_path——这是 Yii2 文件上传的标准解耦设计。
如果用了 kartik-v/yii2-widget-fileinput,要显式设置 'pluginOptions' => ['maxFileCount' => 1],否则用户可能误选多张图,而模型规则只允许一张,导致 validate 失败却无提示。
控制器:提取、保存、写回三步闭环
第一步:从模型中获取上传实例 → $uploadedFile = UploadedFile::getInstance($model, 'image');
第二步:检查是否真有文件上传 → if ($uploadedFile === null) { return $this->redirect(['create']); },不加这句,用户没选图就提交,saveAs 会抛出 Trying to get property of non-object 异常。
第三步:构造唯一保存路径 → $fileName = date('YmdHis') . '_' . uniqid() . '.' . $uploadedFile->extension; $uploadPath = Yii::getAlias('@webroot') . '/uploads/' . date('Y/m/d') . '/';
第四步:创建目录并保存 → if (!is_dir($uploadPath)) { mkdir($uploadPath, 0755, true); } $uploadedFile->saveAs($uploadPath . $fileName); 这里 【0755 权限不可省略】,否则 Linux 下 webserver 进程无法读取图片,前端 403 错误。
第五步:把相对路径写入模型数据库字段 → $model->image_path = str_replace(Yii::getAlias('@webroot'), '', $uploadPath . $fileName); 然后调用 $model->save() 持久化。











