Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'd like to allow users to add functions to the theme I'm developing, but don't want users to change functions.php directly, as this file may be updated with theme updates. In other words, I'd like this to work in a similar fashion to custom CSS files.

How can I setup a user-functions.php file for users and ensure those functions are also run when the theme is activated?

share|improve this question

5 Answers 5

up vote 1 down vote accepted

My suggestion would be to use get_template_part. I think that is the closest you can get to what you want.

You may be able to just drop get_template_part('userfuncts'); into your functions.php. That will load userfuncts.php from your theme's main directory, if the file is present, or from a child theme's directory if applicable. See the Codex for how the function searches for files. It is a stepped-up version of PHP's include really. Any function that would work in functions.php should work in that included file. But that is an important condition. Some things do not load well from a theme's functions.php and need to be in a plugin.

However, EAMann has a good point. While it is possible to update the theme without losing the userfuncts.php file, that is not necessarily the case. It is fairly common to completely delete a theme and then upload the update. I don't know how the automatic updater does this, as I never use that updater, but if it deletes and then reinstalls you are going to have trouble.

You could do something like create two directories for your theme-- the main one and a second user functions directory.

  • wp-content/themes/my-theme
  • wp-content/themes/my-theme-userfuncts

Then create a get_template_part-like function to load files from that directory. It shouldn't be hard to do using get_template_part as a model. You'd have a kind of pseudo-child theme. It could be a source of confusion but good docs would help a lot and I have no idea how 'proper' that solution is. I only just thought about it. Hope I don't get yelled at :)

Your theme could just install itself and a child but the you'd have the same update issue if you ever altered the child.

share|improve this answer
    
"Then create a get_template_part-like function to load files from that directory..." Might I suggest locate_template()? –  Chip Bennett Feb 5 '13 at 20:31
    
['locate_template](http://core.trac.wordpress.org/browser/tags/3.5.1/wp-include‌​s/template.php#L368), if I am not mistaken, will look inside the current theme for the file, not outside of it which is key to this. At least, I couldn't get the syntax right to make either get_template_part` or locate_template look outside the current theme folder to grab a file. If you know how to do that, then yes, that would be preferable. –  s_ha_dum Feb 5 '13 at 20:41
    
@s_ha_dum: Appreciate your response. I think you've gotten the closest to what I need. I'm planning to have a separate directory for custom user stuff and I was thinking about using PHP's include. I'm going to accept and upvote your answer. –  chowwy Feb 5 '13 at 20:44
    
get_template_part() is just a wrapper for locate_template(). You can tell locate_template() where to look. ;) @chowwy: caveat: if that directory is inside your own Theme, it will get removed when the Theme is updated. Nothing in the Theme itself is safe/update-proof for the end user to edit. –  Chip Bennett Feb 5 '13 at 20:45
    
@ChipBennett, locate_template uses the constants STYLESHEETPATH and TEMPLATEPATH. Those point to either the child or the parent theme directory-- var_dump(STYLESHEETPATH,TEMPLATEPATH);-- and they are hard coded into locate_template. It does not appear meant to load files from outside of one of those two locations, which is what I am suggesting that the asker do. If you know how to do that, I'd love to know. I will edit my answer and thank you for it. I am not suggesting the asker create an actual child theme for this, if that is what you are thinking. –  s_ha_dum Feb 5 '13 at 21:19

Really, any files you place in the theme will be replaced/removed when the theme updates.

Instead, if you want users to add custom functionality they should do so through a custom plugin. If you have hooks and filters exposed through the theme, a custom functionality plugin will solve the problem.

Basically, it's two files:

readme.txt

=== My Functionality Plugin ===
Contributors:      me
Donate link:
Tags:
Requires at least: 3.4.2
Tested up to:      3.5
Stable tag:        1.0
License:           GPLv2 or later
License URI:       http://www.gnu.org/licenses/gpl-2.0.html

Adds custom functionality where needed

functionality.php

<?php
/**
 * Plugin Name: My Functionality Plugin
 * Plugin URL:
 * Description: Adds custom functionality where needed
 * Version:     1.0
 * Author:      Me
 * Author URI:  
 * License:     GPL2+
 */

function filter_my_theme_copyright( $copyright ) {
    return '&copy; 2013';
}
add_filter( 'my_theme_copyright', 'filter_my_theme_copyright' );

Without knowing what your theme is doing or what custom functionality you need, I can't be very precise. But if you expose actions where you want users to do something and filter what output you want them to filter, then anyone can use a custom functionality plugin like this without hacking on the theme directly.

share|improve this answer
    
Thanks. I already know how to setup a custom functions file in a plugin. I would prefer to build this directly into my theme, so that users can simply edit the user-functions.php file and the functions will be active with the theme. –  chowwy Feb 5 '13 at 19:33
    
If user-functions.php is part of your theme, it will be wiped out when they upgrade. The exact same problem you're trying to avoid by not having them edit functions.php itself. The only way to allow persistent user-specified functionality is to move it out of the theme itself. Or to have them build a child theme of your theme with its own functionality. –  EAMann Feb 5 '13 at 19:44
    
Not necessarily. I've noticed similar custom functions functionality in the thesis theme and didn't encounter any loss of code when upgrading the theme. Just like custom CSS files don't change when a theme is upgraded. –  chowwy Feb 5 '13 at 19:48
1  
As far as I know, Thesis doesn't use the core updater; users have to update it manually. That's not a model I would choose to emulate. YMMV. –  Chip Bennett Feb 6 '13 at 3:55
    
Not interested in emulating Thesis' model, just want to make it as convenient as possible for users to add functions to my theme. –  chowwy Feb 6 '13 at 15:23

For allowing user functions, you really have two options:

  1. Make your Theme as Child Theme-friendly as possible, and encourage users to define custom functions in the Child Theme functions.php
  2. Provide ample action/filter hooks, for the user to define callback functions, either via Child Theme, or via custom Plugin.
share|improve this answer
    
Thanks for your response. I'm planning to use the hooks, just not in a plugin or child theme. –  chowwy Feb 5 '13 at 20:38
    
What do you mean by, "not in a plugin or child theme"? Presumably, you would define your hooks, and the user would add callbacks to your Theme-defined hooks. –  Chip Bennett Feb 5 '13 at 20:43
    
I meant that I want to allow users to add their functions to the theme without using a plugin or child theme. –  chowwy Feb 5 '13 at 20:45
    
Impossible. Anything an end user adds to your Theme will be removed/overwritten when the Theme is updated. WordPress physically deletes the current Theme directory, then unpacks the new Theme to put in its place. Files are deleted then written, not simply overwritten-in-place. –  Chip Bennett Feb 5 '13 at 20:48

There is a plugin that allows you to do this in the admin, it allows for portable user input functions (theme agnostic) , with no need to edit to your theme's functions.php

You can see it here: https://github.com/bungeshea/code-snippets

You can download it from wordpress.org here: http://wordpress.org/extend/plugins/code-snippets/

Screenshot: enter image description here

share|improve this answer
    
Thanks for this. Would rather not use a plugin for theme functionality. –  chowwy Feb 5 '13 at 20:36
    
If the code is tied into a specific theme's functionality then yes, otherwise think about abstracting the code for portability. –  Wyck Feb 5 '13 at 21:14

To ensure your customers are able to easily override aspects of your theme, the best bet is to stick with WordPress' existing conventions for this, ie: a child theme. "functions.php" is also intended for custom user-entered code, but you said you'd prefer to stay away from that, so I'll focus on other options.

The general rule of thumb is as follows:

Styles

Overriding CSS styles should be done in the "style.css" file inside a child theme.

Functions

Overriding procedural functions should be done using pluggable functions. The WordPress Codex has an example of how to setup pluggable functions.

Hooked Functions

While functions that are assigned to a hook or filter could also be made pluggable, you could also just encourage customers to unhook the function and hook in their own replacement. This would save you, at most, 2 lines of code per function in your files, as you wouldn't be making the functions pluggable.

Template Parts

If you'd like customers to be able to easily override specific sections of your theme's output without having to copy an entire template file into their child theme, you could make effective use of template parts to achieve this (for example, if your footer area contains widgets and then, maybe, a credits section, each of those could be a template part).

As mentioned above, effective placement of do_action() calls is an easy way to allow customers to hook in their own code.

Combined with the above options, you should be well on your way to having your customers easily customise your theme using existing WordPress conventions and making it easier for them to update their copy of your theme to future versions. :)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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