synatree/yii2-dynamic-relations
Composer 安装命令:
composer require synatree/yii2-dynamic-relations
包简介
Allows Yii2 views to contain a dynamically expanding set of fields based on model relations.
关键字:
README 文档
README
This extension came about after I googled in vain for such things as:
- Create 'child' models from a 'master' view dynamically
- Add Inputs to Yii2 views dynamically
- Use Yii2 widgets in related models
- Add fields to a form dynamically
Hopefully the above saves somebody else some time searching.
What does this do?
Sometimes a picture is worth 1000 words:
Allows Yii2 views to contain a dynamically expanding set of fields based on model relations.
This system allows you to define a view, conventionally called _inline.php, that will be auto-loaded each time a user hits the "add" button on your form.
Behind the scenes, the module takes care of saving the related records if they are new, updating them if they have been changed, and removing them if deleted.
Basically this is a way to add an arbitrarily expanding set of related records to your model using Ajax.
It's also been designed to intellegently move the JavaScripts and event bindings that your view's widgets may use so as not to conflict with each other when multiple "identical" views are added via ajax. Frankly, it's managing the JavaScript conflicts that arise that is the largest time-saver here.
I'm not sure how big of a deal the security implications actually are, but to be safe I've also implemented the ajax request portions of the code tied to the user's session, so replaying the same requests after the user has lost their session should not be possible. The way it's setup also basically hides the real name and path of the inline view; I just didn't like the idea of the script leaking server-side file paths in the HTML code.
Installation
The preferred way to install this extension is through composer.
Either run
php composer.phar require synatree/yii2-dynamic-relations "dev-master"
or add
"synatree/yii2-dynamic-relations": "dev-master"
to the require section of your composer.json file.
Next, you must add the following to your module config:
'modules' => [ ... 'dynamicrelations' => [ 'class' => '\synatree\dynamicrelations\Module' ], ...
Usage
The first thing you should do is to create a view called _inline.php for the model you which to use dynamically. This view can include arbitrary widgets, it's been tested with some widgets from Krajee.
This is the most complicated part, because we have to ensure that every time this view is invoked, the HTML and the script generated are unique.
You'll also have to tell DynamicRelations how to add and remove models by providing routes.
Finally, you'll have to maintain a certain structure in your field names so that the widget can pick up new vs existing models upon submit. Example:
use synatree\dynamicrelations\DynamicRelations; use kartik\widgets\ActiveForm; use kartik\datecontrol\DateControl; use yii\helpers\Url; /* @var $this yii\web\View */ /* @var $model app\models\BusinessHours */ /* @var $form kartik\widgets\ActiveForm */ // generate something globally unique. $uniq = uniqid(); if( $model->primaryKey ) { // you must define an attribute called "data-dynamic-relation-remove-route" if you plan to allow inline deletion of models from the form. $removeAttr = 'data-dynamic-relation-remove-route="' . Url::toRoute(['business-hours/delete', 'id'=>$model->primaryKey]) . '"'; $frag = "BusinessHours[{$model->primaryKey}]"; } else { $removeAttr = ""; // new models must go under a key called "[new]" $frag = "BusinessHours[new][$uniq]"; } ?> <div class="BusinessHours-form form-inline" <?= $removeAttr; ?>> <?= DateControl::widget([ 'type' => DateControl::FORMAT_DATE, 'name' => $frag.'[day]', // expanded, this ends up being something like BusinessHours[1][day] or BusinessHours[new][random][day] 'value' => $model->day, // for Kartik widgets, include the following line. This basically generates a globally unique set of pluginOptions, which is important to prevent // javascript errors and make sure everything works as expected. 'options' => DynamicRelations::uniqueOptions('day',$uniq) ]);?> .... More widgets use the same structure as above .... </div>
The next step is to setup the controller to save the related models you're expecting to receive. In the below example, we only have to add one small line to each of the create and update action methods.
use synatree\dynamicrelations\DynamicRelations; use app\models\BusinessHours; use yii\web\Controller; class SomeController extends Controller { /** * Creates a new SomethingModel model. * If creation is successful, the browser will be redirected to the 'view' page. * @return mixed */ public function actionCreate() { $model = new SomethingModel(); if ($model->load(Yii::$app->request->post()) && $model->save()) { // this next line is the only one added to a standard Gii-created controller action: DynamicRelations::relate($model, 'hours', Yii::$app->request->post(), 'BusinessHours', BusinessHours::className()); // Parent Model --^ ^-- Attribute ^-- Array to search ^-- Root Key ^-- Model Class Name return $this->redirect(['view', 'id' => $model->primaryKey]); } else { return $this->render('create', [ 'model' => $model, ]); } } public function actionUpdate($id) { ... if ($model->save()) { // this next line exactly the same as in actionCreate: DynamicRelations::relate($model, 'hours', Yii::$app->request->post(), 'BusinessHours', BusinessHours::className()); return $this->redirect(['view', 'id' => $model->boatShowId]); } else { return $this->render('update', [ 'model' => $model, ]); } ... } }
In order to support Ajax delete of related records, modify your related model controller:
/** * Deletes an existing BusinessHours model. * If deletion is successful, the browser will be redirected to the 'index' page. * @param integer $id * @return mixed */ public function actionDelete($id) { $this->findModel($id)->delete(); if(! Yii::$app->request->isAjax){ return $this->redirect(['index']); } else { return "OK"; } }
Finally, in your view for the parent model, include lines like the following for each related model you want to add dynamically.
use synatree\dynamicrelations\DynamicRelations; <?= DynamicRelations::widget([ 'title' => 'Business Hours', 'collection' => $model->hours, 'viewPath' => '@app/views/business-hours/_inline.php', // this next line is only needed if there is a chance that the collection above will be empty. This gives the script a prototype to work with. 'collectionType' => new \app\models\BusinessHours, ]); ?>
That should do it. I hope this helps people, I really wanted this feature.
synatree/yii2-dynamic-relations 适用场景与选型建议
synatree/yii2-dynamic-relations 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 2.8k 次下载、GitHub Stars 达 11, 最近一次更新时间为 2014 年 12 月 24 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「extension」 「yii2」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 synatree/yii2-dynamic-relations 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 synatree/yii2-dynamic-relations 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 synatree/yii2-dynamic-relations 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
A custom URL rule class for Yii 2 which allows to create translated URL rules
The Yii2 extension uses jQuery jquery.carousel-1.1.min.js and makes image carousel from php array of structure defined.
TYPO3 CMS extension to create gallery content element with preset crop ratios and pagination
UI Kit 3 Extension for Yii2
Adds more BBCode
Define your own css rule-sets for the TYPO3 CMS backend.
统计信息
- 总下载量: 2.8k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 12
- 点击次数: 19
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: GPL-3.0
- 更新时间: 2014-12-24