alexs / yii2-tabularload
A simple extension for complex forms have a tabular input for Yii2 Framework.
1.1.0
2021-10-09 22:05 UTC
Requires
- php: >=7.1
- yiisoft/yii2: ^2.0
Requires (Dev)
This package is auto-updated.
Last update: 2024-11-10 06:59:17 UTC
README
A simple trait for complex forms which have a tabular input for Yii2 Framework.
It makes sense when we have a create/update form with relations one-to-many inside to do fast input, for example the main form adds Countries and it has many related Cities inside.
SQL
CREATE TABLE `country` (
`id` int(4) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`population` int(4) DEFAULT NULL
) ENGINE=InnoDB;
CREATE TABLE `city` (
`id` int(4) NOT NULL,
`country_id` int(4) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`is_capital` tinyint(1) DEFAULT '0',
`foundation` int(4) DEFAULT NULL,
`image` varchar(255) DEFAULT NULL
) ENGINE=InnoDB;
ALTER TABLE `country`
ADD PRIMARY KEY (`id`);
ALTER TABLE `city`
ADD PRIMARY KEY (`id`),
ADD KEY `fk-city-country_id` (`country_id`);
ALTER TABLE `country`
MODIFY `id` int(4) NOT NULL AUTO_INCREMENT;
ALTER TABLE `city`
MODIFY `id` int(4) NOT NULL AUTO_INCREMENT;
ALTER TABLE `city`
ADD CONSTRAINT `fk-city-country_id` FOREIGN KEY (`country_id`) REFERENCES `country` (`id`) ON DELETE SET NULL;
Models
Country
<?php
namespace alexs\yii2tabularload\tests\models;
use yii\db\ActiveRecord;
/**
* @property int $id
* @property string $name
* @property int $population
*/
class Country extends ActiveRecord
{
public function rules() {
return [
[['name', 'population'], 'filter', 'filter'=>'trim'],
[['name', 'population'], 'required'],
['population', 'integer'],
];
}
}
City
<?php
namespace alexs\yii2tabularload\tests\models;
use alexs\yii2tabularload\TraitTabularload;
use yii\db\ActiveRecord;
/**
* @property int $id
* @property int $country_id
* @property string $name
* @property int $is_capital
* @property int $foundation
* @property string $image
* @property Country $course
*/
class City extends ActiveRecord
{
use TraitTabularload;
public function rules() {
return [
[['name', 'foundation'], 'filter', 'filter'=>'trim'],
[['name', 'foundation'], 'required'],
[['is_capital', 'foundation'], 'integer'],
//['image', 'image', 'extensions'=>['jpg', 'jpeg', 'png', 'gif']],
['image', 'string'], // just for tests
];
}
/**
* @return \yii\db\ActiveQuery
*/
public function getCountry() {
return $this->hasOne(Country::class, ['id' => 'country_id']);
}
}
The form
<div class="form">
<!-- existing cities -->
<?php if (!empty($cities)) { ?>
<?php foreach ($cities as $i=>$city) { ?>
<div class="row">
<div class="col col-lg-6">
<?=$activeForm->field($city, "[$i]name", ['enableClientValidation'=>false])?>
<?=$activeForm->field($city, "[$i]foundation", ['enableClientValidation'=>false])->textarea();?>
<?=$activeForm->field($city, "[$i]is_capital", ['enableClientValidation'=>false])->checkbox();?>
</div>
<?=$activeForm->field($city, "[$i]id", ['enableClientValidation'=>false])->hiddenInput()->label(false);?>
</div>
<?php } ?>
<?php } ?>
<!-- 3 new empty blocks, they can be added via JS -->
<?php $city = new City;?>
<?php for ($i = 0; $i <= 2; $i ++) { ?>
<div class="row">
<div class="col col-lg-6">
<?=$activeForm->field($city, "[$i]name", ['enableClientValidation'=>false])?>
<?=$activeForm->field($city, "[$i]foundation", ['enableClientValidation'=>false])->textarea();?>
<?=$activeForm->field($city, "[$i]is_capital", ['enableClientValidation'=>false])->checkbox();?>
</div>
</div>
<?php } ?>
</div>
Actions
Create
<?php
public function actionCreate() {
$country = new Country();
$cities = [];
if (\Yii::$app->request->isPost) {
$country->load(\Yii::$app->request->post());
$cities = City::tabularloadCreate('\app\models\City');
$valid = $country->validate() && City::validateMultiple($cities);
if ($valid) {
$country->save(false);
City::tabularloadSave($cities, 'country', $country);
return $this->redirect('/countries');
}
}
return $this->render([
'country'=>$country,
'cities'=>$cities,
]);
}
Update
<?php
public function actionUpdate($id) {
if (!$country = Country::findOne($id)) {
throw new \yii\web\NotFoundHttpException;
}
$cities = [];
if (\Yii::$app->request->isPost) {
$country->load(\Yii::$app->request->post());
$cities = City::tabularloadUpdate('\app\models\City', ['country_id'=>$country->id]);
$valid = $country->validate() && City::validateMultiple($cities);
if ($valid) {
$country->save(false);
City::tabularloadSave($cities, 'country', $country);
return $this->redirect('/countries');
}
}
return $this->render([
'country'=>$country,
'cities'=>$cities,
]);
}