Yii2——同时上传文件和其他表单项

本文链接:https://www.cnblogs.com/alanabc/p/9443391.html

本文的关键是想解释关于验证规则的问题,因为涉及到上传文件的时候,初学者常会在这里陷入错误,导致上传失败。

假设现有需求如下:创建一个表单,表单项一是普通的输入框,用来输入文件名称;表单项二是文件选择框,用来选择一个文件;点击上传按钮完成上传,并录入数据库。

在官方指导的基础上,我添加了一点点东西,以适应以上需求(官方文档:https://www.yiiframework.com/doc/guide/2.0/zh-cn/input-file-upload)。

创建模型

数据库中用来记录该项数据的表名为 document,因此首先要有对应的模型 Document.php

<?php
namespace app\models;

use yii\db\ActiveRecord;

// 注意是继承自ActiveRecord
class Document extends ActiveRecord
{

}

我们使用 ActiveForm 来上传表单,因此再新建一个模型类 DocumentAddForm.php

<?php
namespace app\models;

use yii\base\Model;
use yii\web\UploadedFile;

// 注意是继承自 Model,与上面的不同
class DocumentAddForm extends Model
{
    public $file;
    public $name;
    private $filePath;

    public function rules()
    {
        return [
            ['name', 'required', 'message' => '不能为空'],
            ['file', 'file', 'skipOnEmpty' => false, 'uploadRequired' => '请选择文件']
        ];
    }

    public function upload()
    {
        // $this->file早已在控制器中完成了赋值,传入了一个 UploadedFile 对象
        // $this->validate()是验证上面rules定义的规则,原因见下文
        if ($this->validate()) {
            // 加入时间戳time()防止文件重名,这里的文件路径是相对于web/目录的,也就是你的可访问目录
            $this->filePath = 'uploads/' . $this->file->baseName . '_' . time() . '.' . $this->file->extension;
            $this->file->saveAs($this->filePath);
            return true;
        } else {
            return false;
        }
    }

    public function add()
    {
        // 如果上传成功,就把文件名和文件路径存入数据库
        if ($this->upload()) {
            $model = new Document();
            $model->name = $this->name;
            $model->path = $this->filePath;
            return $model->save();
        }
        return false;
    }
}

控制器

namespace app\controllers;

use Yii;
use yii\web\Controller;

class SiteController extends Controller
{
    public function actionDocument()
    {
        $modelAdd = new DocumentAddForm();
        // 载入提交的数据,一般我们会在load()之后紧接着就进行validate(),验证是不是符合DocumentAddForm类的规则,但是这里不能这样,原因见下文
        if ($modelAdd->load(Yii::$app->request->post())) {
            // 上传文件通常借助yii\web\UploadedFile类,封装成UploadedFile对象后传递给$modelAdd->file
            $modelAdd->file = UploadedFile::getInstance($modelAdd, 'file');
            $this->checkAddResult($modelAdd->add());
        }

        return $this->render('document', [
            'modelAdd' => $modelAdd
        ]);
    }
}

视图

视图里通过 ActiveForm 把表单渲染输出,注意 file 使用 fileInput() 就可以了

<?php $form_formAdd = ActiveForm::begin([
    'id' => 'formAdd-form',
    'fieldConfig' => [
        'template' => '{label}{input}<small class="text-danger">{error}</small>',
        'labelOptions' => ['class' => '']
        ]
        ]);
        ?>
        
    <?= $form_formAdd->field($modelAdd, 'name')->textInput()->label('文件名') ?>
        
    <?= $form_formAdd->field($modelAdd, 'file')->fileInput(['class' => 'btn btn-light col-12'])->label('') ?>
        
    <?= Html::submitButton('添加', ['class' => 'btn btn-primary']) ?>
        
<?php
ActiveForm::end();
?>

解释原因(何时验证规则)

我们在模型和控制器中留下了两个待解释的地方,就是 validate() 的使用。

按照往常的做法,我们会在控制器中先 load() 载入提交的数据,紧接着就进行 validate() 验证,但是请注意,此时进行验证的话,由于提交上来的数据没有 file 字段(上传文件传的是文件信息数组),因此就会报缺少文件的提示(因为在模型中定义了规则:'skipOnEmpty'=>false)。

真正给 DocumentAddForm 模型的 $file 赋值是在控制器的这一行:

$modelAdd->file = UploadedFile::getInstance($modelAdd, 'file');

,应该在这行赋值完成后再进行验证,所以才把 validate() 放在 DocumentAddForm 模型中。

另外,DocumentAddForm 模型中还有一个变量是 $name,这个变量是要存到数据库的,所以要接收表单传上来的值,这个在 $modelAdd->load(Yii::$app->request->post()) 就自动载入了。

如果还遇到了一些其他的问题,仍然可以尝试 var_dump($model->getErrors()) 来看是什么错误。

转载于:https://www.cnblogs.com/alanabc/p/9443391.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值