基本上我有一个源于 Joomla 3.1 的 JSON 处理的问题,尽管因为我无法隔离它,所以我提出了这个问题以寻求指导。如果这是我应该报告的错误或我的应用程序中的某些内容,这将有望用于隔离。
Joomla 3.1 似乎有一个插件,或者在默认$model->save()
或$table->save()
. 这可能会导致在保存任何类型的页面时对 JSON 字段进行不必要的添加。到目前为止,通过他们的代码查看我一直无法隔离它(女巫让我想到插件,虽然我只启用了默认值。)
所以这是一个问题:
Joomla 是否对表单输入进行任何 JSON 处理?如果可以,可以禁用吗?
为了澄清我个人的问题,我有一个骨架组件保存功能(将一些次要值保存到数据库中,一列是 JSON 字段)。它使用JModelAdmin
并通过它JTable
来处理内容的保存。然而,JSON 数组中的每个项目(它是一个对象数组)在每次保存时都会被复制。考虑到它是一个隐藏形式的字符串,当它被保存时,在进程的某个地方它被解析成一个 php 数组并由 Joomla 复制。由于实际保存过程中没有自定义代码,因此 Joomla 可能需要在其他地方编辑 JSON 值,而我的组件触发了它。
这是表单 xml,如果这与它有任何关系,values
隐藏的表单字段是“应该”包含 json 的内容,它在您保存之前一直有效。那是 JSON 数组中的每个索引都重复的时候。
<?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset>
<field name="id" type="text" class="readonly" label="JGLOBAL_FIELD_ID_LABEL"
description ="JGLOBAL_FIELD_ID_DESC" size="10" default="0"
readonly="true" />
<field name="name" type="text" label="COM_HELLO_COMPANY_FIELD_NAME_LABEL"
description="COM_HELLO_COMPANY_FIELD_NAME_DESC" class="input-xlarge" size="30"
required="true" labelclass="control-label" />
<field name="state" type="list" label="JSTATUS"
description="JFIELD_PUBLISHED_DESC" class="span12 small"
filter="intval" size="1" default="1"
>
<option value="1">
JPUBLISHED</option>
<option value="0">
JUNPUBLISHED</option>
<option value="2">
JARCHIVED</option>
<option value="-2">
JTRASHED</option>
</field>
<field
name="buttonspacer"
description="JGLOBAL_ACTION_PERMISSIONS_DESCRIPTION"
type="spacer" />
<field name="created" type="calendar" label="COM_HELLO_FIELD_CREATED_LABEL"
description="COM_CONTENT_FIELD_CREATED_DESC" class="inputbox" size="22"
format="%Y-%m-%d %H:%M:%S" filter="user_utc" labelclass="control-label" />
<field name="created_by" type="user"
label="COM_HELLO_FIELD_CREATED_BY_LABEL" description="COM_HELLO_FIELD_CREATED_BY_DESC" labelclass="control-label" />
<field name="modified" type="calendar" class="readonly"
label="JGLOBAL_FIELD_MODIFIED_LABEL" description="COM_HELLO_FIELD_MODIFIED_DESC"
size="22" readonly="true" format="%Y-%m-%d %H:%M:%S" filter="user_utc" labelclass="control-label" />
<field name="modified_by" type="user"
label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
class="readonly"
readonly="true"
filter="unset"
labelclass="control-label"
/>
<field name="checked_out" type="hidden" filter="unset" />
<field name="values" type="hidden" />
<field name="checked_out_time" type="hidden" filter="unset" />
<field name="publish_up" type="calendar"
label="COM_HELLO_FIELD_PUBLISH_UP_LABEL" description="COM_HELLO_FIELD_PUBLISH_UP_DESC"
class="inputbox" format="%Y-%m-%d %H:%M:%S" size="22"
filter="user_utc" labelclass="control-label" />
<field name="publish_down" type="calendar"
label="COM_HELLO_FIELD_PUBLISH_DOWN_LABEL" description="COM_HELLO_FIELD_PUBLISH_DOWN_DESC"
class="inputbox" format="%Y-%m-%d %H:%M:%S" size="22"
filter="user_utc" labelclass="control-label" />
<field name="assesments" type="text" label="COM_HELLO_COMPANY_FIELD_ASSESEMENTS_LABEL"
description="COM_HELLO_COMPANY_FIELD_ASSESEMENTS_DESC" class="readonly" size="6"
readonly="true" filter="unset" />
</fieldset>
</form>
这是我的页面的edit.php。它使用 JSON 来更新值字段,相同的概念在站点的前端完美运行,只有管理员方面存在问题。
<?php
defined('_JEXEC') or die;
JHtml::_('behavior.formvalidation');
JHtml::_('behavior.keepalive');
//JHtml::_('formbehavior.chosen', 'select');
$app = JFactory::getApplication();
$input = $app->input;
if(!empty($this->item->values)){
$values = json_decode($this->item->values);
}else{
$values = array();
}
function setupSelect($selected = 0,$savedValues){
$selectOptions = '';
foreach($savedValues as $value){
$selectOptions .= '<option value="'.$value->id.'"'.($value->id==$selected?' selected="selected"':'').'>'.$value->name.'</option>';
}
return $selectOptions;
}
?>
<script type="text/javascript">
Joomla.submitbutton = function(task){
if(task == 'company.cancel' || document.formvalidator.isValid(document.id('item-form'))){
Joomla.submitform(task, document.getElementById('item-form'));
}
}
</script>
<form action="<?php echo JRoute::_('index.php?option=com_hello&view=company&layout=edit&id='.(int) $this->item->id); ?>" method="post" name="adminForm" id="item-form" class="form-validate">
<?php echo JLayoutHelper::render('joomla.edit.item_title', $this); ?>
<div class="row-fluid">
<!-- Begin Content -->
<div class="span10 form-horizontal">
<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'general')); ?>
<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'general', JText::_('COM_HELLO_VALUE_DETAILS', true)); ?>
<fieldset class="adminform">
<div class="control-group form-inline">
<?php echo $this->form->getLabel('name'); ?> <?php echo $this->form->getInput('name'); ?>
</div>
<div>Core Values:</div>
<div class="control-group form-inline">
<div id="core-values" class="accordion">
<?php
if(count($values)):
foreach($values as $value):
$id = uniqid();
?>
<div class="core-value row-fluid">
<div class="accordion-group core-value span9" style="padding:0;">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" data-parent="#core-values" href="#collapse<?php echo $id; ?>">
<select class="value-select">
<option value="0"><?php echo JText::_('COM_HELLO_CORE_VALUES_SELECT_NONE'); ?></option>
<?php echo setupSelect($value->id,$this->values); ?>
</select>
<span class="pull-right" style="height:28px;line-height:28px;">
<span class="icon-plus main"></span>
</span>
</a>
<span class="clearfix"></span>
</div>
<div id="collapse<?php echo $id; ?>" class="accordion-body collapse">
<div class="accordion-inner">
<input type="text" class="outcome-input input-block-level" placeholder="Outcome Statement" value="<?php echo $value->outcome; ?>">
<ul class="behaviors">
<?php
$num = 6;
for($i=0;$i<$num;$i++):
?>
<li><input type="text" class="behaviors-input input-block-level" placeholder="Behavior" value="<?php echo empty($value->behaviors[$i])?'':$value->behaviors[$i]; ?>"></li>
<?php endfor; ?>
<?php if(count($value->behaviors)>6):
for($i=6;$i<count($value->behaviors);$i++):
?>
<li><input type="text" class="behaviors-input input-block-level" placeholder="Behavior" value="<?php echo empty($value->behaviors[$i])?'':$value->behaviors[$i]; ?>"></li>
<?php endfor;
endif; ?>
</ul>
<div class="clearfix"></div>
<button type="button" class="btn new-value2 pull-right"><span class="icon-plus no-stop"></span></button>
<div class="clearfix"></div>
</div>
</div>
</div>
<div class="span3" style="line-height:44px;">
<button type="button" class="btn rm-value"><span class="icon-minus"></span></button>
</div>
</div>
<?php
endforeach;
endif;
$id = uniqid();
?>
<div class="core-value row-fluid">
<div class="accordion-group span9" style="padding:0;">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" data-parent="#core-values" href="#collapse<?php echo $id; ?>">
<select class="value-select">
<option value="0"><?php echo JText::_('COM_HELLO_CORE_VALUES_SELECT_NONE'); ?></option>
<?php echo setupSelect(0,$this->values); ?>
</select>
<span class="pull-right" style="height:28px;line-height:28px;">
<span class="icon-plus main"></span>
</span>
</a>
<span class="clearfix"></span>
</div>
<div id="collapse<?php echo $id; ?>" class="accordion-body collapse">
<div class="accordion-inner">
<input type="text" class="outcome-input input-block-level" placeholder="Outcome Statement">
<ul class="behaviors">
<li><input type="text" class="behaviors-input input-block-level" placeholder="Behavior"></li>
<li><input type="text" class="behaviors-input input-block-level" placeholder="Behavior"></li>
<li><input type="text" class="behaviors-input input-block-level" placeholder="Behavior"></li>
<li><input type="text" class="behaviors-input input-block-level" placeholder="Behavior"></li>
<li><input type="text" class="behaviors-input input-block-level" placeholder="Behavior"></li>
<li><input type="text" class="behaviors-input input-block-level" placeholder="Behavior"></li>
</ul>
<div class="clearfix"></div>
<button type="button" class="btn new-value2 pull-right"><span class="icon-plus no-stop"></span></button>
<div class="clearfix"></div>
</div>
</div>
</div>
<div class="span3" style="line-height:44px;">
<button type="button" class="btn rm-value"><span class="icon-minus"></span></button>
<button type="button" class="btn new-value"><span class="icon-plus"></span></button>
</div>
</div>
</div>
</div>
<?php echo $this->form->getInput('values'); ?>
</fieldset>
<?php echo JHtml::_('bootstrap.endTab'); ?>
<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'publishing', JText::_('COM_HELLO_FIELDSET_PUBLISHING', true)); ?>
<div class="row-fluid">
<div class="span6">
<div class="control-group">
<div class="control-label">
<?php echo $this->form->getLabel('id'); ?>
</div>
<div class="controls">
<?php echo $this->form->getInput('id'); ?>
</div>
</div>
<div class="control-group">
<?php echo $this->form->getLabel('created_by'); ?>
<div class="controls">
<?php echo $this->form->getInput('created_by'); ?>
</div>
</div>
<div class="control-group">
<?php echo $this->form->getLabel('created'); ?>
<div class="controls">
<?php echo $this->form->getInput('created'); ?>
</div>
</div>
</div>
<div class="span6">
<div class="control-group">
<?php echo $this->form->getLabel('publish_up'); ?>
<div class="controls">
<?php echo $this->form->getInput('publish_up'); ?>
</div>
</div>
<div class="control-group">
<?php echo $this->form->getLabel('publish_down'); ?>
<div class="controls">
<?php echo $this->form->getInput('publish_down'); ?>
</div>
</div>
<?php if ($this->item->modified_by) : ?>
<div class="control-group">
<?php echo $this->form->getLabel('modified_by'); ?>
<div class="controls">
<?php echo $this->form->getInput('modified_by'); ?>
</div>
</div>
<div class="control-group">
<?php echo $this->form->getLabel('modified'); ?>
<div class="controls">
<?php echo $this->form->getInput('modified'); ?>
</div>
</div>
<?php endif; ?>
<?php if ($this->item->assesments) : ?>
<div class="control-group">
<div class="control-label">
<?php echo $this->form->getLabel('assesments'); ?>
</div>
<div class="controls">
<?php echo $this->form->getInput('assesments'); ?>
</div>
</div>
<?php endif; ?>
</div>
</div>
<?php echo JHtml::_('bootstrap.endTab'); ?>
<?php echo JHtml::_('bootstrap.endTabSet'); ?>
<input type="hidden" name="task" value="" />
<input type="hidden" name="return" value="<?php echo $input->getCmd('return');?>" />
<?php echo JHtml::_('form.token'); ?>
</div>
<!-- End Content -->
<!-- Begin Sidebar -->
<?php echo JLayoutHelper::render('joomla.edit.details', $this); ?>
<!-- End Sidebar -->
</div>
</form>
<script>
var template = jQuery('.core-value:last').clone();
function setupButton(){
jQuery('.new-value').on('click',function(){
var clone = template.clone();
clone.find('.accordion-body').attr('id','collapse'+new Date().getTime());
clone.find('.accordion-toggle').attr('href','#collapse'+new Date().getTime());
jQuery(this).parent().parent().after(clone);
jQuery(this).remove();
setupButton();
setupRm();
});
}
function setupRm(){
jQuery('.rm-value').each(function(){
jQuery(this).off('click').on('click',function(){
var root = jQuery(this).parent().parent();
if(jQuery('.core-value').length==1){
root.replaceWith(template.clone());
setupButton();
setupRm();
}else{
root.remove();
}
});
});
}
function parseBehaviors(root){
var beh = [];
root.find('li').each(function(){
if(jQuery(this).find('.behaviors-input').val()){
beh.push(jQuery(this).find('.behaviors-input').val());
}
});
return beh;
}
jQuery(document).ready(function(){
jQuery('.new-value2').on('click',function(){
var root = jQuery(this).parent();
root.find('.behaviors').append('<li><input type="text" class="behaviors-input input-block-level" placeholder="Behavior"></li>');
});
setupButton();
setupRm();
jQuery('.value-select').on('click',function(event){
event.stopPropagation();
});
jQuery('#core-values').sortable();
jQuery('#core-values').on('shown',function(event){
jQuery(event.target).parent().find('.icon-plus.main').removeClass('icon-plus').addClass('icon-minus');
}).on('hidden',function(event){
jQuery(event.target).parent().find('.icon-minus.main').removeClass('icon-minus').addClass('icon-plus');
});
var setRefresh = setInterval(function(){
var arr = [];
jQuery('.core-value').each(function(){
var obj = {};
if(jQuery(this).find('.value-select option:selected').val()!=0){
obj.id=jQuery(this).find('.value-select option:selected').val();
obj.name=jQuery.trim(jQuery(this).find('.value-select option:selected').text());
obj.outcome=jQuery(this).find('.outcome-input').val();
obj.behaviors=parseBehaviors(jQuery(this).find('.behaviors'));
arr.push(obj);
}
});
var parse = JSON.stringify(arr);
jQuery('#jform_values').val(parse);
},200);
});
</script>
整个事情作为一个非常动态和压缩的自定义表单输入。话虽这么说,我必须将 JSON 作为字符串提供,因为我自己处理它真的没有意义,所以我不费心在模型/表中做任何保存覆盖作为 joomla 的默认函数“应该管用。我的下一步是几乎完全覆盖 JTable/JModelAdmin 以确保我解决了这个问题(尽管我的代码中仍有一部分可能是这个问题的来源,尽管经过几个小时的搜寻,我已经几乎放弃了希望在那)。
我也将此添加到 Joomla 问题跟踪器
在那里,我包含了几个屏幕截图。尽管它链接到相同的东西,但也将其作为问题发布在 cms 存储库上。
无论哪种方式,如果找不到答案,我都会以一种或另一种方式解决这个问题,我感谢任何可以提供帮助的人,因为这是该组件中的一个严重错误,不一定是 Joomla,但如果它确实是 3.1 的错误,我可以想象一下,我将是第一个遇到这种情况的人。