如何在我的 .cfc 文件中获取 cfquery 结果?

How do I get cfquery results in my .cfc file?

我希望在提交表单之前验证输入字段 (PromoCode)。 @Adrian J. Moreno 向我指出了“The Remember The Milk 注册表单”(https://jqueryvalidation.org/files/demo/milk/),@SOS 已引导我完成了这一过程。

除了从 DB 中获取 PromoCode(它目前硬编码在 .cfc 文件中)之外,我的一切都正常(有点)。

该网站是为我的兄弟设计的,他教授多个培训课程,问我是否可以在注册表中添加促销代码选项。他有几门课程,因此可能有多个促销代码(每门可能的课程都不同。)

我有 2 个问题:

  1. 如何从 SQL 获取每门课程的促销代码以与用户输入的内容进行比较?
  2. 如上所述,除了目前,如果用户输入了错误的促销代码,它会告诉他们促销代码无效,我已经完成了所有其他工作......但是用户无法提交表单,除非他们清除该字段或输入正确的代码。我希望用户能够提交表单,无论促销代码是否有效。如果有效,他们会得到折扣……如果无效,他们就不会。

这是精简代码。如有必要,我可以提供完整的代码。

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> 
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="/scripts/jquery.validate.js"></script>

<script>
    $(document).ready(function() {
        var validator = $("#signupform").validate({
            rules: {
                promocode: {
                    remote: "/components/promocodecomponent.cfc?method=validatepromocode"
                }
            },
            messages: {
                promocode: {
                    remote: jQuery.validator.format("<span class='text-danger font-weight-bold font-italic ml-2'>Sorry, {0} is not a valid Promo Code</span>")
                }
            }
        });
    });
</script>

<div class="row justify-content-center">
    <div class="col-10">
        <form id="signupform" autocomplete="off" method="get" action="">
            <input id="promocode" name="promocode" type="text" value="">
            <br>
            <input id="signupsubmit" name="signup" type="submit" value="Signup">
        </form>
    </div>
</div>

CFC 文件:

component {
    remote boolean function validatepromocode(string promocode) returnFormat="json"{
        
        if (arguments.promocode == "john") { //Need to replace "John" with #cfoutput#
            return true;
        }

        return false;
    }

}

cfquery:

<cfquery name="GetAllCourses" datasource="#request.dsn#">
        SELECT ID, EVENT_NAME, NPT_STORY_TYPE, STORY_TYPE, PICTURE, SHOWDATE, SHOWENDDATE, 
            SHOWTIME, SHOWENDTIME, REGISTRATIONTIME, DOORSOPEN, AGE, SEATS, FEE_ADVANCED, 
                FEE_DAYOFSHOW, PROMOCODE, VENUE, ADDRESS, CITY, STATE, ZIP, SHOWDATE, 
                    PHONE, GOOGLEMAPADDRESS, COMMENTS, TEASER, REQUIREMENTS, 
                        STARTDATE, ENDDATE, SHORT_URL
                            FROM DBO.COURSES         
                            <cfif isDefined('url.sname')>
                                WHERE SHORT_URL = <cfqueryparam value="#TRIM(url.sname)#" cfsqltype="cf_sql_varchar">  
                            <cfelseif isDefined('url.id')>
                                WHERE ID = <cfqueryparam value="#url.id#" cfsqltype="cf_sql_integer"> 
                            </cfif>             
</cfquery>

如果每门课程都可以有自己的促销代码,那么您需要将“PromoCode”和“CourseId”值都传递给 CFC。使用 data option to pass additional parameters to the remote url:

Javascript

$(document).ready(function() {
    var validator = $("#signupform").validate({
        rules: {
            promocode: {
                remote: {
                    url: "/components/promoCodeComponent.cfc?method=validatePromoCode",
                    data: { 
                        courseId : $("#courseId").val() 
                    }
                }
            }
        },
        messages: {
            promocode: {
                remote: jQuery.validator.format("Sorry, {0} is not a valid Promo Code")
            }
        },
        errorClass: "text-danger",
        validClass: "text-success"          
    });
});

表格

<form id="signupform" autocomplete="off" method="get" action="">
    <!--- demo only --->
    Course Id: <input id="courseId" name="courseId" type="text" value=""><br>
    Promo Code: <input id="promocode" name="promocode" type="text" value=""><br>
    <input id="signupsubmit" name="signup" type="submit" value="Signup">
</form>

修改您的 CFC 函数以接受附加参数:courseID。在函数内部,使用 QueryExecute() 在数据库中查找 promoCode 和 courseId。如果找到匹配项,return true(即有效)。

注意:将 "Your_DataSource_Name" 替换为您的数据源名称。另请参阅标题为 "Default Datasource".

的部分
component {
    // Note: See Application.cfc docs on setting application level datasource, i.e. "this.datasource"
    remote boolean function validatePromoCode(string courseId, string promoCode) returnFormat="json"{
        
        local.qPromoCode = queryExecute(
            "   SELECT COUNT(*) AS TotalFound 
                FROM   Courses 
                WHERE  Id = :courseId 
                AND    PromoCode = :promoCode
                AND    LEN(PromoCode) > 0                                   
            "
            , { 
                promoCode = { value=arguments.promoCode, cfsqltype="varchar" }
                , courseId = { value=arguments.courseId, cfsqltype="integer", null=!isNumeric(arguments.courseId) }
              }
            , { datasource="Your_DataSource_Name" }
        );
                                        ;
        if (local.qPromoCode.TotalFound gt 0) {
            return true;
        }

        return false;
    }

}

2022 年 2 月 20 日更新

关于问题 #2,我还没有用这个插件尝试过类似的东西。您所描述的听起来更像是一个“警告”,我认为该插件不是为此而设计的。但是,您可能 post 一个 JS 特定问题,以便从那些更熟悉该插件的人那里获得更明确的答案。

如果您只在这一领域使用插件,使用一点 jQuery(而不是插件)可能会在紧要关头完成。挂钩到文本字段的 blur() event. When the field loses focus, call the cfc with $.getJSON()。然后用响应更新 <div>。该方法缺少插件的花哨功能(并且可以改进,可用性方面)但似乎更符合您的意图,即显示警告与硬失败。

Javascript

$(document).ready(function() {
    // attach handler to all text fields with class ".promocode"
    $(".promocode").on( "blur", function(evt) {
    
        // promo code field that triggered event
        var txtPromo = $(this);
        // find nearest "course" id 
        var txtCourse = txtPromo.prevAll('.courseid').first();
        // find nearest "status" element 
        var elemStatus = txtPromo.nextAll('.promocode-status').first();
        
        // clear any previous status
        elemStatus.removeClass("text-success")
                .removeClass("text-danger")
                .html("");
                
        // nothing entered, nothing to do
        if (txtPromo.val().trim() == "") {
            return;
        }
        
        // verify promo code 
        $.getJSON( "/path/PromoCode.cfc"
            , { method : "validatePromoCode"
            , courseId: txtCourse.val()
            , promoCode : txtPromo.val()
        })
        .done(function( response ) {
            if (response.isValidCode) {
                elemStatus
                    .addClass("text-success")
                    .html("Success");
            }
            else {
                elemStatus
                    .addClass("text-danger")
                    .html("Sorry, "+ response.promoCode + " is not a valid Promo Code");
            }
        });
    });
    
});

表格(多个促销代码字段)

<!--- assign a "class" instead of "id" to identify each of the 3 elements in handler --->
<form id="signupform" autocomplete="off" method="get" action="">
   <div>
     Class 1: <input class="courseid" name="courseid" type="text" value="1">
     Promo Code: <input class="promocode" name="promocode" type="text" value="">
     <span class="promocode-status"></span>
   </div>
   <div>
     Class 2: <input class="courseid" name="courseid" type="text" value="2">
     Promo Code: <input class="promocode" name="promocode" type="text" value="">
     <span class="promocode-status"></span>
   </div>

   <input id="signupsubmit" name="signup" type="submit" value="Signup">
</form>

CFC

component {
    remote struct function validatePromoCode(string courseId, string promoCode) returnFormat="json"{
        
        local.qPromoCode = queryExecute(
            "   SELECT COUNT(*) AS TotalFound 
                FROM   Courses 
                WHERE  Id = :courseId 
                AND    PromoCode = :promoCode
                AND    LEN(PromoCode) > 0                                   
            "
            , { 
                promoCode = { value=arguments.promoCode, cfsqltype="varchar" }
                , courseId = { value=arguments.courseId, cfsqltype="integer", null=!isNumeric(arguments.courseId) }
              }
            , { datasource="SQLServer" }
        );
        
        return { 
            "promoCode": arguments.promoCode 
            , "isValidCode" : (qPromoCode.TotalFound gt 0) 
        };
    }

}