< 返回 1.9 Joomla field showon属性的进一步说明 - 博客

Joomla的field字段中有一个showon属性,用来设置该字段显示的条件。之前使用这个属性在相同的fields里面,完全没有问题。但如果两个字段在不同的fields里面,需要进行条件控制,此时应该如何做呢?查找了很多的文档,都没有找到答案,最后自己通过分析joomla的源码,找到了解决方案。

问题描述

在开发在线视频教程组件的时候,有这样的一个需求,如果视频为付费,则显示价格字段。如果视频为免费,则显示是否要求注册字段。

 实现这个需求在joomla中很简单,只需要使用showon字段就行了。但这次遇到了问题。价格字段可以使用showon控制,但登录观看字段却不行,经过分析师因为登录观看字段在另外的一个fields里面。表单的XML结构如下:

<fieldset label="费用信息" name="price"
		addfieldpath="administrator/components/com_zmedia/models/fields"
		>
		<field 
			name="type" 
			type="zradio"
			label="付费类型" 
			default="0"
			class="btn-group btn-group-yesno"
			description="该课程是收费课程还是免费课程" 
		>
			<option value="1">付费</option>
			<option value="0">免费</option>
		</field>
		<field 
				name="price" 
				type="ztext"
				label="价格"
				showlist="0" 
				default="0.1"
				showon="type:1"
				description="如果课程为付费课程,则该课程的价格" 
			>
		</field>
		<fields name="params">
			<field 
				name="visit_type" 
				type="zradio"
				class="btn-group-yesno btn-group"
				label="登录观看" 
				default="0"
				showlist="0"
				showon="type:0"
				description="该课程的观看类型,如何设置为登录观看,那么该课程中的视频都需要登录才能观看。" 
				
			>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
			
			<field 
				name="preview" 
				type="zradio"
				label="允许试看" 
				default="1"
				showlist="false"
				class="btn-group btn-group-yesno"
				description="当你在创建视频的时候设置了试看,那么你可以启用这个" 
			>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
		</fields>
	</fieldset>

问题如何解决

在所有介绍showon字段的文档中,都是假设字段都在同一个分组中,并没有介绍不在同一分组中的情况。使用chatGPT咨询后,它建议我自己写一个。感觉说了和没说一样。最后我决定分析一下源码。

在网站根目录 \libraries\src\Form\FormHelper.php,期中关于showon的代码部分如下:

 public static function parseShowOnConditions($showOn, $formControl = null, $group = null)
    {
        // Process the showon data.
        if (!$showOn) {
            return array();
        }

        $formPath = $formControl ?: '';

        if ($group) {
            $groups = explode('.', $group);

            // An empty formControl leads to invalid shown property
            // Use the 1st part of the group instead to avoid.
            if (empty($formPath) && isset($groups[0])) {
                $formPath = $groups[0];
                array_shift($groups);
            }

            foreach ($groups as $group) {
                $formPath .= '[' . $group . ']';
            }
        }

        $showOnData  = array();
        $showOnParts = preg_split('#(\[AND\]|\[OR\])#', $showOn, -1, PREG_SPLIT_DELIM_CAPTURE);
        $op          = '';

        foreach ($showOnParts as $showOnPart) {
            if (($showOnPart === '[AND]') || $showOnPart === '[OR]') {
                $op = trim($showOnPart, '[]');
                continue;
            }

            $compareEqual     = strpos($showOnPart, '!:') === false;
            $showOnPartBlocks = explode(($compareEqual ? ':' : '!:'), $showOnPart, 2);

            $dotPos = strpos($showOnPartBlocks[0], '.');

            if ($dotPos === false) {
                $field = $formPath ? $formPath . '[' . $showOnPartBlocks[0] . ']' : $showOnPartBlocks[0];
            } else {
                if ($dotPos === 0) {
                    $fieldName = substr($showOnPartBlocks[0], 1);
                    $field     = $formControl ? $formControl . '[' . $fieldName . ']' : $fieldName;
                } else {
                    if ($formControl) {
                        $field = $formControl . ('[' . str_replace('.', '][', $showOnPartBlocks[0]) . ']');
                    } else {
                        $groupParts = explode('.', $showOnPartBlocks[0]);
                        $field      = array_shift($groupParts) . '[' . join('][', $groupParts) . ']';
                    }
                }
            }

            $showOnData[] = array(
                'field'  => $field,
                'values' => explode(',', $showOnPartBlocks[1]),
                'sign'   => $compareEqual === true ? '=' : '!=',
                'op'     => $op,
            );

            if ($op !== '') {
                $op = '';
            }
        }

        return $showOnData;
    }

 通过上面的代码,返现实际上传递来的$showon会自动分成两个部分,一个是分组,一个是真正的字段名称。看到这里我有一个大胆的猜想,也许我可以给字段前面加一个点(.),高速系统使用上一个分组。经过测试,发现这个想法完美的实现我的需求。

总结

在showon中,关于条件字段的名称,实际是两部分组件,第一部分是字段分组,第二部分才是字段的名称,如果没有分组,则默认使用当前的分组。如果不使用分组,则在字段的前面加一个点(.).如下:

<field 
				name="visit_type" 
				type="zradio"
				class="btn-group-yesno btn-group"
				label="登录观看" 
				default="0"
				showlist="0"
				showon=".type:0"
				description="该课程的观看类型,如何设置为登录观看,那么该课程中的视频都需要登录才能观看。" 
				
			>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

 说明

如果在Joomla3上面使用.type的方式没有作用,那么是joomla核心的bug.直接替换文件FormHelper.php。文件路径如下:网站根目录/libraries/src/Form/FormHelper.php

FormHelper.php文件的下载

FormHelper.php

 

博客

第1章:经验分享
第2章:专题教程
第3章:扩展推荐
第13章:扩展更新日志
  • 内容提要
  • 留言讨论 (0)
  • 视频教程
Joomla的field字段中有一个showon属性,用来设置该字段显示的条件。之前使用这个属性在相同的fields里面,完全没有问题。但如果两个字段在不同的fields里面,需要进行条件控制,此时应该如何做呢?查找了很多的文档,都没有找到答案,最后自己通过分析joomla的源码,找到了解决方案。

评论 (0)

  • 最新在前
  • 最佳在前

内容待完善

该课程提供视频版,可以观看完整的视频教程