@ZaurK

Как обработать две модели в одной форме?

Пытаюсь реализовать что-то наподобие вот этого, только на экшне добавления продукта в базу и одновременного прикрепления картинки. Надо сказать, что по-отдельности добавление записи в таблицу продуктов и загрузки файла картинки на сервер работали, но решил объединить эти модели и обрабатывать их в одной форме.
Вот соответствующий экшн из ProductController.php:
public function actionCreate()
    {
        $model = new Product();
		$uploadForm = new UploadForm();

        if ($model->load(Yii::$app->request->post()) && $uploadForm->load(Yii::$app->request->post()) ) {
            $isValid = $model->validate();
            $isValid = $uploadForm->validate() && $isValid;
			if ($isValid) {
                $model->save(false);
                $uploadForm->save(false);
				return $this->redirect(['view', 'id' => $model->id]);
            }
			
        }

        return $this->render('create', [
            'model' => $model,
            'uploadForm' => $uploadForm,
        ]);
    }

models/UploadForm.php:
<?php
namespace backend\models;

use Yii;
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()) {
			$dir = Yii::getAlias('@uploads') . '/images/';
            $this->imageFile->saveAs($dir . $this->imageFile->baseName . '.' . $this->imageFile->extension);
            return true;
        } else {
            return false;
        }
    }
}
?>

models/Product.php:
<?php

namespace backend\models;

use Yii;
use backend\models\Category;
use yii\helpers\ArrayHelper;
/**
 * This is the model class for table "product".
 *
 * @property int $id
 * @property int $cat_id
 * @property string $ptitle
 * @property string $pdescription
 * @property string $img_path
 */
class Product extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'product';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['cat_id', 'ptitle'], 'required'],
            [['cat_id'], 'integer'],
            [['pdescription'], 'string'],
            [['ptitle', 'img_path'], 'string', 'max' => 256],
			[['cat_id'], 'exist', 'skipOnError' => true, 'targetClass' => Category::className(), 'targetAttribute' => ['cat_id' => 'id']],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'cat_id' => 'Категория',
            'ptitle' => 'Название продукции',
            'pdescription' => 'Описание продукции',
            'img_path' => 'Img Path',
        ];
    }
	
	/**
     * @return \yii\db\ActiveQuery
     */
    public function getCategory()
    {
        return $this->hasOne(Category::className(), ['id' => 'cat_id']);
    }

    public function getCatName()
    {
        // Выбираем 
    $cattitle = Category::find()
        ->select(['id', 'ctitle'])
		->where(['id' => $this->cat_id])
        ->one();

    return $cattitle ? $cattitle->ctitle : 'hhh';
    }
	
	public static function getCatsList()
{
    // Выбираем 
    $parents = Category::find()
        ->select(['id', 'ctitle'])
        ->all();
 
    return ArrayHelper::map($parents, 'id', 'ctitle');
}
}

views/product/create.php:
<?php

use yii\helpers\Html;


/* @var $this yii\web\View */
/* @var $model backend\models\Product */

$this->title = 'Добавить продукт';
$this->params['breadcrumbs'][] = ['label' => 'Продукция', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="product-create">

    <h1><?= Html::encode($this->title) ?></h1>

    <?= $this->render('_form', [
        'model' => $model,
		'uploadForm' => $uploadForm,
    ]) ?>

</div>

views/product/_form.php:
<?php

use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;
use backend\models\Category;

/* @var $this yii\web\View */
/* @var $model backend\models\Product */
/* @var $form yii\widgets\ActiveForm */
?>

<div class="product-form">

     <?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data'], 'action' => ['product/create'],]); ?>
	
	<?php
    $categories = ArrayHelper::map(Category::find()->all(), 'id', 'ctitle');
    echo $form->field($model, 'cat_id')->dropDownList($categories, ['prompt' => 'Выберите категорию']);
    ?>

    <?= $form->field($model, 'ptitle')->textInput(['maxlength' => true]) ?>

    <?= $form->field($model, 'pdescription')->textarea(['rows' => 6]) ?>

     <?= $form->field($uploadForm, 'imageFile')->fileInput() ?>
	
	

    <div class="form-group">
        <?= Html::submitButton('Сохранить', ['class' => 'btn btn-success']) ?>
    </div>

    <?php ActiveForm::end(); ?>	
</div>

В результате, при отправке формы с заполненными полями и выбранным изображением, около поля выбора файла появляется надпись "файл не выбран", очевидно, что не проходит валидацию наличие файла. Попробовал распечатать переменную $_POST - действительно все заполнено, кроме переменной для файла.
Подскажите, в чем ошибка и как это правильно реализовать?
  • Вопрос задан
  • 79 просмотров
Пригласить эксперта
Ответы на вопрос 1
slo_nik
@slo_nik Куратор тега Yii
Добрый вечер.
Для начала сохраните модель Products, сформируйте имя для нового файла и передайте это имя в модель UploadForm.
Имя файла создайте в beforeSave();
Так же используйте транзакцию. Если файл не загрузится - откатите транзакцию.
Получается, что Вам надо сохранить одну модель.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы