The common task when data is sent from view to controller is uploading files. Also, in this case, Yii2 provides a convenient helper to handle this task: yiiwebUploadedFile
. This class has two important methods: getInstance()
(in plural form getInstances()
) and saveAs()
.
The first method, getInstance()
, allows us to get the file from the form's input field, while the second method, saveAs()
, as its name implies, allows us to save file input field content to the server filesystem.
Before we start with the example, it is important to create a folder that will contain the uploaded files. The best place to create this folder is at the root directory of the application. So create a folder named uploadedfiles
under the basic/
folder.
Next, to centralize configuration, define an alias for this new folder, so that we can change this path from app configuration. Enter in basic/config/web.php
and append the aliases
property, if it does not exist, to the $config
array with these lines:
'aliases' => [ '@uploadedfilesdir' => '@app/uploadedfiles' ],
In this example, we will see how to upload an image of a room.
We need to make changes in model, view, and controller. Let's start with model.
In model, we need to add a new property, named fileImage
, with its specific rule.
This is the final version of Model:
<?php namespace appmodels; use Yii; use yiiaseModel; class Room extends Model { public $floor; public $room_number; public $has_conditioner; public $has_tv; public $has_phone; public $available_from; public $price_per_day; public $description; public $fileImage; public function attributeLabels() { return [ 'floor' => 'Floor', 'room_number' => 'Room number', 'has_conditioner' => 'Conditioner available', 'has_tv' => 'TV available', 'has_phone' => 'Phone available', 'available_from' => 'Available from', 'price_per_day' => 'Price (Eur/day)', 'description' => 'Description', 'fileImage' => 'Image' ]; } /** * @return array the validation rules. */ public function rules() { return [ ['floor', 'integer', 'min' => 0], ['room_number', 'integer', 'min' => 0], [['has_conditioner', 'has_tv', 'has_phone'], 'integer', 'min' => 0, 'max' => 1], ['available_from', 'date', 'format' => 'php:Y-m-d'], ['price_per_day', 'number', 'min' => 0], ['description', 'string', 'max' => 500], ['fileImage', 'file'] ]; } }
In rules, for the fileImage
field, we can add many types of validation; for example, check if required, check mime type (.gif
, .jpeg
, and .png
).
Next, we will use the static method getInstance()
of the UploadedFile
class in controller, to get the file from the input file field and then use saveAs
to save in the specific folder. This is the final version of RoomsController
:
<?php namespace appcontrollers; use Yii; use yiiwebController; use appmodelsRoom; class RoomsController extends Controller { public function actionCreate() { $model = new Room(); $modelCanSave = false; if ($model->load(Yii::$app->request->post()) && $model->validate()) { $model->fileImage = UploadedFile::getInstance($model, 'fileImage'); if ($model->fileImage) { $model->fileImage->saveAs(Yii::getAlias('@uploadedfilesdir/' . $model->fileImage->baseName . '.' . $model->fileImage->extension))); } $modelCanSave = true; } return $this->render('create', [ 'model' => $model, 'modelSaved' => $modelCanSave ]); } }
UploadedFile::getInstance
gets the file from the $_FILES
array to fill the fileImage
property of Model with its data.
The last thing to do is to update the create
view content, by appending the fileInput
field. This is the final version:
<?php use yiihelpersHtml; use yiiwidgetsActiveForm; use yiihelpersUrl; use yiihelpersArrayHelper; ?> <?php if($modelCanSave) { ?> <div class="alert alert-success"> Model ready to be saved! <br /><br /> These are values: <br /> Floor: <?php echo $model->floor; ?> <br /> Room Number: <?php echo $model->room_number; ?> <br /> Has conditioner: <?php echo Yii::$app->formatter->asBoolean($model->has_conditioner); ?> <br /> Has TV: <?php echo Yii::$app->formatter->asBoolean($model->has_tv); ?> <br /> Has phone: <?php echo Yii::$app->formatter->asBoolean($model->has_phone); ?> <br /> Available from (mm/dd/yyyy): <?php echo Yii::$app->formatter->asDate($model->available_from,'php:m/d/Y'); ?> <br /> Price per day: <?php echo Yii::$app->formatter->asCurrency($model->price_per_day,'EUR'); ?> <br /> Image: <?php if(isset($model->fileImage)) { ?> <img src="<?php echo Url::to('@uploadedfilesdir/'.$model->fileImage->name) ?>" /> <?php } ?> </div> <?php } ?> <?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?> <div class="row"> <div class="col-lg-12"> <h1>Room form</h1> <?= $form->field($model, 'floor')->textInput() ?> <?= $form->field($model, 'room_number')->textInput() ?> <?= $form->field($model, 'has_conditioner')->checkbox() ?> <?= $form->field($model, 'has_tv')->checkbox() ?> <?= $form->field($model, 'has_phone')->checkbox() ?> <?= $form->field($model, 'available_from')->textInput() ?> <?= $form->field($model, 'price_per_day')->textInput() ?> <?= $form->field($model, 'description')->textarea() ?> <?= $form->field($model, 'fileImage')->fileInput() ?> </div> </div> <div class="form-group"> <?= Html::submitButton('Create' , ['class' => 'btn btn-success']) ?> </div> <?php ActiveForm::end(); ?>
Take care of the last row of this example, ActiveForm::end()
that closes the body of the $form
widget defined at the top of the file using the ActiveForm::begin()
method.
In this example, the ActiveForm
widget has been created by filling the enctype
property of the configuration array with the multipart/form-data
value, which allows us to send the binary data other than the form text parameters. However, this does not deal with Yii or PHP, because this is an HTML requirement for notifying the browser how to send files to the server.
In this view, if the model has been validated and the fileImage
property is filled, the corresponding image will be displayed.
18.117.70.132