如果您问“ Yii是什么?” 查阅我之前的教程: Yii Framework简介 ,它回顾了Yii的优点,并概述了2014年10月发布的Yii 2.0的新功能。
在本《 如何使用Yii2编程》系列中 ,我指导读者使用PHP的Yii2框架。 在本教程中,我将指导您了解在Yii2中上传文件和图像的基础知识。
对于这些示例,我们将继续想象我们正在构建一个用于发布简单状态更新的框架,例如我们自己的微型Twitter。 上图显示了上传我拍摄的泰姬陵照片时写的简短更新。
提醒一下,我确实参与了下面的评论主题。 如果您有不同的方法,其他想法或想为将来的教程提供建议,我特别感兴趣。 如果您有任何问题或建议,请在下面发布。 您也可以直接通过Twitter @reifman与我联系 。
文件上传插件
Yii2有两个似乎最强大的文件上传插件:
对于本教程,我决定继续使用Kartik的插件。 我发现它比2Amigos插件更易于使用和文档记录。 但是,BlueImp File Uploader具有一些您可能想要探索的有趣的用户体验功能(如下所示):
使用FileInput插件
让我们开始安装和使用文件上传器,并将其集成到类似Twitter的状态创建小程序中。 同样,我们将使用Yii2 Hello应用程序树,您可以通过旁边或下方的GitHub按钮链接下载该树。
安装插件
首先,我们可以使用composer将kartik-v/yii2-widget-fileinput
到我们的应用程序中:
$ composer require kartik-v/yii2-widget-fileinput "*"
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Updating kartik-v/yii2-widget-fileinput (dev-master 36f9f49 => v1.0.4)
Checking out 36f9f493c2d814529f2a195422a8af2e020fc80c
Writing lock file
Generating autoload files
扩展状态表
接下来,我们需要为要上传到“状态”表中的文件添加字段。 在此示例中,我们将允许用户上传图像以及其状态更新。
我们将添加的字段用于上传文件的原始文件名以及将存储在我们服务器上以供显示的唯一文件名:
- image_src_filename
- image_web_filename
创建一个新的迁移,以将以下字段添加到“状态”表中:
$ ./yii migrate/create extend_status_table_for_image
Yii Migration Tool (based on Yii v2.0.6)
Create new migration '/Users/Jeff/Sites/hello/migrations/m160316_201654_extend_status_table_for_image.php'? (yes|no) [no]:yes
New migration created successfully.
这是将两个字段添加为字符串的定制迁移:
<?php
use yii\db\Schema;
use yii\db\Migration;
class m160316_201654_extend_status_table_for_image extends Migration
{
public function up()
{
$tableOptions = null;
if ($this->db->driverName === 'mysql') {
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
}
$this->addColumn('{{%status}}','image_src_filename',Schema::TYPE_STRING.' NOT NULL');
$this->addColumn('{{%status}}','image_web_filename',Schema::TYPE_STRING.' NOT NULL');
}
public function down()
{
$this->dropColumn('{{%status}}','image_src_filename');
$this->dropColumn('{{%status}}','image_web_filename');
return false;
}
}
然后,运行迁移:
$ ./yii migrate/up
Yii Migration Tool (based on Yii v2.0.6)
Total 1 new migration to be applied:
m160316_201654_extend_status_table_for_image
Apply the above migration? (yes|no) [no]:yes
*** applying m160316_201654_extend_status_table_for_image
> add column image_src_filename string NOT NULL to table {{%status}} ... done (time: 0.044s)
> add column image_web_filename string NOT NULL to table {{%status}} ... done (time: 0.011s)
*** applied m160316_201654_extend_status_table_for_image (time: 0.071s)
Migrated up successfully.
由于Yii2是使用模型视图控制器(MVC)架构构建的,因此我们需要为文件上传器实现其他三个编码区域:
- 状态模型
- 状态视图和表格
- 状态控制器
增强模型功能
现在,我们将对/models/Status.php
文件进行更改。 首先,我们需要提供新图像字段的属性和验证规则,以及小部件将用来上传文件的临时$image
变量。
下面,我们为两个新的$image_xxx_filename
变量添加注释,并创建一个名为$image
的公共临时变量:
/**
* This is the model class for table "status".
*
* @property integer $id
* @property string $message
* @property integer $permissions
* @property string $image_src_filename
* @property string $image_web_filename
* @property integer $created_at
* @property integer $updated_at
* @property integer $created_by
*
* @property User $createdBy
*/
class Status extends \yii\db\ActiveRecord
{
const PERMISSIONS_PRIVATE = 10;
const PERMISSIONS_PUBLIC = 20;
public $image;
接下来,我们将为图像添加验证规则,例如文件类型和最大大小:
public function rules()
{
return [
[['message'], 'required'],
[['message'], 'string'],
[['permissions', 'created_at', 'updated_at','created_by'], 'integer'],
[['image'], 'safe'],
[['image'], 'file', 'extensions'=>'jpg, gif, png'],
[['image'], 'file', 'maxSize'=>'100000'],
[['image_src_filename', 'image_web_filename'], 'string', 'max' => 255], ];
}
以及视图的新属性标签:
public function attributeLabels()
{
return [
'id' => Yii::t('app', 'ID'),
'message' => Yii::t('app', 'Message'),
'permissions' => Yii::t('app', 'Permissions'),
'image_src_filename' => Yii::t('app', 'Filename'),
'image_web_filename' => Yii::t('app', 'Pathname'),
'created_by' => Yii::t('app', 'Created By'),
'created_at' => Yii::t('app', 'Created At'),
'updated_at' => Yii::t('app', 'Updated At'), ];
}
现在我们可以继续查看ActiveModel表单中的View更改。
添加我们的视图和表单功能
将图像上传集成到状态创建表单
要启用图像上传到状态更新的表单集成(如上所示),我们需要对/views/status/_form.php
文件进行更改。
首先,我们在顶部附近添加kartik\file\FileInput
小部件,并将表单更新为多部分,从而支持发布文件:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use app\assets\StatusAsset;
use kartik\file\FileInput;
StatusAsset::register($this);
/* @var $this yii\web\View */
/* @var $model app\models\Status */
/* @var $form yii\widgets\ActiveForm */
?>
<div class="status-form">
<?php
$form = ActiveForm::begin([
'options'=>['enctype'=>'multipart/form-data']]); // important
?>
然后,在“权限”字段和“提交”按钮之间,添加FileInput小部件:
<?=
$form->field($model, 'permissions')->dropDownList($model->getPermissions(),
['prompt'=>Yii::t('app','- Choose Your Permissions -')]) ?>
</div>
</div>
<div class="row">
<?= $form->field($model, 'image')->widget(FileInput::classname(), [
'options' => ['accept' => 'image/*'],
'pluginOptions'=>['allowedFileExtensions'=>['jpg','gif','png'],'showUpload' => false,],
]); ?>
</div>
<div class="row">
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
</div>
在pluginOptions
行中,我们将文件类型限制为常见的图像格式,例如jpg。
完成后,它将看起来像这样,等待用户添加图像:
显示影像
我还将添加代码以显示上载的图像以供以后使用(在完成对控制器的支持之后)。
首先,我将其添加到状态视图页面( /views/status/view.php
),这是非常基础的。 但是,我将在项目详细信息下方显示图像:
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'createdBy.email',
'message:ntext',
'permissions',
'image_web_filename',
'image_src_filename',
'created_at',
'updated_at',
],
]) ?>
<?php
if ($model->image_web_filename!='') {
echo '<br /><p><img src="'.Yii::$app->homeUrl. '/uploads/status/'.$model->image_web_filename.'"></p>';
}
?>
它看起来像这样:
我们还将在状态索引页面( /views/status/index.php
)中添加一个小的缩略图视图。 我向Yii2的GridView小部件添加了一个自定义列属性:
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
'message:ntext',
'permissions',
'created_at',
[
'attribute' => 'Image',
'format' => 'raw',
'value' => function ($model) {
if ($model->image_web_filename!='')
return '<img src="'.Yii::$app->homeUrl. '/uploads/status/'.$model->image_web_filename.'" width="50px" height="auto">'; else return 'no image';
},
],
['class' => 'yii\grid\ActionColumn',
'template'=>'{view} {update} {delete}',
'buttons'=>[
'view' => function ($url, $model) {
return Html::a('<span class="glyphicon glyphicon-eye-open"></span>', 'status/'.$model->slug, ['title' => Yii::t('yii', 'View'),]);
}
],
],
],
]); ?>
最终,它将如下所示:
建立控制器支持
为了使以上所有可能成为可能,我们需要完成控制器集成。
在/controllers/StatusController.php
的顶部,我们必须包含yii\web\UploadedFile
:
<?php
namespace app\controllers;
use Yii;
use app\models\Status;
use app\models\StatusSearch;
use app\models\User;
use app\components\AccessRule;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use yii\web\UploadedFile;
然后,我们必须更新actionCreate
函数:
public function actionCreate()
{
$model = new Status();
if ($model->load(Yii::$app->request->post())) {
$image = UploadedFile::getInstance($model, 'image');
if (!is_null($image)) {
$model->image_src_filename = $image->name;
$ext = end((explode(".", $image->name)));
// generate a unique file name to prevent duplicate filenames
$model->image_web_filename = Yii::$app->security->generateRandomString().".{$ext}";
// the path to save file, you can set an uploadPath
// in Yii::$app->params (as used in example below)
Yii::$app->params['uploadPath'] = Yii::$app->basePath . '/web/uploads/status/';
$path = Yii::$app->params['uploadPath'] . $model->image_web_filename;
$image->saveAs($path);
}
if ($model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
var_dump ($model->getErrors()); die();
}
}
return $this->render('create', [
'model' => $model,
]);
}
本质上,这将执行以下操作:
- 我们从上传文件的表单信息(
image_src_filename
)中捕获原始文件名。 - 我们为服务器生成一个唯一的文件名(
image_web_filename
)。 - 我们将文件保存到我们的上传目录(
/web/uploads/status/
)。 - 我们保存模型。
- 我们重定向到增强型视图页面。
您可以在上面的图像中看到最终的结果,其中包括泰姬陵的照片。
Kartik的File Input Widget还提供了更高级的配置,这些配置他都很好地记录在案,例如拖放:
在以下页面上查看更多这些内容:
下一步是什么?
希望这对您在Yii2应用程序中上传文件的基础有所帮助。 如果您希望看到这种功能的另一个类似的演练,请查看使用PHP构建您的启动:用户设置,个人资料图片和联系方式 。 该教程使用选项卡,更新用户配置文件和缩放图像,与本教程提供的集成稍有不同。
在继续研究框架的不同方面时,请观看“ 如何使用Yii2编程”系列中即将发布的教程。 您可能还需要查看“ 使用PHP构建您的启动”系列 ,该系列在构建真实应用程序时使用了Yii2的高级模板。
如果您想知道下一个Yii2教程何时到达, 请在Twitter上关注我@reifman或查看我的讲师页面 。 发布后,我的讲师页面将包含本系列中的所有文章。
相关链接
这是我用来研究和编写本教程的各种链接:
- Yii2开发者交流 ,我的Yii2资源网站
- FileInput Widget演示作者-Kartik
- 使用FileInput小部件在Yii 2中上传文件-Kartik
- kartik-v / yii2-widget-fileinput的代码(GitHub)
- BlueImp JQuery文件上传演示
- 2 amigos/yii2-file-upload-widget的代码:BlueImp文件上传小部件(Github)
- 上传文件-Yii 2.0权威指南
翻译自: https://code.tutsplus.com/tutorials/how-to-program-with-yii2-uploading-files--cms-23511