情况就是这样:我是Yii2的新手,想在ActiveForm中使用一些文件上传器小部件..到目前为止,我发现这个非常优秀:\kartik\widget\FileInput
使用此小部件,我可以管理文件上传,然后在进入编辑模式时,使用oportunite显示上一个上传的图像以替换它。
问题在于,如果我按下表格的“更新”按钮而不修改图像,则说明图像“不能为空”,因为我在模型中设置了“必需”规则。
答案 0 :(得分:7)
在一个糟糕的下午和一个更有成效的夜晚之后,我遇到了一个对我有用的解决方案..
主要问题是文件输入在更新时不发送其值(存储在数据库中的文件的名称)。它仅在浏览并通过文件输入选择时发送图像信息..
所以,我的解决方法是创建另一个"虚拟"用于管理文件上传的字段,名为" upload_image"。为实现这一点,我简单地将一个带有此名称的公共属性添加到我的模型类中:public $upload_image;
我还将以下验证添加到Model类的规则方法:
public function rules()
{
return [
[['upload_image'], 'file', 'extensions' => 'png, jpg', 'skipOnEmpty' => true],
[['image'], 'required'],
];
}
此处,' upload_image'是我的虚拟专栏。我添加了' file'使用' skipOnEmpty'验证= true,' image'是我的数据库中的字段,在我的情况下必须是必需的。
然后,在我看来,我配置了'upload_image'小部件如下:
echo FileInput::widget([
'model' => $model,
'attribute' => 'upload_image',
'pluginOptions' => [
'initialPreview'=>[
Html::img("/uploads/" . $model->image)
],
'overwriteInitial'=>true
]
]);
在" initialPreview'选项I我的图像名称,存储在' $ model-> image'从数据库返回的属性。
最后,我的控制器如下:
public function actionUpdate($id)
{
$model = $this->findModel($id);
$model->load(Yii::$app->request->post());
if(Yii::$app->request->isPost){
//Try to get file info
$upload_image = \yii\web\UploadedFile::getInstance($model, 'upload_image');
//If received, then I get the file name and asign it to $model->image in order to store it in db
if(!empty($upload_image)){
$image_name = $upload_image->name;
$model->image = $image_name;
}
//I proceed to validate model. Notice that will validate that 'image' is required and also 'image_upload' as file, but this last is optional
if ($model->validate() && $model->save()) {
//If all went OK, then I proceed to save the image in filesystem
if(!empty($upload_image)){
$upload_image->saveAs('uploads/' . $image_name);
}
return $this->redirect(['view', 'id' => $model->id]);
}
}
return $this->render('update', [
'model' => $model,
]);
}
答案 1 :(得分:4)
我通过创建方案遇到了另一种解决方案。在你的情况下,我会修改这样的规则:
public funtion rules() {
[['image'], 'file'],
[['image'], 'required', 'on'=> 'create']
}
因此仅在create action中需要fileupload字段。在更新操作中,我有以下代码:
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post())) {
$newCover = UploadedFile::getInstance($model, 'image');
if (!empty($newCover)) {
$newCoverName = Yii::$app->security->generateRandomString();
unlink($model->cover);
$model->cover = 'uploads/covers/' . $newCoverName . '.' . $newCover->extension;
$newCover->saveAs('uploads/covers/' . $newCoverName . '.' . $newCover->extension);
}
if ($model->validate() && $model->save()) {
return $this->redirect(['view', 'id' => $model->post_id]);
} else {
// error saving model
}
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
在更新方案中,图像文件不是必需的,但代码会检查是否上传了任何内容并且不会更改以前的值。
我的表单文件:
<?= $form->field($model, 'image')->widget(FileInput::classname(), [
'options' => ['accept'=>'image/*'],
'pluginOptions'=>[
'allowedFileExtensions'=>['jpg', 'gif', 'png', 'bmp'],
'showUpload' => true,
'initialPreview' => [
$model->cover ? Html::img($model->cover) : null, // checks the models to display the preview
],
'overwriteInitial' => false,
],
]); ?>
我认为比虚拟领域更容易一些。希望它有所帮助!
答案 2 :(得分:3)
尝试使用该字段的内容预加载文件输入字段。这样,您在提交表单后就不会丢失数据。
我查看了kartik file-input widget(很好的发现,顺便说一句),我遇到了一种方法来做到这一点
// Display an initial preview of files with caption
// (useful in UPDATE scenarios). Set overwrite `initialPreview`
// to `false` to append uploaded images to the initial preview.
echo FileInput::widget([
'name' => 'attachment_49[]',
'options' => [
'multiple' => true
],
'pluginOptions' => [
'initialPreview' => [
Html::img("/images/moon.jpg", ['class'=>'file-preview-image', 'alt'=>'The Moon', 'title'=>'The Moon']),
Html::img("/images/earth.jpg", ['class'=>'file-preview-image', 'alt'=>'The Earth', 'title'=>'The Earth']),
],
'initialCaption'=>"The Moon and the Earth",
'overwriteInitial'=>false
]
]);
您可能还想放宽模型中针对该字段的required
规则,因此它不会在验证时抱怨。您可以选择通过更微妙的方式提示用户。
答案 3 :(得分:-4)
来自Krajee:
http://webtips.krajee.com/advanced-upload-using-yii2-fileinput-widget
创建,删除,更新:非常简单,不用再看了。
(1)我已经设定了所需的&#39;也在我的模型中统治。
(2)在Wampserver上工作:
Yii::$app->params['uploadPath'] = Yii::$app->basePath . '/web/uploads/';
Yii::$app->params['uploadUrl'] = Yii::$app->urlManager->baseUrl . '/uploads/';