Introduction
Ce petit tutoriel explique comment sauvegarder un fichier « image » avec Yii 2.
Modèle de base
Le modèle de base sur lequel sont basé les opérations présentées ci-dessous est le suivant :

Dans ce tutoriel, nous allons nous concentrer uniquement sur la classe/table Site qui contient une image (logo du site).
Prérequis
Avoir créé le CRUD des deux modèles à l’aide de Gii.
Opérations à effectuer
Modèle
Pour commencer, il faut modifier le modèle Site afin d’y ajouter la variable $image et des règles concernant l’image.
# modeles/Site.php
class Site extends \yii\db\ActiveRecord
{
public $image;
les règles :
# models/Site.php::rules()
// Other rules
[['image'], 'file', 'skipOnEmpty' => true,
'maxSize' => 102400, 'extensions' => 'jpg, jpeg, png',
'tooBig' => 'L\'image ne peut pas être plus grande que 100 Ko.',
'wrongExtension' => 'L\'image doit être au format JPG ou PNG.',
'on' => 'register'],
[['image'], 'file', 'skipOnEmpty' => false,
'maxSize' => 102400, 'extensions' => 'jpg, jpeg, png',
'tooBig' => 'L\'image ne peut pas être plus grande que 100 Ko.',
'wrongExtension' => 'L\'image doit être au format JPG ou PNG.',
'on' => 'update']
Dans cet exemple, l’image doit être de type jpg, jpeg ou png et ne doit pas être plus grande que 100 octets.
Form
Nous devons ensuite modifier le formulaire afin de permettre la sélection de l’image. Nous en profiterons pour épurer l’affichage du formulaire des données techniques de l’image (type et taille).
Il faut que le formulaire ait l’option enctype de type multipart/form-data.
use yii\widgets\ActiveForm;
$form = ActiveForm::begin(
[
'enableAjaxValidation' => false,
'options' => ['enctype' => 'multipart/form-data'],
]
);
Ensuite, il faut supprimer les lignes suivantes car ces champs seront renseignés par le controller :
<?= $form->field($model, 'image_name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'image_type')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'image_size')->textInput() ?>
Puis, il faut ajouter le champs « fichier » d’upload de l’image :
<?= $form->field($model, 'image')->fileInput() ?>
Controller
Finalement, nous allons voir comment récupérer et sauvegarder l’image. Pour ce faire, il faut modifier le controller controllers/SiteController.php.
Create
Nous allons commencer par modifier l’action actionCreate. Son état de base est le suivant :
public function actionCreate()
{
$model = new Site();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
Il faut la modifier comme suite :
public function actionCreate()
{
$model = new Site();
if (Yii::$app->request->isPost) {
$model->load(Yii::$app->request->post());
$model->image = UploadedFile::getInstance($model, 'image');
if($model->image !== null){
$model->image_name = $model->mnemo . '.' . $model->image->extension;
$model->image_type = $model->image->type;
$model->image_size = $model->image->size;
}
if ($model->save()) {
if($model->image !== null){
$model->image->saveAs('chemin/vers/destination');
}
return $this->redirect(['view','id' => $model->id]);
}
}
return $this->render('create', ['model' => $model]);
}
Il faut également ajouter en début de document le namespace pour pouvoir utiliser le helper du même nom :
use yii\web\UploadedFile;
Update
Les modifications à apporter à l’action Update sont très similaire à l’action Create.
L’action sans modification est la suivante :
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
Nous la modifions comme suite :
public function actionUpdate($id)
{
$model = $this->findModel($id);
if (Yii::$app->request->isPost) {
$model->load(Yii::$app->request->post());
$upload = UploadedFile::getInstance($model, 'image');
if($upload !== null){
$model->image_name = $model->mnemo . '.' . $upload->extension;
$model->image_type = $upload->type;
$model->image_size = $upload->size;
}
if ($model->save()) {
if($upload !== null){
$model->image = $upload;
$model->image->saveAs('chemin/vers/destination');
}
return $this->redirect(['view','id' => $model->id]);
}
}
return $this->render('update', ['model' => $model]);
}
Delete
Il ne faut pas oublier de supprimer le fichier lors du lancement de l’action Delete. Pour ce faire, nous utilisons la fonction unlink de PHP.
Action d’origine :
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
Action modifiée :
public function actionDelete($id)
{
$model = $this->findModel($id);
$filename = $model->image_name;
$model->delete();
unlink('chemin/vers/destination' . $filename);
return $this->redirect(['index']);
}
Remarques
Dans ce tutoriel, nous n’avons pas abordé plusieurs aspect qu’il est important de traiter dans un projet réel :
- centraliser le chemin vers les image dans les paramètres de l’application