elisdn/yii2-composite-form

Yii2 框架的嵌套表单基类。

安装数: 160,907

依赖者: 8

建议者: 0

安全: 0

星标: 53

关注者: 8

分支: 16

公开问题: 6

类型:yii2-extension

1.1.0 2018-03-04 14:15 UTC

This package is not auto-updated.

Last update: 2024-09-17 15:03:46 UTC


README

该扩展允许创建嵌套表单模型。

安装

使用 composer 安装

composer require elisdn/yii2-composite-form

使用示例

创建任何简单的表单模型,用于 SEO 信息

class MetaForm extends Model
{
    public $title;
    public $description;
    public $keywords;

    public function rules()
    {
        return [
            [['title'], 'string', 'max' => 255],
            [['description', 'keywords'], 'string'],
        ];
    }
}

以及特性

class ValueForm extends Model
{
    public $value;

    private $_characteristic;

    public function __construct(Characteristic $characteristic, $config = [])
    {
        $this->_characteristic = $characteristic;
        parent::__construct($config);
    }

    public function rules()
    {
        return [
            ['value', 'safe'],
        ];
    }

    public function attributeLabels()
    {
        return [
            'value' => $this->_characteristic->name,
        ];
    }

    public function getCharacteristicId()
    {
        return $this->_characteristic->id;
    }
}

然后创建一个复合表单模型,它将两者都用作内部表单

use elisdn\compositeForm\CompositeForm;

/**
 * @property MetaForm $meta
 * @property ValueForm[] $values
 */
class ProductCreateForm extends CompositeForm
{
    public $code;
    public $name;

    public function __construct($config = [])
    {
        $this->meta = new MetaForm();
        $this->values = array_map(function (Characteristic $characteristic) {
            return new ValueForm($characteristic);
        }, Characteristic::find()->orderBy('sort')->all());
        parent::__construct($config);
    }

    public function rules()
    {
        return [
            [['code', 'name'], 'required'],
            [['code', 'name'], 'string', 'max' => 255],
            [['code'], 'unique', 'targetClass' => Product::className()],
        ];
    }

    protected function internalForms()
    {
        return ['meta', 'values'];
    }
}

就是这样。之后只需使用外部 $form 以及内部 $form->meta$form->values 模型为 ActiveForm

<?php $form = ActiveForm::begin(); ?>

    <h2>Common</h2>
    
    <?= $form->field($model, 'code')->textInput() ?>
    <?= $form->field($model, 'name')->textInput() ?>
    
    <h2>Characteristics</h2>
    
    <?php foreach ($model->values as $i => $valueForm): ?>
        <?= $form->field($valueForm, '[' . $i . ']value')->textInput() ?>
    <?php endforeach; ?>
    
    <h2>SEO</h2>

    <?= $form->field($model->meta, 'title')->textInput() ?>
    <?= $form->field($model->meta, 'description')->textarea(['rows' => 2]) ?>
    
    <div class="form-group">
        <?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?>
    </div>

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

以及您的应用程序服务

class ProductManageService
{
    private $products;
    
    public function __construct(ProductRepository $products)
    {
        $this->products = $products;
    }

    public function create(ProductCreateForm $form)
    {
        $product = Product::create(
            $form->code,
            $form->name,
            new Meta(
                $form->meta->title,
                $form->meta->description,
                $form->meta->keywords
            )
        );

        foreach ($form->values as $valueForm) {
            $product->changeValue($valueForm->getCharacteristicId(), $valueForm->value);
        }

        $this->products->save($product);

        return $product->id;
    }

    ...
}

使用简单的控制器进行网络

class ProductController extends \yii\web\Controller
{
    ...

    public function actionCreate()
    {
        $form = new ProductCreateForm();

        if ($form->load(Yii::$app->request->post()) && $form->validate()) {
            $id = $this->service->create($form);
            return $this->redirect(['view', 'id' => $id]);
        }

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

或 API

class ProductController extends \yii\rest\Controller
{
    ...

    public function actionCreate()
    {
        $form = new ProductCreateForm();
        $form->load(Yii::$app->request->getBodyParams());

        if ($form->validate()) {
            $id = $this->service->create($form);
            $response = Yii::$app->getResponse();
            $response->setStatusCode(201);
            $response->getHeaders()->set('Location', Url::to(['view', 'id' => $id], true));
            return [];
        }

        return $form;
    }
}