Вопрос

I have been having the hardest time trying to resolve the weirdest error when any kind of condition is used within any kind of loop.

The error I keep getting is: "Complex object types cannot be converted to simple values." on the line that contains <cfloop condition="true">. What's even funnier is that a <cfbreak> doesn't break out of the loop. I have used the debugger within Eclipse to confirm that this code is actually executed.

The odd thing is sometimes the code loops forever even though I know the <cfbreak> gets executed and sometimes it errors out on the first iteration.

I've confirmed that this issue occurs on two other computers as well.

Before everyone freaks out on my use of the always true condition, I used to have a valid condition: <cfloop condition="not done"> where done was a boolean. This caused the same error.

I'm working on older code written by someone else, so rewriting isn't an option at this time.

I have just patched ColdFusion 8.0.1 to the latest updater 4 to see if that would resolve the issue and it hasn't.

This is what the code essentially looks like:

<cfloop condition="true">
    <cfif condition is true>
        <cfbreak>
    </cfif>
</cfloop>

Here is the code that does get executed:

<cfset done = false />
<cfloop condition="true">
    <cfscript>
        try
        {
            lineitem.quantity = quantityRemaining;

            quantityRemaining = 0;

            arrayAppend( currentTub, lineitem );

            currentCartItemCount = currentCartItemCount + lineitem.quantity;
            currentTubItemCount = currentTubItemCount + lineitem.quantity;

        }
        catch(Any e){}


        availableSpaceInCart = this.itemsPerCart - currentCartItemCount;
        availableSpaceInTub = this.itemsPerTub - currentTubItemCount;
    </cfscript>

    <cfif quantityRemaining LTE 0>
        <cfset done = true />
        <cfbreak />
    </cfif>
</cfloop>

UPDATE:

Well we figured out what the issue was. There was two <CFOUTPUT> tags wrapped around this loop, the outer <CFOUTPUT query='query_name' groupby='column_name'> tag was using a QueryNew() generated query which for some reason ColdFusion didn't like. So we resolved that issue and it resolved our weird issue.

Это было полезно?

Решение

You are passing ambiguous values to a conditional loop.

When you write:

<cfloop condition="x">

You are telling ColdFusion: continue to loop so long as 'x' evaluates to true. This could be a statement like (myvar gte 10), which would evaluate to true if myvar is greater than or equal to 10. If some mechanism inside the loop decrements myvar, eventually, a pass through the loop will cause it to stop, because myvar will no longer be greater than or equal to 10 (it has dropped below 10).

Now, let's look at your condition:

<cfloop condition="true">

Is CF considering it as:

<cfif 'true'>

Or

<cfif TRUE>

One is definitely wrong, and will throw an error, if you write into a ColdFusion statement. You will probably find that you cannot evaluate a "string" into a boolean TRUE or FALSE evaluation. I'm almost certain the parsing of a string value is confusing ColdFusion with the actual boolean TRUE or FALSE value. It is perhaps this lexical conversion of 'true' to TRUE that is causing your object-related errors. What you want, more than likely is:

since the value of done is set to FALSE to start, which, when coupled with a logical NOT, evaluates to true.

Then, later down your statement:

   <cfif quantityRemaining LTE 0>
        <cfset done = true />
   </cfif>

There is no need for a <cfbreak> statement, which forcibly breaks you out of a loop. If you are conditionally looping, the evaluation of that variable will affect the iteration of the loop (read: it will stop it).

Furthermore, you may very well want to change your condition to:

<cfloop condition="quantity LTE 0">

and will not require the done variable at all.

Другие советы

It seems from your code that you want to break out of the loop if the value of quantityRemaining reaches 0 or lower. So why not use that as the condition in the cfloop, rather than using 'true'. Then you can remove the cfbreak block since that's essentially what the cfloop condition is doing.

<cfset quantityRemaining = 5>
<cfloop condition="quantityRemaining GT 0">
    <!--- your code here --->
    <cfoutput>#quantityRemaining#<br></cfoutput>

    <!--- don't forget to change the value, otherwise you'll loop forever --->
    <cfset quantityRemaining = quantityRemaining - 1>
</cfloop>

The error "Complex object types cannot be converted to simple values." means exactly that.

Complex objects - objects,arrays,structs,queries,etc - cannot be converted to simple values - strings,numbers,dates,booleans,etc - because there's no globally defined way of doing that.

Based on the code you've posted, at least one of these variables does not hold a simple value:

  • currentCartItemCount
  • currentTubItemCount
  • lineitem.quantity
  • this.itemsPerCart
  • this.itemsPerTub
  • quantityRemaining

To find out which one, put this before the loop:

<cfdump var=#isSimpleValue(currentCartItemCount)# />
<cfdump var=#isSimpleValue(currentTubItemCount)# />
<cfdump var=#isSimpleValue(lineitem.quantity)# />
<cfdump var=#isSimpleValue(this.itemsPerCart)# />
<cfdump var=#isSimpleValue(this.itemsPerTub)# />
<cfdump var=#isSimpleValue(quantityRemaining)# />
<cfabort/>

If any output false (or no) then unwrap the isSimpleValue function to find out what it contains and trace the code backwards to find out why.

If you get the true (or yes) six times, then something else is going on, and you probably need to share more code.

<cfloop condition="true">

is the same as

<cfloop condition=true>

just as <cfif 'true'> is the same as <cfif true>

What you are basically setting up there is an infinite loop, as your condition will always be true. If your code never breaks out of this you're going to be in serious trouble.

What you probably want to do is the following, and remove the <cfbreak> from your loop.

<cfloop condition="quantityRemaining GT 0">
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top