Domhnall Posted January 9, 2009 Share Posted January 9, 2009 Hi all I'm trying to move an old project from php4 (4.0.4pl1) to the latest php5 (5.2.8 ). When I run with php5 I get a lot of "Fatal error: Cannot redeclare xxxx" errors. On inspection it looks like instead of using methods like include_once and require_once the original developers put in C style header guards like this: if (!defined("TESTFUNCTION")) { define("TESTFUNCTION", true); } else { return; } While this appears to work fine in php4, in php5 it seems like the interpreter parses the entire file again even though the return statement is hit. Does anyone know the reason for this? Is it possible to get this to work in php5? Or am I just asking for trouble with such a massive jump in the php version! Heres a couple of simple files that can replicate this happening: testfunction.php <?php if (!defined("TESTFUNCTION")) { define("TESTFUNCTION", true); } else { return; } function testFunction() { echo "This is a function"; } ?> includetest.php <?php include('testfunction.php'); include('testfunction.php'); testFunction(); ?> Result: Fatal error: Cannot redeclare testfunction() (previously declared in /opt/opwv/sw/msp/6.6.2/mscc/cac/prod/docroot/cac/testfunction.php:9) in /opt/opwv/sw/msp/6.6.2/mscc/cac/prod/docroot/cac/testfunction.php on line 10 Cheers Domhnall Quote Link to comment https://forums.phpfreaks.com/topic/140152-fatal-error-cannot-redeclare-function/ Share on other sites More sharing options...
premiso Posted January 9, 2009 Share Posted January 9, 2009 Your including the file twice, of course you will get that error. If you are going to include a file twice (which I have no clue why you would) then you would need to do this: <?php if (!function_exists("testFunction")) { function testFunction() { echo "This is a function"; } } ?> And that should stop the error. Oh and also, the return; value in the include, I do not think that works. So I would just remove that part altogether. But yea, you really should only include it once, there is no reason to have it included multiple times. Quote Link to comment https://forums.phpfreaks.com/topic/140152-fatal-error-cannot-redeclare-function/#findComment-733345 Share on other sites More sharing options...
gevans Posted January 9, 2009 Share Posted January 9, 2009 or use include_once() Quote Link to comment https://forums.phpfreaks.com/topic/140152-fatal-error-cannot-redeclare-function/#findComment-733347 Share on other sites More sharing options...
GingerRobot Posted January 9, 2009 Share Posted January 9, 2009 Given that you can indeed use the return statement to return control back to the file that did the including, i would imagine this arises out of PHP's look-ahead ability. Unlike some languages, you need not declare a function prior to it's usage in your script - it can appear anywhere. So, whilst in other languages, the function definition would never be arrived at the second time that file is included, PHP has already "seen" the function before even considering the rest of the logic flow. Quote Link to comment https://forums.phpfreaks.com/topic/140152-fatal-error-cannot-redeclare-function/#findComment-733368 Share on other sites More sharing options...
Domhnall Posted January 9, 2009 Author Share Posted January 9, 2009 Thanks for the replies. Sorry perhaps my example wasn't very good. In the example I included the file twice just to show what was happening. In the real code the problem is caused were a lot of the time files are included twice via some other included file so you end up with a loop in the include "tree". For example (imagine like this but even more horrible!): fileA.php includes incA.php fileA.php includes someutil.php incA.php includes someutil.php I understand that including twice would cause the function to be defined twice and result in the error but is interesting is why the header guard method seemed to prevent this in php4 but not in php5 and if it is somehow possible to replicate the php4 behavior in php5. GingerRobot, for what you say the other option I might have is to mass change all the include()s to include_once()s. I'm slightly worried about any side effects though. Quote Link to comment https://forums.phpfreaks.com/topic/140152-fatal-error-cannot-redeclare-function/#findComment-733385 Share on other sites More sharing options...
PFMaBiSmAd Posted January 9, 2009 Share Posted January 9, 2009 This is directly out of the php4 to php5 migration section in the php manual - If there are functions defined in the included file, they can be used in the main file independent if they are before return() or after. If the file is included twice, PHP 5 issues fatal error because functions were already declared, while PHP 4 doesn't complain about it. It is recommended to use include_once() instead of checking if the file was already included and conditionally return inside the included file. That code is attempting to use an include statement like it is a subroutine "call" statement and to conditionally define functions in that "subroutine" on the first "call". That is just poor programming, but I am guessing because the manual has a statement that exactly matches what the code is doing that the manual must have contained an example using that code at some point in time. The solutions from more desirable to least desirable - Organize your logic correctly so that functions are defined near the start of your main file (usually by placing the function definitions in their own file(s) and including them.) Use include_once/require_once Conditionally define functions as premiso has posted or in the existing code, if the function definition is placed inside of the if() logic, it will be conditionally defined only on the first include (untested but should work.) Quote Link to comment https://forums.phpfreaks.com/topic/140152-fatal-error-cannot-redeclare-function/#findComment-733390 Share on other sites More sharing options...
PFMaBiSmAd Posted January 9, 2009 Share Posted January 9, 2009 For the new information in your last post, if the included file also contains code that produces content at that point in the document, then you cannot just switch to the _once() version of include/require as that content will no longer be produced. If the included files only contain function definitions, you can change the include/require to include_once/require_once. If there is content being produced in the included files, I recommend moving the function definitions into the if() statement. Short-answer: it is time to properly organize where and when functions are defined and files are included. Quote Link to comment https://forums.phpfreaks.com/topic/140152-fatal-error-cannot-redeclare-function/#findComment-733398 Share on other sites More sharing options...
Domhnall Posted January 9, 2009 Author Share Posted January 9, 2009 Argh! Thanks PFMaBiSmAd I read over the manual but totally missed that bullet point, sorry ! I'd love to reorganize everything but the project I'm moving is so huge and old that it would take awful long time. I guess I was hoping for a quick fix but if it has to be done it has to be done! Quote Link to comment https://forums.phpfreaks.com/topic/140152-fatal-error-cannot-redeclare-function/#findComment-733401 Share on other sites More sharing options...
PFMaBiSmAd Posted January 9, 2009 Share Posted January 9, 2009 Actually, I just tested my suggestion of putting the function definition inside of the if() statement and it does work AND because of the return; statement in the else condition, content being output later in the included file will only be output the first time. So it is likely that the included files only contain function definitions and since the original programmers did not better organize the code or use the _once version of include/require, you are left with this task now. Quote Link to comment https://forums.phpfreaks.com/topic/140152-fatal-error-cannot-redeclare-function/#findComment-733416 Share on other sites More sharing options...
premiso Posted January 9, 2009 Share Posted January 9, 2009 An idea I just thought of. How many includes do you have that just include a function? Why not put all these functions into one include and just include that one file each time? If the include does nothing more than include a function, I would just combine those files and included a "main.functions.php" As long as it is not something insane like 50 includes, this should be just peachy. Quote Link to comment https://forums.phpfreaks.com/topic/140152-fatal-error-cannot-redeclare-function/#findComment-733420 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.