2

Hope someone can help, am looking for some suggestions on how to override/replace some functions that are loading in a parent theme and move them into the child theme so we can make alterations to the files themselves in the child theme.

We will "duplicate" the structure and files into the child theme, but can't yet find a way to "unload" the original parent theme files and then load the child theme files we want to alter instead.

Essentially it's all the "require" files listed below that we will duplicate and alter in the child theme, but need to find some way to override the parents functions.php.

We have tried multiple ways to do this but just can't seem to get it to work so far.

THIS IS THE CURRENT PARENT FUNCTIONS.PHP:


<?php
/**
 * moto functions and definitions
 *
 * @package moto
 */
if ( ! function_exists( 'moto_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 for post thumbnails.
 */
function moto_setup() {
    /*
     * Make theme available for translation.
     * Translations can be filed in the /languages/ directory.
     * If you're building a theme based on moto, use a find and replace
     * to change 'moto' to the name of your theme in all the template files
     */
    load_theme_textdomain( 'moto', get_template_directory() . '/languages' );
    // Add default posts and comments RSS feed links to head.
    add_theme_support( 'automatic-feed-links' );
    /*
     * Let WordPress manage the document title.
     * By adding theme support, we declare that this theme does not use a
     * hard-coded <title> tag in the document head, and expect WordPress to
     * provide it for us.
     */
    add_theme_support( 'title-tag' );
    /*
     * Enable support for Post Thumbnails on posts and pages.
     *
     * @link http://codex.wordpress.org/Function_Reference/add_theme_support#Post_Thumbnails
     */
    add_theme_support( 'post-thumbnails' );
    // This theme uses wp_nav_menu() in one location.
    register_nav_menus( array(
        'primary' => esc_html__( 'MOTO Main Menu', 'moto' ),
        'pre_header' => esc_html__( 'Preheader Menu(You have to enable Preheader from MOTO Options panel to view this menu.)', 'moto' )
    ) );
    /*
     * Switch default core markup for search form, comment form, and comments
     * to output valid HTML5.
     */
    add_theme_support( 'html5', array(
        'search-form',
        'comment-form',
        'comment-list',
        'gallery',
        'caption',
    ) );
    /*
     * Enable support for Post Formats.
     * See http://codex.wordpress.org/Post_Formats
     */
    add_theme_support( 'post-formats', array(
        'aside',
        'image',
        'video',
        'quote',
        'link',
    ) );
    // Set up the WordPress core custom background feature.
    add_theme_support( 'custom-background', apply_filters( 'moto_custom_background_args', array(
        'default-color' => 'ffffff',
        'default-image' => '',
    ) ) );
    add_theme_support( 'woocommerce' );

    global $pagenow;
    if ( is_admin() && 'themes.php' == $pagenow && isset( $_GET['activated'] ) ) {
        wp_redirect(admin_url("options-general.php?page=moto-system-status")); // Your admin page URL
        exit();
    }

}
endif; // moto_setup
add_action( 'after_setup_theme', 'moto_setup' );
/**
 * Set the content width in pixels, based on the theme's design and stylesheet.
 *
 * Priority 0 to make it available to lower priority callbacks.
 *
 * @global int $content_width
 */
function moto_content_width() {
    $GLOBALS['content_width'] = apply_filters( 'moto_content_width', 640 );
}
add_action( 'after_setup_theme', 'moto_content_width', 0 );
/**
 * Register widget area.
 *
 * @link http://codex.wordpress.org/Function_Reference/register_sidebar
 */
function moto_widgets_init() {
    register_sidebar( array(
        'name'          => esc_html__( 'Sidebar', 'moto' ),
        'id'            => 'sidebar-1',     
        'description'   => esc_html__( 'Defualt Sidebar', 'moto' ),
        'before_widget' => '<div id="%1$s" class="row no-margin widget %2$s">',
        'after_widget'  => '</div>',
        'before_title'  => '<hr><h4>',
        'after_title'   => '</h4>',
    ) ); 
    register_sidebar( array( 
        'name'          => esc_html__( 'Shop Sidebar', 'moto' ),
        'id'            => 'shopsidebar',       
        'description'   => esc_html__( 'Shop Sidebar Show Only Shop pages', 'moto' ),
        'before_widget' => '<div id="%1$s" class="row no-margin widget %2$s">',
        'after_widget'  => '</div>',
        'before_title'  => '<hr><h4>',
        'after_title'   => '</h4>',
    ) );
    register_sidebar( array(
        'name'          => esc_html__( 'Footer Sidebar - 1', 'moto' ),
        'id'            => 'footer-1',      
        'description'   => esc_html__( 'Footer Sidebar - 1', 'moto' ),
        'before_widget' => '<div class="col-md-3 col-sm-6 text-left">',
        'after_widget'  => '</div>',
        'before_title'  => '<hr><h4>',
        'after_title'   => '</h4>',
    ) );
    register_sidebar( array(
        'name'          => esc_html__( 'Footer Sidebar - 2', 'moto' ),
        'id'            => 'footer-2',      
        'description'   => esc_html__( 'Footer Sidebar - 2', 'moto' ),
        'before_widget' => '<div class="col-md-3 col-sm-6 text-left"><div class="mt_footer_content">',
        'after_widget'  => '</div></div>',
        'before_title'  => '<hr><h4>',
        'after_title'   => '</h4>',
    ) );
}
add_action( 'widgets_init', 'moto_widgets_init' );
/**
 * Implement the Custom Header feature.
 */
require get_template_directory() . '/function/custom-header.php';
/**
 * Custom template tags for this theme.
 */
require get_template_directory() . '/function/template-tags.php';
/**
 * Custom functions that act independently of the theme templates.
 */
require get_template_directory() . '/function/extras.php';
/**
 * Customizer additions.
 */
require get_template_directory() . '/function/customizer.php';
/**
 * Load Jetpack compatibility file. 
 */ 
require get_template_directory() . '/function/jetpack.php';

require_once get_template_directory() . '/include/aq_resizer.php';
require_once get_template_directory() . '/include/moto-sys-req.php';
require_once get_template_directory() . '/include/moto-enqueue.php';
require_once get_template_directory() . '/include/moto-functions.php';
require_once get_template_directory() . '/include/theme_plugin/plugin-activate-config.php';
require_once get_template_directory() . '/include/wordpress-reset.php';

Any suggestions?

Thank you in advance.

4

You can't necessarily replace entire arbitrary files with a child theme.

WordPress will automatically look in the child theme for replacements for the templates in the template hierarchy, as well as a couple of additional files like searchform.php or comments.php, but any other files that the parent theme loads are only replaceable in a child theme if the parent theme author has built them to be. This includes any files included into functions.php or in templates.

For a file to be replaceable by a child theme it must be loaded using supported functions. For example, if a theme (like yours) loads a file like this:

require_once get_template_directory() . '/include/aq_resizer.php';

Then a child theme cannot replace it. This is because the '/include/aq_resizer.php' part of the path is not going through WordPress at all. It's a normal PHP include that WordPress cannot intercept. Additionally, get_template_directory() will only ever be the directory to the parent theme, not the child theme if one is active.

For it to be possible to replace an entire file in a child theme the parent theme must load it with one of these functions:

require_once get_theme_file_path( '/include/aq_resizer.php' );

Because the file path is passed as an argument to get_theme_file_path(), rather than just being a concatenated string passed directly to PHP, it's possible for the function to look in the child theme first, which it does.

For templates, if the parent theme uses get_template_part(), like this:

get_template_part( 'partials/content' );

Then the child theme can create partials/content.php to replace it, but if the parent theme uses include partials/content.php, then it's not possible to replace with a child theme.

get_theme_file_path() is much newer (introduced in 4.7) than get_template_part() (introduced in 3.0), so is much less common, and non-existent in older themes. It's also not widely known.

In your code the parent theme doesn't use either of these methods, so it's just not possible to replace the entire file. This means that you will need to replace individual functions one-by-one. The method for doing this will depend on how the function is used.

If the parent theme hooks the function with add_action()

If the parent theme hooks the function you want to replace with add_action(), then you can replace the function by creating a new version of the function in your child theme (with a different name), unhooking the original function with remove_action(), then hooking your new function with add_action():

remove_action( 'hook_name', 'parent_theme_function_name' );
add_action( 'hook_name', 'child_theme_function_name' );

If the parent theme uses the function in a template file

If the parent theme has a function you want to replace, and that function is used in a template file, then you will need to create a new version of the function in your child theme (with a different name) then replace the template file in your child theme, then in your child theme's version of the template replace the original function usage with your new function.

If the parent theme function is pluggable

Parent themes are loaded before the child theme. This means that it's possible for theme developers to make functions replaceable by child themes by wrapping then in a function_exists() check. This means that you can replace the function definition with your own function and it won't cause a conflict, because the parent theme won't try to re-define it if you already have.

Your code has an example of this: the moto_setup() function is inside this check:

if ( ! function_exists( 'moto_setup' ) ) :
endif;

This makes the moto_setup() function 'pluggable', which means that you can define a moto_setup() function in your child theme and the parent theme will use it instead.

Whether or not other functions in your theme are 'pluggable' this way is impossible to say without seeing the code.

Conclusion

  • It's not necessarily possible to replace whole files in child themes. Outside of a handful of core WordPress templates, the parent theme has to explicitly support files being replaceable.

  • If the theme has not made functions' files replaceable, there are several options for replacing functions depending on how the parent theme was constructed.

  • Depending on how the parent theme was constructed it is entirely possible that there are parts of it that are impossible to replace with a child theme without replacing huge chunks of the theme that you otherwise don't want to change. This can reach a point where you're better off just forking the theme and creating a new one.

  • Thank you Jacob, we've tried multiple options to achieve what we want with no success so far, but your suggestions/clarification were a big help. – CMYK Jul 30 '18 at 0:42
  • Thanks for a great, no-frills overview of such a complicated yet necessary topic that for some reason is entirely missing from the Codex. I'm in a similar situation, and your answer only leaves me with one remaining question - in the context of Wordpress, what does it mean to fork a theme? Does it refer to changing the theme information so as to prevent the theme from updating itself, and then making changes to that theme directly, or is it something more? – Hashim May 29 at 2:44
  • 1
    "Fork" just means to copy the theme code and make a new theme. If you're not using version control then this is as simple as renaming the theme folder to something unique, so that it doesn't receive updates for the existing theme. – Jacob Peattie May 29 at 4:09
  • In defence of the codex though (or the handbook, which is more current), you should be able to replace all template files in the child theme. The only reason you wouldn't is if the parent theme was not built correctly. The handbook, rightly, does not suggest that any other files are necessarily replaceable. – Jacob Peattie May 29 at 4:11
0

Simply use

function moto_setup() { 
  // Your new moto_setup function
}

without checking if the function exists or not. That function will override the moto_setup() declared in the parent theme.

  • Yeah, tried that, along with many other combinations and just can't get it to work – CMYK Jul 31 '18 at 3:58
0

OK, after weeks of working with the developers of Moto Theme Pro v3, they are unable to get the child theme working as it should.

The theme doesn't adhere to "best practice" coding, the child theme is unable to override the parent theme without extensive additional coding in the functions.php file and overall is a bit of a mess.

We've given up on it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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