I have a Wordpress parent theme that my child theme is extending a lot of functionality from. My issue though is that when I want to use or extend a class from the Parent them in my child theme folder structure, I get errors of "class is not defined" or "class not found"
What is the correct way to use classes from the parent theme?
Here is an example of one of the classes:
class MyNewClass extends ReadAndDigestWidget {}
And that class will call more classes inside it that are from the parent theme.
Any help in understanding Wordpress and php more deeply is greatly appreciated!
PHP is not an OOP language by design so the results can be trivial at times. Here is a basic example of how inheritance works in PHP
class ChildTheme extends ParentTheme {
function parentDropDownMenu(){
parent::dropDownMenu();
//do additionall stuff
}
}
theme = new ParentTheme();
$theme->dropDownMenu(); // will call the parent function directly
$theme->parentDropDownMenu(); // will call the function override
Typically I wouldn't even override my parent's class methods in PHP but merely extend the class if I don't have complete control over the parent class. What if an upgrade takes place in wordpress and you override a must needed upgrade?
Related
I'm working on a WordPress project. There is a child theme implemented, and the parent one has a class to show authors' links. We have implemented a feature to support multiple authors per post, then we have our own methods for showing the proper links (not a single-author link, but many links joined depending on the authors count).
The complete scenario:
Theme: Newspaper
File: td_module.php (includes/wp_booster/td_module.php)
Class: td_module (abstract, many other classes in the parent theme inherit this one)
Method: get_author()
There are many other classes inheriting td_module in the parent theme, hence I cannot just extend td_module in my child theme since every change to the parent theme would be lost when the theme gets updated
Somehow I need to expand this method to show something different, but I don't want to change the method in the td_module class: even when it would be the fastest / most secure solution, this code would be overwritten on every theme upgrade.
This method is widely used in the Theme, that's why is that important to add some code here.
Why I still have some hope: There is a WP filter td_wp_booster_module_constructor, being called on the constructor of td_module class. The problem is that this class doesn't have any other filter on the method for showing the authors, but just the td_wp_booster_module_constructor filter call on the constructor.
The base PHP (and OOP) question: is it possible to expand / replace a method by using this filter in the constructor somehow?
Some code to clarify:
abstract class td_module {
...
function __construct($post, $module_atts = array()) {
...
// Can I change the get_author behavior by using this filter?
apply_filters("td_wp_booster_module_constructor", $this, $post);
// This is the only filter available in the entire class!
...
}
...
function get_author() {
$buffy = '';
// Code for generating author link ($buffy .= ...)
...
// This function doesn't have any apply_filter, there are no filters available
return $buffy;
}
}
Basically, you can't modify a class definition at runtime. The fact that you have a filter available on the constructor is a red herring and really not relevant.
Either the get_author() has some facility to change it's behaviour from outside class definition (in Wordpress parlance, filter and action hooks), or you simply cannot do it.
Outside of Wordpress, in an application with a proper dependency inversion container, you should probably do this by decorating the class and having all class consumer use the decorated class.
But since you have no way of telling class consumers to use one or the other, and a lot of code out of your control is presumably instantiating the class directly, something like this simply won't fly.
There is one extension, Runkit, that allows for changes of behaviour and definitions at runtime. there is even a method to modify a method definition. although I have not tried the extension, and do not know if it runs in an updated PHP runtime.
Note it is almost certainly a very bad idea to do this on production code, and that since you are dealing with code out of your control anyway you can't even be sure you would be changing the definition before it's used for the first time.
I've also found a repo for Runkit that says that it almost works on PHP 7, if you are absolutely convinced on going that way.
Your issue is that the base class is vendor code which you did not write.
So create a class in between your classes extending it!
Job done!
<?php
class SomeWordpressCrap
{
public function doSomething()
{
return 'something';
}
}
class YourAwesomeNewClass extends SomeWordpressCrap
{
public function doSomething()
{
return 'something better!';
}
}
class OneOfYourExistingClasses extends YourAwesomeNewClass
{
}
UPDATE So it turns out the OneOfYourExistingClasses is also vendor code, so the above solution will not work.
However! You could use Roave's "Better Reflection" lib, which you can find here https://github.com/Roave/BetterReflection
This will allow you to "Change the body of a function or method to do something different", which I believe is exactly what you need. Good luck!
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 ?
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:
re-declaring the functions/classes
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.
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:
re-declaring the functions/classes
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.
Can I instantiate a child when when the parent is instantiated?
I am trying to use inheritance to override a parent function. But I can't just create a new instance of the child because the variable for the parent constructor are not present at the time.
Basically, I am trying to extend a Wordpress plugin and I do not want to change the core plugin files. When the plugin calls for the parent object to be created, I want the the child to instantiate when that happens to override one of the parent functions.
Example:
return new WC_Subscription( $subscription_id );
My class extends WC_Subscription, and My class does one thing and that is override one function through inheritance.
For my latest website I'm trying to use OOP. I'm using the project to develop my understanding of this technique. Previously I would 'include' a functions folder that contains various php files labelled things like image.upload.functions.php and general.error.handling.functions.php etc.
However, this time I'm using classes wherever possible.
I have just read that in order to use a parents methods (in an extended class) you must run the parents constructor however I haven't done this and my project seems to work ok.
So.. I have a class called Form Validation
I have another class called Process Login that extends Form Validation.
My Form Validation class does things like test a password strength to make sure it is strong enough, check whether a user is in the database etc.
I extend Form Validation with a Registration class and a Forgotten Passowrd class.
Should I be putting:
parent::_construct();
..in the constructor of each of the extended classes?
Could someone explain 'simply' the reasons why we do OR do not do this? And whether it's something I should be doing?
Many thanks :-)
Here's the link to official documentaion: constructors and destructors
And here's the quote:
Note: Parent constructors are not called implicitly if the child class defines a constructor. In order to run a parent constructor, a call to parent::__construct() within the child constructor is required. If the child does not define a constructor then it may be inherited from the parent class just like a normal class method (if it was not declared as private).
Calling parent constructor is NOT necessary. And, in general, it is not called implicitly, if You have defined constructor in Your own child class. But, if in the parent constructor You have a nice piece of logic or functionality, that You don't want to lose, then call parent's constructor from the child's one.
You call parent::__construct() (watch that there are two underscores) if you want to reuse the functionality of the constructor from the class you're extending.
The reuse of code is a main reason for inheritance in OOP. So if there is any algorithm in your parent class that you want to use, you have to call parent::__construct().
If you're extending the parent's constructor, you also have to call it before (or after) your own additions, e.g. like this
class A extends B {
public __constructor() {
parent::__construct();
// Your own code
}
}
If you don't want to use any of your parents' constructor functions, you don't inherit from that parent constructor - but I assume that in most cases you want to.
If I have:
class main {
//hello
}
class child1 {
function love($v) {
}
}
class child1 {
function hate($v) {
}
}
function __autoload($file) {
include_once($file . '.php');
}
Is there a way I can set this up so that I can do
$main = new main();
$main->hate();
$main->love();
and still
keep them as seperate classes, and
use the autoloader for the child classes?
I think even if the child classes extend the main class, that I can't access the child methods from the parent class. Is that correct? If so, is there something like a reverse extends which injects the child class properties/methods into the main class?
Update 1
Okay, so it looks like there's nothing straight-up built in to php to acheive this (Thanks everyone for the answers). How about I write up my goal and maybe you or someone you know can suggest a way to acheive this?
I would like to have one main class. I then have a set of subclasses which operate like grouped function libraries. Each of these subclasses is __autoloaded when needed to acheive an end. So for example, I have a subclass of file upload & processing functions, a subclass of database interaction functions, a subclass of xml processing functions, and so on.
I want to use this like: call the main class at the top of every script $main = new main();. Then, later on, an image processing method from a child class (which has not been loaded) is needed, so I call
$main->methodFromChildClass(); which will cause that child class to be autoloaded and the method used.
I am hoping in this way to optimize which files are loaded, and keep things well organized. I'm fairly new to oop. Is there a way to achieve this type of organization now?
There is not such a language construct (not in PHP anyway - other languages offer mechanisms like mixins, which kind of work like that), but there is a technique to do something like that called inversion of control.
class Main {
public $child;
public function __construct($child) {
$this->child = $child;
}
}
$main = new Main(
new Child1()
);
$main->child->love();
This is very simplified example, that does not show full potential of this technique. For more information search for 'inversion of control' and 'design patterns'
I think you're interested in is called traits, which are not available in the current release of PHP, but will be in the next version, and is available in trunk if you check out the source from SVN and compile yourself.
For more information, see http://wiki.php.net/rfc/traits
Not to my knowledge, kinda violates the whole concept of OO programming. The main class should have the methods and properties which need to be used by all child classes of the main class, and then the child classes have methods and properties that only they will need to use.
I suppose if you really wanted to, you could store a child class object inside a main class object and do something like $main->child->hate(); but that would be sort of recursive, because if the child extends the parent class, and if the child was created and stored on the parent's construct, then you would wind up with an infinite loop of the parent creating the child which creates a new parent inside it which creates a new child which creates a new parent ad infinitum. Though you could get around that by simply having a method that would have to be manually called in order to create and store the child.
With the code you gave, it's not going to work.
If child1 extends main, you can call hate() method only by creating instance from the child1 class or by introducing the hate() method in the main() class.
Child classes inherit methods from Mother classes but the reverse is not true.
What exactly are you trying to do ?
You can use magic to simulate that behaviour, but "clean" is something different
class main {
public function __call ($name, $args) {
switch ($name) {
case 'hate':
$x = new child1;
return $x->hate();
break;
case 'love':
$x = new child2;
return $x->hate();
break;
}
}
}