自定义函数在 ColdFusion 10/11 中有效,但在 Lucee 中抛出错误

Custom function works in ColdFusion 10/11 but throws error in Lucee

我有以下函数,继承自一些CF代码。它有效,但仅适用于 ColdFusion 版本 10 和 11。我不关心 2016 年,因为没有升级计划。我试图在 Lucee 下 运行 它,但它不起作用。

<cffunction name="QueryToArray" access="public" returntype="array" output="false" hint="This turns a query into an array of structures.">
  <!--- Define arguments. --->
  <cfargument name="Data" type="query" required="yes" />
  <cfscript>    
    var LOCAL = StructNew(); // Define the local scope.
    LOCAL.Columns = data.getMetaData().getColumnLabels();  // Get the column names as an array.
    LOCAL.QueryArray = ArrayNew(1); // Create an array that will hold the query equivalent.
    for (LOCAL.RowIndex = 1 ; LOCAL.RowIndex LTE ARGUMENTS.Data.RecordCount; 
    LOCAL.RowIndex = (LOCAL.RowIndex + 1)){
        LOCAL.Row = StructNew();
        for (LOCAL.ColumnIndex = 1 ; LOCAL.ColumnIndex LTE ArrayLen(LOCAL.Columns); 
        LOCAL.ColumnIndex = (LOCAL.ColumnIndex + 1)){
            LOCAL.ColumnName = LOCAL.Columns[LOCAL.ColumnIndex];
            LOCAL.Row[LOCAL.ColumnName] = ARGUMENTS.Data[LOCAL.ColumnName][LOCAL.RowIndex];
        }
        ArrayAppend(LOCAL.QueryArray, LOCAL.Row);
    }
    return(LOCAL.QueryArray);
    </cfscript>
</cffunction>

在 Lucee 中,我尝试进行以下更改:

<cffunction name="QueryToArray" access="public" returntype="array" output="false" hint="This turns a query into an array of structures.">
  <!--- Define arguments. --->
  <cfargument name="Data" type="query" required="yes" />
  <cfscript>    
    var LOCAL = StructNew(); // Define the local scope.
    LOCAL.Columns = data.getColumnlist(false); // Get the column names as an array.
    LOCAL.QueryArray = ArrayNew(1); // Create an array that will hold the query equivalent.
    for (LOCAL.RowIndex = 1 ; LOCAL.RowIndex LTE ARGUMENTS.Data.RecordCount; 
    LOCAL.RowIndex = (LOCAL.RowIndex + 1)){
        LOCAL.Row = StructNew();
        for (LOCAL.ColumnIndex = 1 ; LOCAL.ColumnIndex LTE ArrayLen(LOCAL.Columns); 
        LOCAL.ColumnIndex = (LOCAL.ColumnIndex + 1)){
            LOCAL.ColumnName = LOCAL.Columns[LOCAL.ColumnIndex];
            LOCAL.Row[LOCAL.ColumnName] = ARGUMENTS.Data[LOCAL.ColumnName][LOCAL.RowIndex];
        }
        ArrayAppend(LOCAL.QueryArray, LOCAL.Row);
    }
    return(LOCAL.QueryArray);
    </cfscript>
</cffunction> 

但我收到此错误:

Message: Can't cast String [name,value] to a value of type [Array]
Detail: Java type of the object is java.lang.String
Stacktrace: The Error Occurred in

C:\home\website\wwwroot\controller\production\cfc\kernel.cfc: line 12 
     10: LOCAL.RowIndex = (LOCAL.RowIndex + 1)){
     11: LOCAL.Row = StructNew();
     12: for (LOCAL.ColumnIndex = 1 ; LOCAL.ColumnIndex LTE ArrayLen(LOCAL.Columns); 
     13: LOCAL.ColumnIndex = (LOCAL.ColumnIndex + 1)){
     14: LOCAL.ColumnName = LOCAL.Columns[LOCAL.ColumnIndex];

要让您的代码正常工作,您需要做的就是将第 6 行从

LOCAL.Columns = data.getColumnlist(false); // Get the column names as an array.

至此

LOCAL.Columns = data.getColumnNames(); // Get the column names as an array.

不过我发现了一个要点here that works in both ColdFusion and Lucee. I decided to create some sample code and test it at https://trycf.com/。我验证它在 Lucee 4.5 和 5 中有效。它也适用于 ColdFusion 10、11、2016。希望这对您有所帮助!

<!--- Create a new three-column query, specifying the column data types ---> 
<cfset myQuery = QueryNew("Name, Time, Advanced", "VarChar, Time, Bit")> 

<!--- Make two rows in the query ---> 
<cfset QueryAddRow(MyQuery, 2)> 

<!--- Set the values of the cells in the query ---> 
<cfset QuerySetCell(myQuery, "Name", "The Wonderful World of CMFL", 1)> 
<cfset QuerySetCell(myQuery, "Time", "9:15 AM", 1)> 
<cfset QuerySetCell(myQuery, "Advanced", False, 1)> 
<cfset QuerySetCell(myQuery, "Name", "CFCs for Enterprise 
        Applications", 2)> 
<cfset QuerySetCell(myQuery, "Time", "12:15 PM", 2)> 
<cfset QuerySetCell(myQuery, "Advanced", True, 2)> 

<h4>The query</h4> 
<cfdump var="#myQuery#">

<h4>The array of objects</h4> 
<cfset myArray = QueryToArray(myQuery)>
<cfdump var="#myArray#">

<cfscript>
/**
* @hint Returns reasonable array of objects from a cfquery
*/
public function queryToArray(
    required query  query,
             string excludeColumns = ""
){

    if (server.coldfusion.productName == "ColdFusion Server") {
        local.columns = arguments.query.getMetaData().getColumnLabels();
    } else if (server.coldfusion.productName == "Lucee") {
        local.columns = arguments.query.getColumnNames();
    } else {
        local.columns = [];
    }

    local.response = arrayNew(1);

    for (local.rowIndex=1; local.rowIndex<=arguments.query.recordCount; local.rowIndex++) {
        local.response[local.rowIndex] = structNew();

        for (local.columnIndex=1; local.columnIndex<=arrayLen(local.columns); local.columnIndex++) {
            local.columnName = local.columns[local.columnIndex];

            if(local.columnName != "" && (arguments.excludeColumns == "" || !listFindNoCase(arguments.excludeColumns, local.columnName))) {
                local.response[local.rowIndex][local.columnName] = arguments.query[local.columnName][local.rowIndex];
            }
        }
    }

    return local.response;
}
</cfscript>