Single functions.php or split into many small files?

The question:

I am creating a simple framework with theme options. I have divided chunks of code within functions.php and placed it within a specific folder structure.

Now in my main functions.php file, I only have require_once calls to these files.

But for the sake of argument – let’s say that I’ll end up with 20 files to include.

QUESTIONS:

  1. Does this have effect on WP performance in a visible way ?
  2. Is it better to keep it all within 1 file (functions.php)
  3. what is the best way to go about this ?

Thanks.

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

1. Does this have effect on WP performance in a visible way ?

IF it would have a real affect for some small files, then it would have an affect that has an impact lower than WP: PHP and server performance. Does it really have an affect? Not really. But you can still simply start doing performance tests yourself.

2. Is it better to keep it all within 1 file (functions.php)

Now the question is “What is better”? From overall file(s) loading time? From file organisation point of view? Anyway, it doesn’t make any difference. Do it in a way so you don’t loose overview and can maintain the result in a way that is pleasant for you.

3. what is the best way to go about this?

What I normally do is simply hooking somewhere in (plugins_loaded, after_setup_theme, etc. – depends on what you need) and then just require them all:

foreach ( glob( plugin_dir_path( __FILE__ ) ) as $file )
    require_once $file;

Anyway, you can make it a little more complicated and flexible as well. Take a look at that example:

<?php

namespace WCM;

defined( 'ABSPATH' ) OR exit;

class FilesLoader implements IteratorAggregate
{
    private $path = '';

    private $files = array();

    public function __construct( $path )
    {
        $this->setPath( $path );
        $this->setFiles();
    }

    public function setPath( $path )
    {
        if ( empty( $this->path ) )
            $this->path = plugin_dir_path( __FILE__ ).$path;
    }

    public function setFiles()
    {
        return $this->files = glob( "{$this->getPath()}/*.php" );
    }

    public function getPath()
    {
        return $this->path;
    }

    public function getFiles()
    {
        return $this->files;
    }

    public function getIterator()
    {
        $iterator = new ArrayIterator( $this->getFiles() );
        return $iterator;
    }

    public function loadFile( $file )
    {
        include_once $file;
    }
}

It’s a class that does basically the same (needs PHP 5.3+). The benefit is that it’s a bit more fine grained, so you can easily just load files from folders that you need to perform a specific task:

$fileLoader = new WCMFilesLoader( 'assets/php' );

foreach ( $fileLoader as $file )
    $fileLoader->loadFile( $file );

Update

As we live in a new, post PHP v5.2 world, we can make use of the FilterIterator. Example of the shortest variant:

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

If you have to stick with PHP v5.2, then you still can go with the DirectoryIterator and pretty much the same code.

Method 2

I reworked @kaiser answer a bit to my needs – thought I share it. I wanted more options, those are explained inside the code and at the usage example below.

Code:

<?php

defined( 'ABSPATH' ) OR exit;

/**
 * Functions_File_Loader
 * 
 * Makes it possible to clutter the functions.php into single files.
 * 
 * @author kaiser
 * @author ialocin
 * @link http://wordpress.stackexchange.com/q/111970/22534
 *
 */

class Functions_File_Loader implements IteratorAggregate {

    /**
     * @var array
     */
    private $parameter = array();

    /**
     * @var string
     */
    private $path;

    /**
     * @var string
     */
    private $pattern;

    /**
     * @var integer
     */
    private $flags;

    /**
     * @var array
     */
    private $files = array();

    /**
     * __construct
     *
     * @access public 
     * @param array $parameter
     */
    public function __construct( $parameter ) {
        $this->set_parameter( $parameter );
        $this->set_path( $this->parameter[ 'path' ] );
        $this->set_pattern( $this->parameter[ 'pattern' ] );
        $this->set_flags( $this->parameter[ 'flags' ] );
        $this->set_files();
    }

    /**
     * set_parameter
     *
     * @access public 
     * @param array $parameter
     */
    public function set_parameter( $parameter ) {
        if ( empty( $parameter ) )
            $this->parameter = array('','','');
        else
            $this->parameter = $parameter;
    }

    /**
     * get_parameter
     *
     * @access public 
     * @return array
     */
    public function get_parameter() {
        return $this->parameter;
    }

    /**
     * set_path
     *
     * defaults to get_stylesheet_directory()
     * 
     * @access public 
     * @param string $path
     */
    public function set_path( $path ) {
        if ( empty( $path ) )
            $this->path = get_stylesheet_directory().'/';
        else
            $this->path = get_stylesheet_directory().'/'.$path.'/';
    }

    /**
     * get_path
     *
     * @access public 
     * @return string
     */
    public function get_path() {
        return $this->path;
    }

    /**
     * set_pattern
     *
     * defaults to path plus asterisk »*«
     * 
     * @access public 
     * @param string $pattern
     */
    public function set_pattern( $pattern ) {
        if ( empty( $pattern ) )
            $this->pattern = $this->get_path() . '*';
        else
            $this->pattern = $this->get_path() . $pattern;
    }

    /**
     * get_pattern
     *
     * @access public 
     * @return string
     */
    public function get_pattern() {
        return $this->pattern;
    }

    /**
     * set_flags
     *
     * @access public 
     * @param integer $flags
     */
    public function set_flags( $flags ) {
        if ( empty( $flags ) )
            $this->flags = '0';
        else
            $this->flags = $flags;
    }

    /**
     * get_flags
     *
     * @access public 
     * @return integer
     */
    public function get_flags() {
        return $this->flags;
    }


    /**
     * set_files
     *
     * @access public 
     */
    public function set_files() {
        $pattern = $this->get_pattern();
        $flags = $this->get_flags();
        $files = glob( $pattern, $flags );
        $this->files = $files;
    }


    /**
     * get_files
     *
     * @access public 
     * @return array
     */
    public function get_files() {
        return $this->files;
    }

    /**
     * getIterator
     * 
     * This function name has to be kept
     * 
     * @access public 
     * @return void
     */
    public function getIterator() {
        $iterator = new ArrayIterator( $this->get_files() );
        return $iterator;
    }

    /**
     * load_file
     *
     * @access public 
     * @param string $file
     */
    public function load_file( $file ) {
        include_once $file;
    }
}

Usage example:

$parameter = array(
        // define path relative to get_stylesheet_directory()
        // optional, defaults to get_stylesheet_directory()
        'path' => 'includes/plugins',
        // optional, defaults to asterisk »*«
        // matches all files ending with ».php« 
        // and not beginning with »_«, good for quickly deactivating 
        // directories searched are »path« and »subfolders«
        // Additional examples:
        // '{*/,}{[!_],}func-*.php' same as above but for files with a prefix
        // '[!_]*.php' php files in defined »path«, not beginning with »_« 
        'pattern' => '{*/,}[!_]*.php',
        // optional, defaults to 0
        // needed if for example brackets are used
        // more information: http://www.php.net/manual/en/function.glob.php
        'flags' => GLOB_BRACE
    );
// create object
$functionsfileloader = new Functions_File_Loader( $parameter );
// load the files
foreach ( $functionsfileloader as $file ) {
    $functionsfileloader->load_file( $file );
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment