Search code examples
arrayscoldfusioncoldfusion-2018

ColdFusion: how to check if array element exists?


I have to loop over the array of street addresses and insert the data into database. User always provide one line of address and some times two. I am trying to loop the array and dynamically set address_1 and address_2(if exists or NULL if not), but it does not work for me.

Image of array dump

Here is what I have:

<cfset address_1 = #jsonData.addresses.customer.street[1]#>
<cfif isDefined(jsonData.addresses.customer.street[2])>
    <cfset address_2 = #jsonData.addresses.customer.street[2]#> 
<cfelse>    
    <cfset address_2 = "">
</cfif>

When I run it, I get this: Parameter 1 of function IsDefined, which is now Suite 300, must be a syntactically valid variable name.


Solution

  • IsDefined can only tell you if a variable named jsonData.addresses.customer.street exists. It can't examine the contents, so it's the wrong function for this scenario.

    Assuming the street array always exists, just check it's size using the member function len(), or ArrayLen(). If the size is >= 2, then you know the 2nd address exists.

    <!--- Option 1: Member function len()  --->
    <cfif jsonData.addresses.customer.street.len() gte 2 > 
       2nd address exists, do something 
    </cfif>
    
    <!--- Option 2: ArrayLen() --->
    <cfif arrayLen(jsonData.addresses.customer.street) gte 2 > 
       2nd address exists, do something 
    </cfif>
    

    Dynamic "address_x" variables

    Depending on what you're ultimately doing, you might consider leaving the address information as an array, because it's easier work with when dealing with a dynamic number of elements. However, if you prefer you could also define separate address_x variables dynamically, using <cfloop array="..">

    <!--- demo data --->
    <cfset jsonData.addresses.customer.street = ["Line1","Line2","Line3"]>
    
    <cfloop array="#jsonData.addresses.customer.street#" item="line" index="pos">
        <!--- Use the current position to name variables xx_1, xx_2, xx_3 --->
        <cfset variables["address_"& pos] = line>
    </cfloop>
    
    <!--- results --->
    <cfdump var="#variables#">
    

    Results:

    Image of generated variables


    About Original Error

    A frequently misunderstood detail about IsDefined is that the function expects the name of a variable, which is usually a plain string in quotes, like "myVariable". Since there are no quotes surrounding the variable name here:

    <cfif isDefined( jsonData.addresses.customer.street[2] )>
    

    ... that variable gets evaluated and its value is what's actually being passed into IsDefined(). So the code ends up checking the wrong variable name:

    <!--- code is really doing this (thinks address[2] is the variable name) --->
    <cfif isDefined("Suite 300")>
    

    The reason that triggers an error is because IsDefined() only accepts valid CF variable names. So it can't be used on variable names containing special characters (spaces, square brackets, etc..) - meaning it won't work with a variable named Suite 300. That limitation is one of the reasons why StructKeyExists() is usually recommended instead.