How to override a widget in a child theme in WordP

2020-07-10 12:02发布

问题:

I want to make a simple modification in a PHP file located here in my parent theme:

wp-content\themes\sailing\inc\widgets\gallery\tpl\base.php

So I created the same folder structure in my child theme and did the modification I need in this file. I also copied/pasted all the PHP files needed to declare this widget.

wp-content\themes\sailing\inc\widgets\widgets.php  
wp-content\themes\sailing\inc\widgets\gallery\gallery.php

wp-content\themes\sailing-child\inc\widgets\widgets.php  
wp-content\themes\sailing-child\inc\widgets\gallery\gallery.php

What am I missing here ?

回答1:

WordPress child themes are not working this way. The only files that you can override by using the same path in your child themes are the "basic" files: index.php, page.php, style.css... Mostly the template files.

When it comes to overriding functions or classes in a child theme. You've several ways to handle it:

  1. re-declaring the functions/classes
  2. duplicating the functions/classes

But it depends on how your theme is built and if it's "child theme" ready. Let's have a look with your widget issue.

If you open your widget declaration file within your parent theme, you'll see something like:

class Widget_Name extends WP_Widget {
...
CODE OF THE WIDGET
...

See: https://codex.wordpress.org/Widgets_API

The ideal case is you don't see the above lines first but:

if(!class_exists('Widget_Name')) {
    class Widget_Name extends WP_Widget {
    ...
    CODE OF THE WIDGET
    ...

Which means, you can just copy/past your file and that'll work just fine, you widget will override the parent one and no error will be thrown as the parent widget won't be executed. That's the "child theme ready" theme. Note that it's the same with functions (if(!function_exists('function_name')).

Don't forget to call your file from your child-theme/functions.php file as it won't be called by default.

Like:

require_once('path/to/your/widget_class.php');

Other way, if you don't have a class_exists call is to just duplicate the file, call it with the require_once. You should see an error as you're defining 2 times the same class. PHP won't let that happen, fatal error.

Just rename:

class Widget_Name2 extends WP_Widget {

And somewhere (most of the time at the end) of your file, look for register_widget( and edit the class name:

register_widget( 'Widget_Name2' );

That's not the most handy way as you'll have 2 times the same widget but that does work though.



回答2:

So since @2Fwebd answer is kinda incomplete (as marked in the comment), here is a more complete answer (just to make it clearer than an answer and its comment. ) I've suggested an edit for his answer, but while it isn't accepted, here is a more complete answer :

WordPress child themes are not working this way. The only files that you can override by using the same path in your child themes are the "basic" files: index.php, page.php, style.css... Mostly the template files.

When it comes to overriding functions or classes in a child theme. You've several ways to handle it:

  1. re-declaring the functions/classes
  2. duplicating the functions/classes

But it depends on how your theme is built and if it's "child theme" ready. Let's have a look with your widget issue.

If you open your widget declaration file within your parent theme, you'll see something like:

class Widget_Name extends WP_Widget {
...
CODE OF THE WIDGET
...

See: https://codex.wordpress.org/Widgets_API

The ideal case is you don't see the above lines first but:

if(!class_exists('Widget_Name')) {
    class Widget_Name extends WP_Widget {
    ...
    CODE OF THE WIDGET
    ...

Which mean, you can just copy/past your file and that'll work just fine, you widget will override the parent one and no error will be thrown as the parent widget won't be executed. That's the "child theme ready" theme. Note that it's the same with functions (if(!function_exists('function_name')).

Don't forget to call your file from your child-theme/functions.php file as it won't be called by default.

Like:

require_once('path/to/your/widget_class.php');

Other way, if you don't have a class_exists call is to just duplicate the file, call it with the require_once. You should see an error as you're defining 2 times the same class. PHP won't let that happen, fatal error.

Just rename:

class Widget_Name2 extends WP_Widget {

Then, change your id_base in your parent::_construct to a unique id (like this :

parent::__construct( 'new_uniq_id', 'name of your widget', ...)

And somewhere (most of the time at the end) of your file, look for register_widget( and edit the class name:

register_widget( 'Widget_Name2' );

That's not the most handy way as you'll have 2 times the same widget but that does work though.

Hope it helps someone.