Przesyłanie plików w Yii jest zazwyczaj wykonywane przy użyciu klasy UploadedFile, która hermetyzuje każdy przesłany plik jako obiekt UploadedFile
.
W połączeniu z ActiveForm oraz modelem, możesz w łatwy sposób zaimplementować bezpieczny mechanizm przesyłania plików.
Tak jak przy zwykłych polach tekstowych, aby przesłać pojedyńczy plik musisz utworzyć klasę modelu oraz użyć atrybutu tego modelu do przechowania instancji przesłanego pliku. Powinieneś również zadeklarować zasadę walidacji do zwalidowania przesłanego pliku. Dla przykładu:
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;
class UploadForm extends Model
{
/**
* @var UploadedFile
*/
public $imageFile;
public function rules()
{
return [
[['imageFile'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
];
}
public function upload()
{
if ($this->validate()) {
$this->imageFile->saveAs('uploads/' . $this->imageFile->baseName . '.' . $this->imageFile->extension);
return true;
} else {
return false;
}
}
}
W powyższym kodzie, atrybut imageFile
zostanie użyty do przechowania instancji przesłanego pliku. Jest połączony z zasadą walidacji file
, która korzysta z
walidatora FileValidator, aby upewnić się, że przesłany plik posiada rozszerzenie png
lub jpg
.
Metoda upload()
wywoła walidację oraz zapis przesłanego pliku na serwerze.
Walidator file
pozwala na sprawdzenie rozszerzenia, wielkości, typu MIME, itp.
Po więcej szczegółów zajrzyj do sekcji Podstawowe walidatory
Wskazówka: Jeśli przesyłasz obrazek, możesz rozważyć użycie walidatora
image
. Walidator ten jest implementowany przez ImageValidator, który weryfikuje czy atrybut otrzymał prawidłowy obrazek który może być zapisany i przetworzony przez rozszerzenie Imagine.
Po zapisaniu modelu, utwórz pole wyboru pliku w widoku:
<?php
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'imageFile')->fileInput() ?>
<button>Wyślij</button>
<?php ActiveForm::end() ?>
Należy pamiętać, aby dodać opcję enctype
do formularza, przez co plik będzie mógł być prawidłowo przesłany.
Wywołanie fileInput()
spowoduje wyrenderowanie tagu <input type="file">
, który pozwala użytkownikowi na wybranie oraz przesłanie pliku.
Wskazówka: od wersji 2.0.8, fileInput dodaje automatycznie opcję
enctype
do formularza, kiedy pole typu 'file input' jest używane.
W akcji kontrolera musimy połączyć model oraz widok aby zaimplementować przesyłanie plików:
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\UploadForm;
use yii\web\UploadedFile;
class SiteController extends Controller
{
public function actionUpload()
{
$model = new UploadForm();
if (Yii::$app->request->isPost) {
$model->imageFile = UploadedFile::getInstance($model, 'imageFile');
if ($model->upload()) {
// plik został przesłany
return;
}
}
return $this->render('upload', ['model' => $model]);
}
}
W powyższym kodzie, kiedy formularz jest wysłany, metoda getInstance() wywoływana jest do reprezentowania pliku jako instancji UploadedFile
.
Następnie przystępujemy do walidacji modelu, aby upewnić się, że przesłany plik jest prawidłowy, po czym zapisujemy go na serwerze.
Możesz przesyłać wiele plików za jednym razem, modyfikując odrobinę kod wylistowany w powyższych sekcjach.
Najpierw powinieneś dostosować klasę modelu dodając opcję maxFiles
do zasady walidacji file
, aby określić dozwoloną maksymalną liczbę przesyłanych plików.
Metoda upload()
powinna również zostać zaktualizowana, aby zapisywać pliki jeden po drugim.
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;
class UploadForm extends Model
{
/**
* @var UploadedFile[]
*/
public $imageFiles;
public function rules()
{
return [
[['imageFiles'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg', 'maxFiles' => 4],
];
}
public function upload()
{
if ($this->validate()) {
foreach ($this->imageFiles as $file) {
$file->saveAs('uploads/' . $file->baseName . '.' . $file->extension);
}
return true;
} else {
return false;
}
}
}
W pliku widoku, powinieneś dodać opcję multiple
do wywołania fileInput()
, aby pole wyboru pliku pozwalało na wybór wielu plików na raz:
<?php
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'imageFiles[]')->fileInput(['multiple' => true, 'accept' => 'image/*']) ?>
<button>Submit</button>
<?php ActiveForm::end() ?>
Na koniec, w akcji kontrolera musimy zmienić wywołanie UploadedFile::getInstance()
na UploadedFile::getInstances()
, aby przypisać tablicę instancji UploadedFile
do UploadForm::imageFiles
.
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\UploadForm;
use yii\web\UploadedFile;
class SiteController extends Controller
{
public function actionUpload()
{
$model = new UploadForm();
if (Yii::$app->request->isPost) {
$model->imageFiles = UploadedFile::getInstances($model, 'imageFiles');
if ($model->upload()) {
// plik został przesłany
return;
}
}
return $this->render('upload', ['model' => $model]);
}
}
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.