WP – Includes – Functions.php

https://wordpress.stackexchange.com/questions/191646/include-files-in-functions-php/191666

Including a file inside a subdirectory is the same as any other as long as you know the path to the file. Since it’s possible to [move the ‘wp-content’ directory](http://codex.wordpress.org/Editing_wp-config.php#Moving_wp-content_folder), don’t pass that part of the path to the `require` statement; instead, use the `WP_CONTENT_DIR` constant.

[code language=”php”] require_once WP_CONTENT_DIR . ‘/new-directory/my-file.php’;
[/code]

Also, you can leave out the parenthesis since `include` and `require` are [statements, not functions](http://php.net/manual/en/function.require.php).


https://wordpress.stackexchange.com/questions/1403/organizing-code-in-your-wordpress-themes-functions-php-file

If you are getting to the point where the code in your theme’s functions.php is starting to overwhelm you I would definitely say you are ready to consider splitting it up into multiple files. I tend to do that almost by second nature at this point.

Use Include Files in your Theme’s functions.php File

I create a subdirectory called “includes” under my theme directory and segment my code into include files organized by what makes sense to me at the time (which means I’m constantly refactoring and moving code around as a site evolves.) I also rarely put any real code in functions.php; everything goes in the include files; just my preference.

Just to give you an example here’s my test install that I use to test my answers to questions here on WordPress Answers. Every time I answer a question I keep the code around in case I need it again. This isn’t exactly what you’ll do for a live site but it shows the mechanics of splitting up the code:

[code language=”php”] <?php
/*
* functions.php
*
*/
require_once( __DIR__ . ‘/includes/null-meta-compare.php’);
require_once( __DIR__ . ‘/includes/older-examples.php’);
require_once( __DIR__ . ‘/includes/wp-admin-menu-classes.php’);
require_once( __DIR__ . ‘/includes/admin-menu-function-examples.php’);

// WA: Adding a Taxonomy Filter to Admin List for a Custom Post Type?
// http://wordpress.stackexchange.com/questions/578/
require_once( __DIR__ . ‘/includes/cpt-filtering-in-admin.php’);
require_once( __DIR__ . ‘/includes/category-fields.php’);
require_once( __DIR__ . ‘/includes/post-list-shortcode.php’);
require_once( __DIR__ . ‘/includes/car-type-urls.php’);
require_once( __DIR__ . ‘/includes/buffer-all.php’);
require_once( __DIR__ . ‘/includes/get-page-selector.php’);

// http://wordpress.stackexchange.com/questions/907/
require_once( __DIR__ . ‘/includes/top-5-posts-per-category.php’);

// http://wordpress.stackexchange.com/questions/951/
require_once( __DIR__ . ‘/includes/alternate-category-metabox.php’);

// http://lists.automattic.com/pipermail/wp-hackers/2010-August/034384.html
require_once( __DIR__ . ‘/includes/remove-status.php’);

// http://wordpress.stackexchange.com/questions/1027/removing-the-your-backup-folder-might-be-visible-to-the-public-message-generate
require_once( __DIR__ . ‘/includes/301-redirects.php’);
[/code]

Or Create Plugins

Another option it to start grouping your code by function and create your own plugins. For me I start coding in the theme’s functions.php file and by the time I get the code fleshed out I’ve moved most of my code into plugins.

However NO Significant Performance Gain From PHP Code Organization

On the other hand structuring your PHP files is 99% about creating order and maintainability and 1% about performance, if that (organizing .js and .css files called by the browser via HTTP is a completely different case and has huge performance implications.) But how you organize your PHP code on the server pretty much doesn’t matter from a performance perspective.

And Code Organization is Personal Preference

And last but not least code organization is personal preference. Some people would hate how I organize code just as I might hate how they do it too. Find something you like and stick with it, but allow your strategy to evolve over time as you learn more and get more comfortable with it.

How to include your files the right way:

[code language=”php”] function wpse1403_bootstrap()
{
// Here we load from our includes directory
// This considers parent and child themes as well
locate_template( array( ‘inc/foo.class.php’ ), true, true );
}
add_action( ‘after_setup_theme’, ‘wpse1403_bootstrap’ );
[/code]

The same works in plugins too.

How to get the right path or URi

Also take a look at file system API functions like:

  • home_url()
  • plugin_dir_url()
  • plugin_dir_path()
  • admin_url()
  • get_template_directory()
  • get_template_directory_uri()
  • get_stylesheet_directory()
  • get_stylesheet_directory_uri()
  • etc.

How to reduce the number of include/require

If you need to fetch all files from a directory go with

[code language=”php”] foreach ( glob( ‘path/to/folder/*.php’ ) as $file )
include $file;
[/code]

Keep in mind that this ignores failures (maybe good for production use)/not loadable files.

To alter this behavior you might want to use a different config during development:

[code language=”php”] $files = ( defined( ‘WP_DEBUG’ ) AND WP_DEBUG )
? glob( ‘path/to/folder/*.php’, GLOB_ERR )
: glob( ‘path/to/folder/*.php’ )

foreach ( $files as $file )
include $file;
[/code]

Edit: OOP/SPL approach

As I just came back and saw that this answer is getting more and more upvotes, I thought I might show how I’m doing it nowadays – in a PHP 5.3+ world. The following example loads all files from a themes subfolder named src/. This is where I have my libraries that handle certain tasks like menus, images, etc. You don’t even have to care about the name as every single file gets loaded. If you have other subfolders in this directory, they get ignored.

The \FilesystemIterator is the PHP 5.3+ supercedor over the \DirectoryIterator. Both are part of the PHP SPL. While PHP 5.2 made it possible to turn the built in SPL extension off (below 1% of all installs did that), the SPL now is part of PHP core.

[code language=”php”]

namespace Theme;

$files = new \FilesystemIterator( __DIR__.’/src’, \FilesystemIterator::SKIP_DOTS );
foreach ( $files as $file )
{
/** @noinspection PhpIncludeInspection */
! $files->isDir() and include $files->getRealPath();
}
[/code]

Previously while I still supported PHP 5.2.x, I used the following solution: A \FilterIterator in the src/Filters directory to only retrieve files (and not dot pointers of folders) and a \DirectoryIterator to do the looping and loading.

[code language=”php”] namespace Theme;

use Theme\Filters\IncludesFilter;

$files = new IncludesFilter( new \DirectoryIterator( __DIR__.’/src’ ) );
foreach ( $files as $file )
{
include_once $files->current()->getRealPath();
}
[/code]

The \FilterIterator was as easy as that:

[code langauge=”php”] <?php

namespace Theme\Filters;

class IncludesFilter extends \FilterIterator
{
public function accept()
{
return
! $this->current()->isDot()
and $this->current()->isFile()
and $this->current()->isReadable();
}
}
[/code]

Aside from PHP 5.2 being dead/EOL by now (and 5.3 as well), there’s the fact that it’s more code and one more file in the game, so there’s no reason to go with the later and support PHP 5.2.x.

Summed up

EDIT The obviously correct way is to use namespaced code, prepared for PSR-4 autoloading by putting everything in the appropriate directory that already is defined via the namespace. Then just use Composer and a composer.json to manage your dependencies and let it auto-build your PHP autoloader (that imports automatically a file by just calling use \\ClassName). That’s the de-facto standard in the PHP world, the easiest way to go and even more pre-automated and simplified by WP Starter.

I like to use a function to the files inside a folder. This approach makes it easy to add new features when adding new files. But I write always in class or with namespaces – give it more control about the Namespace of functions, method etc.

Below a small example; ut also useage with the agreement about the class*.php

[code language=”php”] public function __construct() {

$this->load_classes();
}

/**
* Returns array of features, also
* Scans the plugins subfolder "/classes"
*
* @since 0.1
* @return void
*/
protected function load_classes() {

// load all files with the pattern class-*.php from the directory classes
foreach( glob( dirname( __FILE__ ) . ‘/classes/class-*.php’ ) as $class )
require_once $class;

}
[/code]

In Themes I use often a other scenario. I define the function of the externel file in a support ID, see the example. That is usefull if I will easy deactivate the feture of the externel file. I use the WP core function require_if_theme_supports() and he load only, if the support ID was active. In the follow example I deifned this supported ID in the line before load the file.

[code language=”php”] /**
* Add support for Theme Customizer
*
* @since 09/06/2012
*/
add_theme_support( ‘documentation_customizer’, array( ‘all’ ) );
// Include the theme customizer for options of theme options, if theme supported
require_if_theme_supports(
‘documentation_customizer’,
get_template_directory() . ‘/inc/theme-customize.php’
);
[/code]

You can see more of this in the repo of this theme.

https://github.com/bueltge/Documentation/blob/master/functions.php

[code language=”php”]

<?php
/**
* Functions and definitions
*
* @package WordPress
* @subpackage Documentation
* @version 2015-03-16
*/

if ( ! function_exists( ‘documentation_setup’ ) ) {

add_action( ‘after_setup_theme’, ‘documentation_setup’ );
/**
* Sets up theme defaults and registers support for various WordPress features.
*
* Note that this function is hooked into the after_setup_theme hook, which runs
* before the init hook. The init hook is too late for some features, such as indicating
* support post thumbnails.
*
* @since 1.0.0
* @return void
*/
function documentation_setup() {

/**
* Post content often has specified width.
* Thus, images which has bigger size than content width can break up the layout of theme.
* To prevent this situation, WordPress provides one way to specify the maximum image size for themes.
* Define the maximum image size
*/
if ( ! isset( $GLOBALS[ ‘content_width’ ] ) ) {
$GLOBALS[ ‘content_width’ ] = 900;
}

/**
* Make Documentation available for translation.
* Translations can be added to the /languages/ directory.
* If you’re building a theme based on Documentation, use a find and replace
* to change ‘documentation’ to the name of your theme in all the template files.
*/
load_theme_textdomain( ‘documentation’, get_template_directory() . ‘/languages’ );

/**
* Login + Admin Bar Branding
*
* @see https://github.com/bueltge/WordPress-Basis-Theme/tree/namespace/inc/admin
*/
require_once( get_template_directory() . ‘/inc/class-branding.php’ );
new Documentation_Admin_Branding( array() );

/**
* Add support for Theme Customizer
*
* @since 09/06/2012
*/
add_theme_support( ‘documentation_customizer’, array( ‘all’ ) );
// Include the theme customizer for options of theme options, if theme supported
require_if_theme_supports( ‘documentation_customizer’, get_template_directory() . ‘/inc/theme-customize.php’ );

/**
* Add support for custom style to write in head
*
* @since 09/06/2012
*/
// include to write the custom theme options in theme head
require_if_theme_supports( ‘documentation_customizer’, get_template_directory() . ‘/inc/head-style.php’ );

/**
* Custom template tags for this theme.
*
* @since 2015-06-10
*/
require get_template_directory() . ‘/inc/template-tags.php’;

/**
* Custom functions, that hook in core for this theme.
*
* @since 2015-06-10
*/
require get_template_directory() . ‘/inc/extras.php’;

/**
* Widget areas in the sidebar and his markup.
*
* @since 2015-06-10
*/
require get_template_directory() . ‘/inc/widgets.php’;

/**
* Custom comment callback function.
*
* @since 2015-06-10
*/
require get_template_directory() . ‘/inc/comments.php’;

/**
* Add support for the hook alliance
*
* @see https://github.com/zamoose/themehookalliance
* @since 2012-02-10
*/
add_theme_support( ‘tha_hooks’, array( ‘all’ ) );
// include the file from this project, if theme supported
if ( file_exists( get_template_directory() . ‘/inc/tha/tha-theme-hooks.php’ ) ) {
require_if_theme_supports( ‘tha_hooks’, get_template_directory() . ‘/inc/tha/tha-theme-hooks.php’ );
} else {
require_if_theme_supports( ‘tha_hooks’, get_template_directory() . ‘/inc/tha-1.0/tha-theme-hooks.php’ );
}

// Add default posts and comments RSS feed links to <head>.
add_theme_support( ‘automatic-feed-links’ );

// This theme uses wp_nav_menu() in one location.
register_nav_menu( ‘primary’, esc_attr__( ‘Primary Menu’, ‘documentation’ ) );

// Add support for custom background.
$args = array(
‘default-image’ => ”,
‘default-color’ => ‘fff’,
);
add_theme_support( ‘custom-background’, apply_filters( ‘documentation_custom_background_args’, $args ) );

// define suffix for development on scripts and styles
$suffix = defined( ‘SCRIPT_DEBUG’ ) && SCRIPT_DEBUG ? ‘.dev’ : ”;
// This theme styles the visual editor with editor-style.css to match the theme style.
add_editor_style( ‘css/editor-style’ . $suffix . ‘.css’ );
}

} // end if func exists

if ( ! function_exists( ‘documentation_get_options’ ) ) {

/**
* Return options value or array of all values
* Small wrapper for the class
*
* @since 08/09/2012
*
* @param string $value
*
* @return String , Array Value of the options item
*/
function documentation_get_options( $value = ” ) {

// failed to load file for options, then return NULL
if ( ! class_exists( ‘Documentation_Customize’ ) ) {
return NULL;
}

$documentation_options = new Documentation_Customize();

$options = $documentation_options->get_theme_options();

if ( ! empty( $value ) ) {
$options = $options[ $value ];
}

return $options;
}

} // end if func exists

if ( ! function_exists( ‘documentation_scripts_styles’ ) ) {

add_action( ‘wp_enqueue_scripts’, ‘documentation_scripts_styles’ );
/**
* Enqueue scripts and styles for front-end.
*
* @since 2.0
*/
function documentation_scripts_styles() {

// set suffix for debug mode
$suffix = defined( ‘SCRIPT_DEBUG’ ) && SCRIPT_DEBUG ? ‘.dev’ : ”;

/**
* Add JavaScript to pages with the comment form to support
* sites with threaded comments (when in use).
*/
if ( is_singular() && comments_open() && get_option( ‘thread_comments’ ) ) {
wp_enqueue_script( ‘comment-reply’ );
}

// Register responsive table script
// Kudos to Responsive Tables project
// @see http://www.zurb.com/playground/responsive-tables
wp_register_script(
‘documentation-responsive-tables’,
get_template_directory_uri() . ‘/js/responsive-tables’ . $suffix . ‘.js’,
array( ‘jquery’ ),
’01/14/2013′,
TRUE
);
// Register responsive table style
wp_register_style(
‘documentation-responsive-tables’,
get_template_directory_uri() . ‘/css/responsive-tables’ . $suffix . ‘.css’,
array(),
’01/14/2013′,
‘screen’
);

// Register main style
wp_register_style( ‘documentation-style’, get_stylesheet_directory_uri() . ‘/css/style’ . $suffix . ‘.css’ );
// Register print CSS file
wp_register_style(
‘documentation-print-style’,
get_stylesheet_directory_uri() . ‘/css/print’ . $suffix . ‘.css’,
array(),
FALSE,
‘print’
);

wp_enqueue_style( ‘documentation-style’ );
wp_enqueue_style( ‘documentation-print-style’ );

//wp_enqueue_script( ‘documentation-responsive-tables’ );
//wp_enqueue_style( ‘documentation-responsive-tables’ );
}

} // end if func exists

[/code]
Scroll to Top