CakePHP 2.4:通过SecurityComponent获取大型,可扩展的表单?

时间:2015-04-10 05:44:34

标签: php jquery forms cakephp

使用CakePHP(2.4)和SecurityComponent提交大型可扩展表单的最安全方法是什么?

我的应用程序上有一个表单,它使用jQuery创建新的字段来存储新的子记录(以及 sub -subrecords)。这与Cake的SecurityComponent冲突,后者希望FormHelper在服务器端创建提交表单上的所有字段。

过去,当我只在一个协会中保存记录时,我已经能够将用户端的字段限制为高但可行的数字,如100,并明确解锁表单可能的每个可能的字段生成:

while($i < 100){
    $this->Form->unlockField('ChildModel.' . $i . '.value'); $i++;
    // unlock other fields for that possible record
}

但是,使用这种新形式,我必须将数据保存在除两个关系之外的其中一个。用户可能会创建大量子记录或子子记录,因此命名空间ChildModel.[1-100].field, ChildModel.[1-100].GrandchildModel.[1-100].field开始变得庞大。解锁一个名为成千上万的可能字段的命名空间,其中很少会被使用,但所有这些字段都可能需要,这听起来真的很疯狂。

其他CakePHP开发人员找到了哪些解决方案可以解决这个问题?我认为这是其他人遇到的问题,在这种情况下,禁用整个操作的安全性根本不是一种选择。

1 个答案:

答案 0 :(得分:2)

就我个人而言,这样做:

  1. 使用AJAX发送动态字段的信息以创建回服务器

  2. 使用新输入生成表单

  3. 从生成的表单HTML中提取标记值,并将其与生成的新字段的HTML一起传回

  4. 将生成的HTML和令牌值注入现有表单

  5. ???

  6. 利润!

  7. 这是旧项目中一个非常基本的剥离示例,它用于为单个关联添加其他输入。

    服务器端:

    App::uses('Xml', 'Utility');
    
    $formHtml = $this->Form->create('Model');
    
    $this->Form->input('some_field');
    $this->Form->input('also_a_field');
    
    $dynamicInputs = array();
    for($i = 0; $i < $numberOfEntries; $i ++)
    {
        $dynamicInputs[] = $this->Form->input('AssociatedModel.' . $i . '.field');
    }
    
    $formHtml .= $this->Form->end();
    
    $xml = Xml::build($formHtml);
    $formData = Xml::toArray($xml);
    
    $data = array
    (
        'token' => array
        (
            'key' => array
            (
                'id' => $formData['form']['div'][0]['input'][1]['@id'],
                'value' => $formData['form']['div'][0]['input'][1]['@value']
            ),
            'fields' => array
            (
                'id' => $formData['form']['div'][2]['input'][0]['@id'],
                'value' => $formData['form']['div'][2]['input'][0]['@value']
            ),
            'unlocked' => array
            (
                'id' => $formData['form']['div'][2]['input'][1]['@id'],
                'value' => $formData['form']['div'][2]['input'][1]['@value']
            )
        ),
        'dynamicInputs' => $dynamicInputs
    );
    
    echo json_encode($data);
    

    前端(使用jQuery):

    var form = $('#my-form');
    
    function addEntry()
    {
        var inputs = form.find('.associated-model .input');
        var numberOfEntries = inputs.length + 1;
    
        $.ajax({
            url: '/controller/action/whatever',
            type: 'POST',
            data: 'numberOfEntries=' + numberOfEntries + '&' + form.serialize(),
            dataType: 'json',
            success: function(data)
            {
                updateForm(data);
            }
        });
    }
    
    function updateForm(data)
    {
        var tokenKey = form.find('input[name=\'data[_Token][key]\']');
        tokenKey.attr('id', data.token.key.id);
        tokenKey.attr('value', data.token.key.value);
    
        var tokenFields = form.find('input[name=\'data[_Token][fields]\']');
        tokenFields.attr('id', data.token.fields.id);
        tokenFields.attr('value', data.token.fields.value);
    
        var tokenUnlocked = form.find('input[name=\'data[_Token][unlocked]\']');
        tokenUnlocked.attr('id', data.token.unlocked.id);
        tokenUnlocked.attr('value', data.token.unlocked.value);
    
        form.find('.associated-model').empty().append(data.dynamicInputs.join('\n'));
    }