Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 8 of 8
  1. #1
    Regular Coder
    Join Date
    Apr 2006
    Posts
    311
    Thanks
    17
    Thanked 0 Times in 0 Posts

    key() Behavioral Differences PHP5.1.6 to PHP5.2.5

    Hey all!
    This little script works fine (iterating through MD array) in PHP5.2.5 on development server, but when I publish to production server (PHP5.1.6) it doesn't work (just loops through first sub "AL" -- over and over...). The problem appears to hinge on the line(s) "$new_state= key($cities);" but I can't figure out why, and am stumped as to an alternative.
    HELP!
    P.S. It's a complete example. Cut, Paste and give it a whirl !
    PHP Code:
    <?php 
    $state
    ="AL";//start value 
    $city="auburn";//start value 
    if($_GET['state']){ 
        
    $state=$_GET['state']; 
        
    $city=$_GET['city']; 

    $cities= Array( 
      
    'AL' => Array ( 
        
    '1' => Array ( 'city' => 'auburn''url' => 'http://auburn.mydomain.com/'), 
        
    '2' => Array ( 'city' => 'birmingham''url' => 'http://bham.mydomain.com/'), 
        
    '3' => Array ( 'city' => 'columbus, GA''url' => 'http://columbusga.mydomain.com/')//border town 
       
    ), 
      
    'AK' => Array ( 'city' => 'anchorage''url' => 'http://anchorage.mydomain.com/'), 
      
    'AZ' => Array ( 
        
    '1' => Array ( 'city' => 'flagstaff / sedona''url' => 'http://flagstaff.mydomain.com/'), 
        
    '2' => Array ( 'city' => 'mohave cnty''url' => 'http://mohave.mydomain.com/'
       ) 
    ); 

    foreach(
    $cities as $key=>$value){ 
        if(
    $key != $state){continue;}// iterate until it does... 
        
    $countcount($value); 
        if(
    $value['city']==''){ //e.g. more than one city this state... 
        
    foreach($value as $c_num=>$c_val){ 
            if(
    $c_val['city']!=$city){continue;} 
                else{
    //OPTION A 
                    
    if($c_num$count){//e.g more cities this state 
                        
    $condition"A"
                        
    $i=$c_num+1
                        
    $new_city $value[$i]['city']; 
                        
    $new_url $value[$i]['url']; 
                        break; 
                    } 
                    else{
    //NEW STATE -- OPTION B 
                        
    $condition"B"
                        
    $new_state key($cities);//WORKS on PHP5.2.5 development server, but not in PHP5.1.6 production 
                        
    $new_city $cities[$new_state]['1']['city']; 
                        
    $new_url=$cities[$new_state]['1']['url']; 
                        if(
    $new_city==''){//e.g only ONE city this new_state 
                        
    $condition"B1"
                            
    $new_city=$cities[$new_state]['city']; 
                            
    $new_url=$cities[$new_state]['url']; 
                        } 
                        break; 
                    } 
                } 
            } 
        }
    //end if more than one city this state... 
        
    else{//only ONE city this state... 
            
    $condition"C"
            
    $new_state key($cities);//WORKS on PHP5.2.5 development server, but not in PHP5.1.6 production 
            
    $new_city $cities[$new_state]['1']['city']; 
            
    $new_url=$cities[$new_state]['1']['url']; 
            if(
    $new_city==''){ 
                
    $condition"C1"
                
    $new_city=$cities[$new_state]['city']; 
                
    $new_url=$cities[$new_state]['url']; 
            } 
            break; 
        } 
    }
    //end foreach $cities 
    if($new_state=='')$new_state=$state
    echo 
    "CONDITION =".$condition."<br>"
    echo 
    "Previous State=".$state."<br>"
    echo 
    "Previous City=".$city."<br>"
    echo 
    "New State=".$new_state."<br>"
    echo 
    "New City=".$new_city."<br>"
    echo 
    "<a href='test.php?state=$new_state&city=$new_city'>Next Iteration</a>"
    ?>

  • #2
    New Coder
    Join Date
    Jan 2009
    Posts
    91
    Thanks
    17
    Thanked 1 Time in 1 Post
    Yep works on 5.2.9 perfectly. Sorry cant test older versions.

  • #3
    GŁtkodierer
    Join Date
    Apr 2009
    Posts
    2,127
    Thanks
    1
    Thanked 426 Times in 424 Posts
    From the PHP reference:
    Note: Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself. foreach has some side effects on the array pointer. Don't rely on the array pointer during or after the foreach without resetting it.
    So, making it referenced should solve your problem:
    PHP Code:
    foreach($cities as $key => &$value
    Last edited by venegal; 05-07-2009 at 02:03 PM.

  • #4
    Regular Coder
    Join Date
    Apr 2006
    Posts
    311
    Thanks
    17
    Thanked 0 Times in 0 Posts
    Thanks venegal,
    That did sound promising! Sadly no joy however.
    Pointer still doesn't advance on 5.1.6 and on 5.2.5 the script breaks down completely at condition C

    As opposed to resetting the pointer I HAD been looking (only half heartedly) for a means of setting (forcing ) the array pointer to a desired location, but no luck there either.

    It's funny,
    PHP Code:
    print_r(array_keys($cities)); 
    returns Array ( [0] => AL [1] => AK [2] => AZ ), by which I would think I could then run a numeric iterator along side like
    PHP Code:
     $i='0'$i++ if($condition$new_state $cities[$i
    but alas a call to $cities[$i] only returns Array
    I'm thinking it calls for a complete re-think but I've got that whole white-blind can't see the trees for the forrest thing going just now. Suggestions welcome!

  • #5
    GŁtkodierer
    Join Date
    Apr 2009
    Posts
    2,127
    Thanks
    1
    Thanked 426 Times in 424 Posts
    An easy fix would be to completely kick the foreach in favor of the (slower) manual each() loop.
    So, try changing
    PHP Code:
    foreach($cities as $key=>$value
    to
    PHP Code:
    reset($cities);
    while (list(
    $key$value) = each($cities)) 
    This will definitely advance the array pointer.

    Your last example can't work, because $i is no key of $cities, but you might try
    PHP Code:
    $new_state $cities[array_keys($cities)[$i]] 

  • #6
    Regular Coder
    Join Date
    Apr 2006
    Posts
    311
    Thanks
    17
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by venegal View Post
    PHP Code:
    reset($cities);
    while (list(
    $key$value) = each($cities)) 
    Well....sort of? Let me offer a little context.
    The start values are returned from a DB SELECT query, which is immediately followed by an UPDATE query
    -- posting the new_values to the record to become the start values next time the script is called.
    Some code is then executed on basis of the original start values, and we exit the script.

    In this context, the call to reset($cities); would have to come only upon condition that the $city start value
    exists at the end of the $cities array (last city value under last state sub-array).
    Your suggestion works on the development server right up until we reach the end of the array.
    Then it doesn't. I don't see a good way to determine weather or not the start value = end($cities).
    Hmmmmm.......

  • #7
    GŁtkodierer
    Join Date
    Apr 2009
    Posts
    2,127
    Thanks
    1
    Thanked 426 Times in 424 Posts
    Acutally, reset($cities) is ok the way it is and needs to be called every time. All it does is set the array pointer to the start of the array, which is expected by your code. foreach does the same thing, only with each() you have to do it manually.

    But I guess I understand now, what the problem is: You want the cities to loop through, so you get the first city of the first state as the next city, if the current city is the last one of the last state, right? And somehow with your approach it magically worked without having to care about it, because for some reason foreach in its unpredictability reset the array pointer to 0 once it reached the end, while each() expectedly does not.

    If that's the case, just use each() and make sure to handle the end of the array properly. For example, change
    PHP Code:
    $new_state key($cities); 
    to
    PHP Code:
    $new_state key($cities) ? key($cities) : "AL"

  • #8
    Regular Coder
    Join Date
    Apr 2006
    Posts
    311
    Thanks
    17
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by venegal View Post
    If that's the case, just use each() and make sure to handle the end of the array properly. For example, change
    PHP Code:
    $new_state key($cities); 
    to
    PHP Code:
    $new_state key($cities) ? key($cities) : "AL"
    correction: I DIDN'T see a good way to determine weather or not the start value = end($cities). NOW I DO! Cool!
    Thanks venegal,
    I'll give it a go and post my results here. Have to move on to other things for a bit now, but that sure beats my alternative solution of including a separate states array wherein $new_state= $states[$i]; (which now works, but is just plain ugly)


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •