YII - Form表单上传文件
一、使用场景
像会员等级、商品品牌等一些情况均需要上传图片、Logo等,这时就需要用到图片上传,产品中封装了图片上传的控件,分为Ajax上传和普通的Form表单上传,这篇文章介绍如何进行普通的Form表单上传。
二、使用方式
0.页面引入图片预览的JS控件
{script src='@static/js/pic/imgPreview.js'}
1.Form表单中添加上传控件:
{input type='file-image' model=$model field='brand_logo' data-image="{imageurl}/{$model->brand_logo}" data-file="brandmodel-brand_logo"}
参数说明:
type:file-image 表示上传图片
model:表单的模型对象
field:模型中的属性
data-image:图片的url地址,如果图片已经存在,则鼠标悬浮上后会有预览图片的效果,点击图片可以查看大图,{imageurl}代表图片服务器的地址,通过{$model->brand_logo}获取图片的相对地址,拼接后即是完整的图片地址,如果图片地址仅仅是{imageurl}或者{imageurl}/ 那么程序将认为图片地址为空,鼠标悬浮上会看到默认的图片。
data-file:此属性指向用户点击上传图片的file控件的id,一般为当前控件的id,如果id为model+field自动生成的,则id符合YII的getInputId()格式
2.指定model类中添加attributeFiles函数,指定哪些属性为文件类型
/** * @inheritdoc */ public function attributeFiles () { return [ 'brand_logo' ]; }
这样,common\base\Model在model->load()的时候会自动识别出文件属性,并试图通过UploadFile::getInstance()函数获取文件,Model中加载文件的代码如下(仅对Post提交有效):
/** * 如果data为空则加载request中的post数据 * * @param unknown $data * @param unknown $formName */ public function loadPost ($data = null, $formName = null) { if($data == null) { $data = Yii::$app->request->post(); $scope = $formName === null ? $this->formName() : $formName; // 如果有属性为文件类型则自动加载 foreach($this->attributeFiles() as $key => $attribute) { // 如果$key为$this的一个属性,则表示将$attribute复制给$key $this->$attribute = UploadedFile::getInstance($this, $attribute); // 从提交的数据中清除,以免后面的load时被覆盖掉 if($scope === '' && ! empty($data)) { unset($data[$attribute]); } elseif(isset($data[$scope])) { unset($data[$scope][$attribute]); } } } return parent::load($data, $formName); }
3.为文件设置前后台的验证规则,并设置场景,一般情况下建议图片“添加”的时候为必填项,更新的时候为非必填项,如果为空则跳过,不为空则更新。
// imagerules()可以获取图片尺寸配置,需要在common/config/params-imagerules.php中进行配置 $rules[] = Model::addRule('brand_logo', 'image', array_merge(imagerules('brand_logo'), [ // 更新下 'on' => self::SCENARIO_UPDATE, // 为空时不校验 'skipOnEmpty' => true ])); // imagerules()可以获取图片尺寸配置,需要在common/config/params-imagerules.php中进行配置 $rules[] = Model::addRule('brand_logo', 'image', array_merge(imagerules('brand_logo'), [ // 更新下 'on' => self::SCENARIO_CREATE ]));
imagerules()函数的主要目的是为了统一维护图片的尺寸和验证规则,便于将来前台模板修改时,在不 修改代码的前提下仅仅通过修改配置文件即可达到修改验证规则的目的,如果有特殊情况可以自定义。
4.在控制器中编写上传图片的代码:
例如更新的时候:
if($this->request->isPost) { // 保留原来的数据 $brand_logo = $model->brand_logo; // 判断是否POST数据据,验证数据是否合法 if($model->load() && $model->validate()) { if($model->brand_logo != null) { $dir = format('/brandlogos/{0,date,yyyy/MM/dd/}', [ time() ]); $model->brand_logo->saveAs('@imagepath' . $dir); $model->brand_logo = $dir . $model->brand_logo->filename; } else { $model->brand_logo = $brand_logo; } try { $result = $model->update();
5.完成。
图片没有时,鼠标悬浮上后显示的默认图片
图片存在时或者用户选择图片后显示的选择图片(Html5预览图片)
用户点击图片显示大图