Answer the question
In order to leave comments, you need to log in
File upload and ActiveRecord - how? Namely, how to do saveAs of the file first, then model->save?
There is a standard task - a table with fields, one of the fields contains a file. Rather, it will contain the file name, and the file itself will be in a special folder. This solution is also quite standard.
So, I have an ActiveRecord successor model, I have a standard generated CRUD controller, everything works, but I need to add this very file.
What I do:
1. In the model, I declare the field itself (it’s as if it were a regular Model, by the way, for a long time I couldn’t understand why it says that it can’t getProperty, my attention was diverted by all these rules and fields and for some reason I began to think that if you write there, then ActiveRecord itself will create this field in the class, but in fact it creates them only for table columns) public $myfile_logo;
2. Then I add validation rules for the field in the model:
public function rules()
{
return [
...
[['myfile_logo'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
...
];
}
public function uploadMyFiles() {
//just gets it from $_FILES
$this->myfile_logo = UploadedFile::getInstance($this, 'myfile_logo');
//TODO this->validate() should be here,
// or all this should be in save() and validate should be in save
//$this->validate(['myfile_logo']); hasn't sense because ActiveRecord anyway validates all
//just move_uploaded_file
$newFileId = $this->myfile_logo->baseName . '_' . time() . '_' . uniqid();
$newFileName = $newFileId . '.png'; //TODO do not stupidly cast any extension to png
$saveRes = $this->myfile_logo->saveAs('files/images/' . $newFileName);
if ($saveRes){
$this->img_logo = $newFileId;
return true;
} else {
return false;
}
}
$model = new Fruit();
if ($model->load(Yii::$app->request->post()) && $model->uploadMyFiles() && $model->save()) {
...
$this->validate(['myfile_logo']);
Answer the question
In order to leave comments, you need to log in
Good afternoon. Everything is
in the
documentation .
p.s. I used mihaildev\elfinder\InputFile to upload the file, a perfectly acceptable solution.
Connects elementarily
<?= $form->field($model, 'logo')->widget(InputFile::className(),['path' => 'logo_dir', 'options' => ['readonly' => true]]) ?>
There are three main options.
1. Correct: Respect the Single Responsibility Principle.
Those. if there is some kind of model and you can additionally attach pictures to it, then create a separate class for the upload form, in its properties you can separately specify a set of properties for the model and separately upload files.
Actually, in the form validation rules, check files for compliance with formats. When saving the form, validate-save the file(s) separately and the model separately.
www.yiiframework.com/doc-2.0/guide-input-file-uplo...
2. Less correct: fix a bug in the current solution.
The problem is that your uploadMyFiles method is called before the validator. Accordingly, you can call it not in the controller, but in the afterValidate method of the model (it will be called before saving the model and after passing all validations).
3. Other methods (least preferred).
In the file validator, you can set a scenario in which it (not) will work, after loading - change the scenario to one in which the validator does not work. Another option is to use ready-made solutions. Another option is to replace the validator with a custom one that will check the file for format compliance and trigger a subsequent download.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question