The php manual states under 'Changelog for break':

5.4.0 Removed the ability to pass in variables (e.g., $num = 2; break $num;) as the numerical argument.

I have a function that copies a table with a tree structure to another table. After copying each record, the function tests a relation to see if that record has more child records in the next "level" of the tree.

If child records are found, this same function is executed for each child record using a foreach() loop. If they also have child records, the process is repeated, etc. etc.

So the number of "branches" and "levels" in the table will determine how many foreach() loops will be executed. Since the user creates the records, I have no control over the number of "branches" and "levels" in the table.

If break cannot receive a variable any more (I cannot run "branch" and "level" counters any more) - how do you break out of ALL loops if an error occurs?

Scaled down example:

public function copyTreeModels($row, $id)
{
    try
    {
        /* copy current record. */
        $status == 'ok';

        /* loop to this same function if $status == 'ok' and hasChildren */
        if($status == 'ok')
        {
            If ($row['hasChildren'] == 'yes') // check relation
            {
                foreach($row['children'] as $child)
                {
                    $this->copyTreeModels($child, $id);
                }
            }
        }
        else
        {   
            //  break;
            throw new CDbException($message);
        }
    }
    catch(CDbException $e)
    {
        $message .= $e->getMessage();
    }
    return($message);
}
有帮助吗?

解决方案

Don't put try in the recursive function. You need a wrapper function around the whole thing that establishes the condition handler:

public function copyTreeModels($row, $id) {
    try {
        $this->copytreeModelsRecurse($row, $id);
    }
    catch(CDbException $e)
    {
        $message .= $e->getMessage();
    }
    return($message);
}

copyTreeModelsRecurse would then be your copyTreeModels function, but without the try/catch blocks.

其他提示

The only thing I can think of is to set a variable which determines whether or not to break all.

An example (untested) is

$break_all = false;
foreach($values as $val) {
    foreach($val as $val1) {
        foreach($val1 as $val2) {
            if($val2 == "xyz") {
                $break_all = true;
            }
            if($break_all) break;
        }
        if($break_all) break;
    }
    if($break_all) break;
}

I'll agree with the fact it's not a pretty solution however.

Edit:

An alternative suggestion if the amount of nested loops to break; from is a variable amount is setting a counter and decrementing the break counter for each break, and only breaking if it is greater than 0:

$break_count = 0;

foreach($values as $val) {
    foreach($val as $val1) {
        foreach($val1 as $val2) {
            if($val2 == "xyz") {
                $break_count = 3;
            }
            if($break_count > 0) { $break_count--; break; }
        }
        if($break_count > 0) { $break_count--; break; }
    }
    if($break_count > 0) { $break_count--; break; }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top