• H2GD Part 24: Fatal error: Cannot redeclare A()

    For reasons that I will not divulge right now I was trying to create a child theme which was almost exactly a clone of the parent theme and came across a problem where I received the PHP Fatal error message: Cannot redeclare function. Fatal error: Cannot redeclare function() ( previously declared in file:nn ) in file on line mm This smacked of a problem I’d previously written about in H2GD Part 16: PHP bug #63156. So I spent some time trying to understand the problem, eventually reducing it to the simplest equivalent problem.

    Original problem

    If a theme has a functions.php file then this is loaded very early on by wp-settings.php. If a child theme has a functions.php then this is included first. Code in both of the files may get executed. if ( ! defined( 'WP_INSTALLING' ) || 'wp-activate.php' === $pagenow ) { if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists( STYLESHEETPATH . '/functions.php' ) ) include( STYLESHEETPATH . '/functions.php' ); if ( file_exists( TEMPLATEPATH . '/functions.php' ) ) include( TEMPLATEPATH . '/functions.php' ); } In my clone the child theme’s functions.php was exactly the same as the parent’s. So I was getting Fatal errors for quite a few functions, which were defined within the main class’s private methods. e.g. public function performA() { function A() { } add_action( 'action', 'A' ); } BUT what I didn’t understand was why this was happening. The class definition was wrapped in a class_exists() test. if (!class_exists( 'B') ) { class B { // methods go here } } It was obvious that the same code was being loaded in different files, but wasn’t it protected by the class_exists()?

    The answer was that the duplication of the code in a child theme was a distraction. The actual problem was a lot simpler.

    Simplified problem

    The problem was due to code execution during instantiation of the class and the fact that the class was being instantiated twice; once in the child theme’s functions.php then again in the parent’s. Here’s a simplified version. class B { function __construct() { function A() {} } } $b1 = new B(); $b2 = new B(); If you omit the last line everything is fine. But as it is, we get the Fatal error.

    Note: In case you’re wondering why the line numbers ( nn and mm ) are different in the Fatal error message. The previously declared line number (nn) is the end of the function; the “on line mm” is the line at the start of the declaration.

    Workaround

    One solution to the problem is to wrap the internal function within a not function_exists() test.

    It turns out that this problem has been around for donkey’s years… longer than WordPress. See http://www.php.net/manual/en/language.functions.php#21150

    Conclusions

    • Don’t use nested functions which are not protected by function_exists() tests.
    • Sometimes its not possible to use child themes.

    Final thought 🙂

    If you try to use two new B’s (newbies) on your project, chances are it won’t work.


    , ,

    Published:

    Last updated:

    August 18, 2014

Categories

Tide times from tidetimes.co.uk

Tide Times & Heights for Langstone Harbour on
Monday, 17 January 2022
Low Tide:04:19 ( 1.50m )
High Tide:11:20 ( 4.40m )
Low Tide:16:39 ( 1.20m )
High Tide:23:50 ( 4.40m )

Tide times from tidetimes.org.uk

Tide Times & Heights for Northney on
17th January 2022
04:27 Low Tide ( 1.31m )
11:23 High Tide ( 4.37m )
16:48 Low Tide ( 1.01m )
23:57 High Tide ( 4.33m )