问题描述:比如 A 与 B 是一个多对多的关系,现在在新建A的时候,要建立与B的一个多对多的关系?
1.在A的model 中定义好 relations ,在B的model中不需要再定义了。同时A model 里的其他都不用再定义了。
PS:(relationName 这个变量后面要用到的,后面的其它变量也是这个意思,我这里只是随意取的一个名字,在现实中要取的有意义)
'relations' => array(
'relationName' =>array(static::MANY_MANY,'B'),
),
2. 接下来 就是 AEditAndDetailsView.php 里定义了。在 global 中定义 derivedAttributeTypes,如下,配置好这个值,
'derivedAttributeTypes' => array(
'derivedElememtName',
),
然后在cell 里写上:
array('cells' =>
array(
array(
'elements' => array(
array('attributeName' => 'null', 'type' => 'derivedElememtName'),
),
),
)
),
这里的 derivedElememtName 就是自己自定义的一个Element.
3: 在A模块的 elements 文件夹先新建一个叫 derived 的文件夹 ,然后在里面新建一个 derivedElememtNameElement.php 的文件,这个文件名要对上,不然会报没有找到这个文件的错误的。
4:在这个类里,继承的是 MultiSelectRelatedModelsAutoCompleteElement 。这个可以参考Zurmo自己自带的多对多关系的那些代码。然后去看这个 父类的代码 要一些是必须要重写的方法。这些方法就关系着 B model .
protected function assertModelType()
{
assert('$this->model instanceof 'B');
}
这个方法如上
public static function getDisplayName()
{
这个方法就是显示新建的那个页面的提示文字
}
protected function getFormName()
{
return 'xxxxForm';
}
这个方法很重要,到时候就是将页面收集到的B model 的所有 的值保存到数据库的表单的。
protected function getUnqualifiedNameForIdField()
{
return '[xxxxxs]';
}
这个方法的作用和上面的那个一样,到时候 构成 xxxxForm[xxxxxs],就是类似 $_POST[][]这个样子吧,后面还会用到的。
protected function getUnqualifiedIdForIdField()
{
return 'xxxxxxxxxxxs';
}
这个方法也是要用上,到时候你审查元素的时候可以看到用在哪里了。
protected function getWidgetSourceUrl()
{
return Yii::app()->createUrl('A/default/autoCompleteAllxxxsForMultiSelectAutoComplete');
}
这个方法就是指向你去 ajax 获取 B model 的值的action
protected function getRelationName()
{
return 'relationName';
}
这个方法就是model 里的那个relationName.
public static function renderHtmlContentLabelFromxxxAndKeyword($productGroup)
{
这个方法就是将B model的数据显示在 表单里的方法
}
还有几个要重写的方法或者是和页面有关的方法,就自己去看吧。
5.现在到 那个action 里去 。可以去参考ProductTemplates 模块的 DefaultController 的代码 ,只需要写3个方法就行了。
PS: 这3个方法 , 你也可以写在一个新的controller 里 ,但是路由要对应上,但是下一步的那个方法,是要写 你的actionCreate的那个controller 中。除非你要重写actionCreate 里调用它的那个代码。
public function actionAutoCompleteAllProductCategoriesForMultiSelectAutoComplete($term)
直接搜这个方法就行了,到时候根据自己的实际需求改好代码。
echo CJSON::encode($autoCompleteResults);
方法里这个代码就是输出到页面的值。
http://localhost/XXXX/app/index.php/A/default/autoCompleteAllxxxForMultiSelectAutoComplete?term=xx
到时候用这个接口去测试,如果可以出来一个关于你的B model 的JSON 的话,你就成功的把数据库输出到页面上了。
PS:(B model 继承的应该 Item , 这点很重要,不然可能会出现Json出来了但是页面上去没有显示出来的情况)
6:接下来是要把数据存到数据库了。在你的actionCreate的那个controller 中 重写 getZurmoControllerUtil() 方法,看看步骤5的PS。
protected static function getZurmoControllerUtil()
{
return new xxxxxControllerUtil('AItems', 'AItemForm');
}
AItems 的 A 的头一个字母不用大写
7: 接下来 在 和 elements 同级新建一个叫 utils 的文件夹,在里面新建一个叫 xxxxxControllerUtil.php 的文件。里面只需要写两个方法就可以了,Zurmo自带的实现方法还多写了一个文件。
去参考 ProductTemplate 模块的 ProductTemplateZurmoControllerUtil 类 和 ProductTemplateProductCategoriesUtil 类 。
我自己是把这个两个文件的代码写在同一个文件了,就是
1:protected function afterSetAttributesDuringSave 方法
2:resolveProductTemplateHasManyxxxFromPost 方法
这两个方法里的参数都是有意义的,和在derivedElememtNameElement 定义的那些方法的值要对应的上,你去看product 模块的那个 productCategories的时候,可以边看控制台,边看代码。变量的名字要对的上。你想想post 表单是如何提交数据的时候,就会明白了。
8.写好代码之后,你可以用 zurmoc 命令去更新数据库 的模式,可以直接生成一个中间表。
9.刷新页面,就可以进行新建操作了。如果页面没变化的话,记得resolveCustomData=1 和 clearCache=1 操作。应该就可以插入成功了。
10.如有不对,请指正!