{"id":3217,"date":"2010-03-13T21:18:29","date_gmt":"2010-03-13T19:18:29","guid":{"rendered":"http:\/\/blog.ginchen.de\/?p=3217"},"modified":"2010-03-14T14:40:14","modified_gmt":"2010-03-14T12:40:14","slug":"php-rekursion-schleife-globales-array-aerger","status":"publish","type":"post","link":"http:\/\/blog.ginchen.de\/en\/2010\/03\/13\/php-rekursion-schleife-globales-array-aerger\/","title":{"rendered":"PHP + Recursion + loop + global array = trouble"},"content":{"rendered":"<figure id=\"attachment_3252\" aria-describedby=\"caption-attachment-3252\" style=\"width: 200px\" class=\"wp-caption alignright\"><a href=\"http:\/\/blog.ginchen.de\/wp-content\/uploads\/2010\/03\/recursion.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/blog.ginchen.de\/wp-content\/uploads\/2010\/03\/recursion-200x160.jpg\" alt=\"Recursion\" title=\"Recursion\" width=\"200\" height=\"160\" class=\"size-thumbnail wp-image-3252\" \/><\/a><figcaption id=\"caption-attachment-3252\" class=\"wp-caption-text\">Recursion<\/figcaption><\/figure>\r\n\r\n<p>Once again, I came across an issue that I racked my brain about for hours, if not days: I had written a recursive function in PHP that should run through a globally declared array with a <code>foreach<\/code> loop and then restart itself if necessary. Everything ran perfectly well &#8211; but only on my local server. On my live server, however, every time the function called itself again, the &#8220;parent&#8221; <code>foreach<\/code> loop was simply canceled. Meaning that, after my function had reached a deeper level of the array, the higher level was not being continued. Instead, it just quit there.<\/p>\r\n\r\n\r\n<!--more-->\r\n\r\n\r\n\r\n\r\n<p>Even the big wide internet provided an unusually small amount of information about this annoyance. But even though I still don&#8217;t have an exact explanation for the phenomenon (the PHP versions of my local and the live server are not that far apart, so I can&#8217;t blame it on the different versions), I was able to find two solutions:<\/p>\r\n\r\n<ol>\r\n<li>Simply make a copy of the array and use that as the argument for the <code>foreach<\/code> loop (not the cleanest solution).<\/li>\r\n<li>Rewrite the function so that you pass the global variable to it as a parameter, rather than declaring it globally within the function.<\/li>\r\n<\/ol>\r\n\r\n<p>To make things a little clearer, I have devised a fascinating example with the following array:<\/p>\r\n\r\n<pre lang=\"php\">\r\n$crew = array(\r\n\t0 => array('Picard',\t0),\r\n\t1 => array('Riker',\t0),\r\n\t2 => array('Data',\t1),\r\n\t3 => array('Yar',\t1),\r\n\t4 => array('LaForge',\t2),\r\n\t5 => array('Worf',\t3),\r\n\t6 => array('Crusher',\t0),\r\n\t7 => array('Troi',\t0)\r\n);\r\n<\/pre>\r\n\r\n<p><code>$crew[x][0]<\/code> always contains the name of a crew member of the Enterprise, and <code>$crew[x][1]<\/code> the ID of the respective superior. I now want to assign the crew members to their superiors with the help of a recursive function. The function looks like this:<\/p>\r\n\r\n<pre lang=\"php\" line=\"1\">\r\nfunction enterprise($crewmember = 0) {\r\n\tglobal $crew;\r\n\t\r\n\tforeach($crew as $key => $member) {\r\n\t\tif($member[1] == $crewmember && $key != 0) {\r\n\t\t\techo $crew[$crewmember][0].\" is the boss of \".$member[0].\"<br \/>\";\r\n\t\t\tenterprise($key);\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\r\n\r\n<p>The expected result would be the following:<\/p>\r\n\r\n<pre>\r\nPicard is the boss of Riker\r\nRiker is the boss of Data\r\nData is the boss of LaForge\r\nRiker is the boss of Yar\r\nYar is the boss of Worf\r\nPicard is the boss of Crusher\r\nPicard is the boss of Troi\r\n<\/pre>\r\n\r\n<p>As I said, this worked fine locally, but my online server always spit out the following:<\/p>\r\n\r\n<pre>\r\nPicard is the boss of Riker\r\nRiker is the boss of Data\r\nData is the boss of LaForge\r\n<\/pre>\r\n\r\n<h3>Solution 1<\/h3>\r\n\r\n<p>The first (worse) version looks like this (only lines 3 and 4 have changed):<\/p>\r\n\r\n<pre lang=\"php\" line=\"1\">\r\nfunction enterprise($crewmember = 0) {\r\n\tglobal $crew;\r\n\t$crew_copy = $crew;\r\n\tforeach($crew_copy as $key => $member) {\r\n\t\tif($member[1] == $crewmember && $key != 0) {\r\n\t\t\techo $crew[$crewmember][0].\" is the boss of \".$member[0].\"<br \/>\";\r\n\t\t\tenterprise($key);\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\r\n\r\n<p>This way, the loop runs through completely, and the array is being read as desired again, but suppose you have stored a huge category tree in your array &#8211; then it would, performance-wise, not be a good idea to copy it unnecessarily. I therefore recommend<\/p>\r\n\r\n<h3>Solution 2<\/h3>\r\n\r\n<p>The global array is being passed to the function when calling. Thus, the loop also runs through dutifully, and you don&#8217;t have to copy the array.<\/p>\r\n\r\n<pre lang=\"php\" line=\"1\">\r\nfunction enterprise($crew, $crewmember = 0) {\r\n\tforeach($crew as $key => $member) {\r\n\t\tif($member[1] == $crewmember && $key != 0) {\r\n\t\t\techo $crew[$crewmember][0].\" is the boss of \".$member[0].\"<br \/>\";\r\n\t\t\tenterprise($crew, $key);\r\n\t\t}\r\n\t}\r\n}\r\nenterprise($crew);\r\n<\/pre>\r\n\r\n<h3>Don&#8217;t like the parameter?<\/h3>\r\n\r\n<p>Now, in my case, there was another speciality: The <code>enterprise()<\/code> function should not have any parameters. (It was meant to serve as a kind of template tag later.) To achieve this, I renamed the actual function and then built a &#8220;dummy function&#8221; called <code>enterprise()<\/code>:<\/p>\r\n\r\n<pre lang=\"php\" line=\"1\">\r\nfunction enterprise_crew($crew, $crewmember = 0) {\t\r\n\tforeach($crew as $key => $member) {\r\n\t\tif($member[1] == $crewmember && $key != 0) {\r\n\t\t\techo $crew[$crewmember][0].\" is the boss of \".$member[0].\"<br \/>\";\r\n\t\t\tenterprise_crew($crew, $key);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunction enterprise() {\r\n\tglobal $crew;\r\n\tenterprise_crew($crew);\r\n}\r\n<\/pre>\r\n\r\n<p>Now you can call <code>enterprise()<\/code> without a parameter again.<\/p>\r\n\r\n<p>I have no idea if this post will help anyone at all &#8211; there are indeed five conditions to be met in order for this problem to occur at all (PHP, recursion, loop, global array, poorly configured server).<br \/>\r\nWell, otherwise this post will only serve me as a reminder. ;)<\/p>\r\n\r\n<p>But I&#8217;d still like to know which server setting is responsible so it works on one server, and on the other it doesn&#8217;t. Perhaps someone knows?<\/p>","protected":false},"excerpt":{"rendered":"Once again, I came across an issue that I racked my brain about for hours, if not days: I had written a recursive function in PHP that should run through a globally declared array with a foreach loop and then restart itself if necessary. Everything ran perfectly well &#8211; but only on my local server. [&hellip;]","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[76],"tags":[442,444,445,443,122,441],"_links":{"self":[{"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/posts\/3217"}],"collection":[{"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/comments?post=3217"}],"version-history":[{"count":39,"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/posts\/3217\/revisions"}],"predecessor-version":[{"id":3260,"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/posts\/3217\/revisions\/3260"}],"wp:attachment":[{"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/media?parent=3217"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/categories?post=3217"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/tags?post=3217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}