在Sugar CRM中使用Ajax防止重复值

7
我使用模块生成器创建了一个模块,现在有一个名为“书名”的字段。如果我两次输入相同的书名,它会接受。我不想使用插件来检查重复值,因为我想通过代码进行定制学习。
所以,我可以调用Ajax并检查数据库中是否存在相同的书名,但我不知道Sugar CRM中控制器如何工作,也不知道如何在Sugar CRM中调用Ajax。
请问有人可以给予指导吗?非常感谢您的帮助。
1个回答

26

如果您真的想使用ajax来完成这个任务,那么我建议使用entryPoint的方式。这个自定义过程需要几个简单的步骤。首先,您需要编写一些Javascript代码来执行实际的ajax调用。该ajax调用将会发布到您编写的entryPoint。entryPoint将会为您运行查询并在编辑视图中向您返回响应。因此,让我们首先编写entryPoint。

首先,打开custom/include/MVC/Controller/entry_point_registry.php文件。如果文件夹结构和文件不存在,请创建它们。

将以下代码添加到entry_point_registry.php文件中:

$entry_point_registry['test'] = array('file' => 'custom/test.php', 'auth' => true);

以下是关于那行代码的一些简短解释:

  • test 的索引值可以更改为任何您喜欢的值,也许在您的情况下 'unique_book_value' 更有意义。您将在稍后看到如何使用此值。
  • 数组中的 file 值指向您要放置实际代码的位置。您还应该给它一个更有意义的名称。它不需要与上面提到的数组键匹配。
  • 'auth' => true 部分确定浏览器是否需要具有经过身份验证的 SugarCRM 活动登录会话。在这种情况下(几乎所有情况下),建议将其保留为true。

现在让我们来看看将要放置在 custom/test.php 中的代码(或者在您的情况下是 unique_book_name.php):

/* disclaimer: we are not gonna get all crazy with using PDO and parameterized queries at this point,
               but be aware that there is potential for sql injection here. The auth => true will help
               mitigate that somewhat, but you're never supposed to trust any input, blah blah blah. */

global $db; // load the global sugarcrm database object for your query

$book_name = urldecode($_REQUEST['book_name']); // we are gonna start with $_REQUEST to make this easier to test, but consider changing to $_POST when confirmed working as expected
$book_id   = urldecode($_REQUEST['book_id']);   // need to make sure this still works as expected when editing an existing record

// the $db->quote is an alias for mysql_real_escape_string() It still does not protect you completely from sql injection, but is better than not using it...
$sql = "SELECT id FROM book_module_table_name WHERE deleted = 0 AND name = '".$db->quote($book_name)."' AND id <> '".$db->quote($book_id)."'";

$res = $db->query($sql);

if ($db->getRowCount($res) > 0) {
    echo 'exists';
}
else {
    echo 'unique';
}
关于使用直接数据库查询的注意事项:可以使用api方法来完成此操作(提示:$bean->retrieve_by_string_fields() - 如果您想走这条路,请查看本文:http://developer.sugarcrm.com/2012/03/23/howto-using-the-bean-instead-of-sql-all-the-time/)。但是,我发现api非常缓慢,而且ajax应该尽可能快。如果客户要求提供此功能,我会有99%的机会使用直接db查询。如果那天我感觉很高级,可能会使用PDO和参数化查询,但由您决定。
使用上面的代码,您应该能够导航到https://crm.yourdomain.com/index.php?entryPoint=test并运行我们刚刚编写的代码。
然而,此时你只会得到一个白屏。如果您修改url以包括entryPoint部分,并且它加载您的主页或不进入白屏界面,则有三个可能的原因:
  1. 您为$entry_point_registry ['test']放置了其他内容。如果是这样,请将url更改为读取index.php?entryPoint = whatever_you_put_as_the_array_key
  2. 您在域名上有sugar文件夹或其他内容,因此它不在crm.yourdomain.com上,而是位于类似于yourdomain.com / sugarcrm /这样的丑陋位置。如果是这种情况,请确保修改url以保留实际域名部分。好吧,我会为您拼出来...https://yourdomain.com/sugarcrm/index.php?entryPoint=test
  3. 这更加罕见,但由于某种原因,我无法弄清楚apache有时需要重新加载才能添加新的入口点。如果您具有shell访问权限,则快速的/ etc / init.d / apache2 reload应该解决问题。如果您没有shell访问权限,则可能需要向托管提供商提出工单(或获取自己控制的vps!,拜托了人啊!)

还是不起作用?你注意到https中的“s”了吗?尝试使用http并购买一个$9的ssl证书,拜托了,伙计!

好了,接下来让我们稍微测试一下entryPoint。向书籍模块添加记录。让我们添加《艺术战争》这本书(不是《战争艺术》,虽然您也应该读一读那本书)。

现在在url中添加这个:index.php?entryPoint=test&book_name=Art%20of%20War

哦天啊,这个url编码太丑陋了!别担心。

希望你能看到一个丑陋的白屏,上面会显示文本“存在”。如果可以,请确保它也可以反向操作。在URL中的书名后面添加2,希望它现在会显示“唯一”。

快速提示:如果你使用Sugar,你可能也在使用mysql,在搜索字符串时不区分大小写。如果你真的需要大小写敏感性,请查看这篇SO文章:如何使MySQL中的SQL区分大小写字符串比较?

好了,现在我们的entryPoint正在工作,我们可以继续进行让所有东西都变得ajaxical的有趣部分。有几种方法可以实现这一点,但与其走基本路线,我要向你展示我发现的最可靠的路线。

你可能需要创建以下文件:custom/modules/CUSTOM_BOOK_MODULE/views/view.edit.php(我希望现在我无需指出更改该路径以使用你的模块名称...)

假设这个文件不存在,我们从头开始,它将需要看起来像这样:

if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');

class CUSTOM_BOOK_MODULEViewEdit extends ViewEdit
{
    public function display()
    {
        // make sure it works in the subpanel too
        $this->useForSubpanel = true;

        // make the name value available in the tpl file
        $this->ss->assign('name_value', $this->bean->name);

        // load the parsed contents of the tpl into this var
        $name_input_code = $this->ss->fetch('custom/modules/CUSTOM_BOOK_MODULE/tpls/unique_book_checker.tpl.js');

        // pass the parsed contents down into the editviewdefs
        $this->ss->assign('custom_name_code', $name_input_code);

        // definitely need to call the parent method
        parent::display();
    }
}

情况看起来不错。现在我们需要编写代码到这个文件中:custom/modules/CUSTOM_BOOK_MODULE/tpls/unique_book_checker.tpl.js

首先,有几个假设:

  1. 我们期望这是Sugar 6.5+版本,并且jquery已经可用。如果您使用的是早期版本,则需要手动包含jquery。

  2. 我们将在名称字段上放置事件监听器。如果您要检查的书名值实际上是不同的字段名称,则只需在下面的javascript中进行调整。

以下是custom/modules/CUSTOM_BOOK_MODULE/unique_book_checker.tpl.js的代码:

<input type="text" name="name" id="name" maxlength="255" value="{$name_value}" />
<span id="book_unique_result"></span>

{literal}
<script type="text/javascript">

$(document).ready(function() {

    $('#name').blur(function(){

        $('#book_unique_result').html('<strong> checking name...</strong>');

        $.post('index.php?entryPoint=test', {book_name: $('#name').val(), book_id: $('[name="record"]').val()}, function(data){

            if (data == 'exists') {
                removeFromValidate('EditView', 'name');
                addToValidate('EditView', 'name', 'float', true, 'Book Name Must be Unique.');

                $('#book_unique_result').html('<strong style="color:red;"> &#x2717;</strong>');
            }
            else if (data == 'unique') {
                removeFromValidate('EditView', 'name');
                addToValidate('EditView', 'name', '', true, 'Name Required');

                $('#book_unique_result').html('<strong style="color:green;"> &#x2713;</strong>');
            }
            else {
                // uh oh! maybe you have php display errors on?
            }

        });
    });
});
</script>
{/literal}
注意:当代码检测到名称已经存在时,我们会使用Sugar内置的验证功能来防止记录保存。基本上,我们是在说如果名称已经存在,那么名称的值必须是浮点数。我认为这种情况很不可能发生并且能够奏效。但是,如果你有一本名为3.14或类似的书籍,并尝试创建重复项,此代码将无法阻止保存,它只会告诉你找到了一个重复项。

好了!最后两个步骤非常简单。 首先,打开文件:custom/modules/CUSTOM_BOOK_MODULE/metadata/editviewdefs.php。 接下来,找到提供名称字段元数据的部分,并添加此customCode属性,以使其看起来像这样:

array (
'name' => 'name',
'customCode' => '{$custom_name_code}',
),

最后,您需要进行快速修复和重建元数据以使更改生效。前往管理>维护>快速修复和重建。

完成了!您现在可以开始使用了!

检查唯一的书名 哎呀,这是一个重复项 好的,可以保存


我已经实现了,运行得很好。谢谢丹尼为你的时间和指导。 - Abhi Adr
1
没问题。很高兴你能把一切都拼凑起来! - dmulvi
@dmulvi 您好,我想请问如何使用名字、姓氏和手机号这三个条件来实现这个功能? - Clinton Canarias

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接