12

I got the problem that i have to load my parent theme's functions.php file before my child theme's functions.php file loads. This is needed for the setup & init procedure. I looked at the hooks inside /wp_core_root/wp-settings.php (named: do_action('setup_theme');).

The problem is that i don't know how to hook into there, because the first file i get is the child theme's functions.php, so no add_action( 'setup_theme', 'my_init_function' ); will work.

Edit:
a) I know that plugins load earlier than theme and therefore can access even the initial Query, but i don't want to rely on a Plugin.
b) Here's the code (shortened) from wp-settings.php file

// happens a lot earlier:  
do_action( 'plugins_loaded' );

// localize stuff happening here
    do_action( 'setup_theme' );

        // Load the functions for the active theme, for both parent and child theme if applicable.
        if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists( STYLESHEETPATH . '/functions.php' ) )
            include( STYLESHEETPATH . '/functions.php' );
        if ( file_exists( TEMPLATEPATH . '/functions.php' ) )
            include( TEMPLATEPATH . '/functions.php' );
    // first available hook, *after* functions.php was loaded
    do_action( 'after_setup_theme' );

I want to avoid two things: First a lot of explanation to users. Second the chance that someone breaks anything if the cuts the rope with accidently deleting the parents init procedure. People shall just play inside the functions.php without risking to break anything without knowing it.

In other words: How do i keep my child themes functions.php file clean, but have the the parent themes bootstrap done?

Any ideas? Thanks a lot!

5
  • Can't you just include it?
    – wyrfel
    Commented Feb 21, 2011 at 19:49
  • My question is: from where? The first file that get's loaded in theme context is the child theme's functions.php. Take a look at the "molto loko" wp-settings.php file in core (line: 275-279 @wp 3.1 rc) ... looks like this: if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists( STYLESHEETPATH . '/functions.php' ) ) include( STYLESHEETPATH . '/functions.php' ); if ( file_exists( TEMPLATEPATH . '/functions.php' ) ) include( TEMPLATEPATH . '/functions.php' );, so i can't see a chance... And i don't want to use a plugin to bootstrap my theme.
    – kaiser
    Commented Feb 21, 2011 at 19:58
  • I might be totally missing something here, but if you insert include(/path/to/parent/themes/functions.php) at the top of your child themes functions.php, then everything in there is loaded before. Not?
    – wyrfel
    Commented Feb 21, 2011 at 21:35
  • @wyrfel: i updated the Q to make it more clear
    – kaiser
    Commented Feb 22, 2011 at 4:50
  • I see, thanks, it's a lot clearer now. Plus i assumed you were just doing this for a single install.
    – wyrfel
    Commented Feb 22, 2011 at 16:45

5 Answers 5

11

Justin Tadlock recently wrote a great post about making a better functions.php file
where (if I remember correctly) he deals with this exact issue.

Unfortunately his site is down at the moment so I have to rely on my memory for now.

You are on the right track with the after_setup_theme hook.

  1. As far as I remember the trick is to wrap your filters and actions into it's function.
    See example below.
  2. You do that in both parent and child functions.php files.
  3. Then you can play with the priority of these two hooks.

Little bit of code worth thousand words - your parent theme's function.php should look like this:

add_action( 'after_setup_theme', 'your_parent_theme_setup', 9 );
function your_parent_theme_setup() {    
    add_action(admin_init, your_admin_init);
    add_filter(the_content, your_content_filter);
}

function your_admin_init () {
...
}

function your_content_filter() {
...
}
3
  • Ehm, thanks for the write up (+1). You got an impressive brain ;). The problem is that after_setup_theme is too late, because the functions.php files were already loaded.
    – kaiser
    Commented Feb 21, 2011 at 23:36
  • EDIT: After rethinking your code and reading "do that in both parent and child functions.php" & "play with the priority" it starts making sense. Still searching for a better solution that user can't break that easy, but it makes sense! Thanks!
    – kaiser
    Commented Feb 21, 2011 at 23:47
  • No real solution over here, so i check mark this, as you were the first one to propose this.
    – kaiser
    Commented Feb 23, 2011 at 0:43
9

Firstly, you can't. The child theme's functions.php always loads first, period.

Second, themes can't hook to setup_theme. Plugins can, but the first thing a theme can hook to is after_setup_theme.

If your parent is designed correctly, then the child is capable of overriding functions and stuff in the parent, but only when it loads first.

Broadly speaking, if you think you need to load the parent's functions file first, then you're probably doing it wrong, somehow. You need to explain the larger issue.

5
  • Thanks for your answer. I understand the need to load plugins before themes and realised the fact already (read above: "And i don't want to use a plugin to bootstrap my theme."). To elaborate my case: I got an ini file that cares about loading all my framework parts, that starts in parent themes functions php with requiring the file and loading the init-class. InitClass cares about loading a) and array of data from child themes .ini-files and then pushes it into diffent classes for further processing ex. meta boxes, custom post types, etc.
    – kaiser
    Commented Feb 21, 2011 at 23:41
  • My problem is that i have to init all this from my parents functions.php file, so a normal user can't break it, when playing around inside the child theme. My second problem is that all of those classes are not available inside the child theme's functions.php file, so they are of no use... but maybe i got a big thinking error right here. Any ideas or suggestions on how to make it better?
    – kaiser
    Commented Feb 21, 2011 at 23:44
  • 3
    .... I think you're just going to have to accept the fact that if a user breaks things, then that's really their problem. Bottom line: There is no way to load the parent theme's functions.php first and leave the child theme "clean". If you need something in the child theme to run after the parent theme's functions.php file has loaded, then you put it inside a function hooked to after_setup_theme. That runs after both functions.php files load.
    – Otto
    Commented Feb 22, 2011 at 7:23
  • Ok. It's not that big problem. I'm just interessted if there's a possibility. Question: What for does a "framework worth it's salt" then have a hook after the init procedure and doesn't simply use the after_setup_theme hook? Just to not "spam" the hook, or because it's more "enterprisy" or "kool"er? I mean: Is the "best practice" idea behind theme specific parallel hooks "leave core hooks for plugins"? (That's how i handle it currently.)
    – kaiser
    Commented Feb 22, 2011 at 9:01
  • "If you're going to to that, don't bother with an extra action. Just hook to after_setup_theme." Ok. Thanks. +1
    – kaiser
    Commented Feb 23, 2011 at 0:42
5

So you're trying to execute code from the child's functions.php, but after the parent theme has loaded. Simple, just use a custom action:

At the end of parent/functions.php:

do_action('parent_loaded');

In child/functions.php:

function parent_loaded() {
    // do init stuff
}
add_action('parent_loaded', 'parent_loaded');

All parent themes worth their salt do it this way. What's more, they have several other actions and filters sprinkled around for the child theme to use.

4
  • I try to avoid as many instructions as possible. That's one of the reasons i switched from a config.php file in the child theme folder and now use ini files instead. In one sentence: I try to get away from my old/your solution and get as close back to core and codex as possible. My problem is that i can't deliver a single function from the child theme, because no class or else from my bootstrap is available inside the child themes functions.php file (not talking about custom/framework template tags).
    – kaiser
    Commented Feb 22, 2011 at 0:04
  • See updated answer.
    – scribu
    Commented Feb 22, 2011 at 0:13
  • I updated the Q too. After reading that 2/3 answers point to me to the same source (thematic, before your edit) i get the feeling that there's only the "justin tadlock" method of including, but i want to get sure.
    – kaiser
    Commented Feb 22, 2011 at 4:55
  • 2
    If you're going to to that, don't bother with an extra action. Just hook to after_setup_theme.
    – Otto
    Commented Feb 22, 2011 at 7:25
0

Why don't you include parent theme's functions.php file in child theme's functions.php file, like this:

In child theme's functions.php file:

if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists( TEMPLATEPATH . '/functions.php' ) )
            include( TEMPLATEPATH . '/functions.php' );

// code of child theme's functions.php file continues here

By this way, the parent theme's functions.php file is not changed (sometimes this is important).

1
  • as mentioned in the Q: "In other words: How do i keep my child themes functions.php file clean, but have the the parent themes bootstrap done?" Even better: How do i avoid a call from inside any functions.php file? Why: People are used to just smash every crap that they don't want to have in template files in there. So there's a high chance that someone accidently deletes some lines. My experience: No one really reads comments, readme or documentation.
    – kaiser
    Commented Feb 22, 2011 at 5:46
0

I had a similar issue before and I fix it by creating an a extra empty "child-functions.php" in parent and including into "functions.php" (parent too) right after the files / functions I want to use in child , then in child theme I create a "child-functions.php" file and there is where I can start simulate child functions.php run after parent isn't an a elegant solution but did the work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.