This is actually comes from a specific WordPress issue but there's a more general PHP point behind it which I'm interested to know the answer to.
The WordPress class is along these lines:
class Tribe_Image_Widget extends WP_Widget {
function example_function(){
// do something useful
}
}
Is there any way in PHP that I can replace example_function() from outside the class?
The reason I want to do this is that the class is from someone else's WP plugin (and has several functions in the class) and I want to continue receiving updates to the plugin but I want one of the functions adapted. If I change the plugin, then I'll lose all my own changes each time. SO if I have my own plugin which just changes that one function, I avoid the problem.
It sounds like what you want to do is extend the class, and override that particular function.
Class Your_Tribe_Image_Widget extends Tribe_Image_Widget
{
function example_function() {
// Call the base class functionality
// If necessary...
parent::example_function();
// Do something else useful
}
}
You could probably have an include_once to the target plugin at the top of your file and then extend the class of the target plugin instead of the WP_Widget class:
include_once otherPlugin.php
class My_Awesome_Plugin_Overloaded extends Someone_Elses_Awesome_Plugin{
function example_function(){
return 'woot';
}
}
As long as the method in the existing class hasn't been marked as final, you can just subclass and override it
class My_Tribe_Image_Widget extends Tribe_Image_Widget {
//override this method
function example_function(){
// do something useful
}
}
Related
I have an object with some protected fields and a method that uses them. The method doesn't do exactly what I need it to do, but I cannot change the original code since I am writing an add-on.
Is it somehow possible to extend the class and override the method so that I could call it on predefined objects of the original class? I thought about monkey patching but apparently it is not implemented in php.
You can override a method by extending the parent class, initiating the new class instead of the parent class and naming your method exactly the same as the parent method, that was the child method will be called and not the parent
Example:
class Foo {
function sayFoo() {
echo "Foo";
}
}
class Bar extends Foo {
function sayFoo() {
echo "Bar";
}
}
$foo = new Foo();
$bar = new Bar();
$foo->sayFoo() //Outputs: Foo
$bar->sayFoo() //Outputs: Bar
I hope below stategy will be works. asume that class is Foo and method is bar(). for override bar() method you have to make customFoo class as mentioned below.
class CustomFoo extends Foo{
public function bar(){
parent::bar();
}
}
I dont know actually what you need because you dont have explained in detail. Still I have tried my best. :)
Try creating a child class that extends the base or parent class that the object currently derives from.
Create a new method with exactly the same name as the method in the Parent class and put your logic in there.
Now instantiate your object from your new class, you would have succeeded in overriding that particular method and still have access to the methods and properties of the base class.
Problem is, once you've loaded the class, you can't officially unload it, and you do need to load it in order to extend it. So it's pretty tied up. Your best bet is to either hack the original class (not ideal) or copy paste the original class definition into a new file:
class ParentClass {
//Copy paste code and modify as you need to.
}
Somewhere after the bootstrapping of your framework:
spl_autoload_register(function ($class) {
if ($class == "ParentClass") { //Namespace is also included in the class name so adjust accordingly
include 'path/to/modified/ParentClass.php';
}
},true,true);
This is done to ensure your own modified class will be loaded before the original one.
This is extremely hacky so first check if the framework you're using has native support for doing this.
From what I understand, when a PHP Class is extended, it's constructor is not called? So in the below, the method Options_Page_Template->on_enqueue_scripts() is never actually run -
class Options_Page_Template{
function __construct(){
/** Enqueue scrips and styles for use in this plugin */
add_action('wp_enqueue_scripts', array(&$this, 'on_enqueue_scripts'));
}
function on_enqueue_scripts(){
{ do Whatever here }
}
}
class Options_Home extends Options_Page_Template{
function __construct(){
{ Add various actions here }
}
}
Is there a way of telling Options_Page_Template() to always run it's own __constructor() when it is extended? I know I can use parent::__construct(), but that involves adding the code to all the files that extend the Class.
I also tried the the old-school method of giving the constructor the same name as the Class, but PHP is obviously more clever than that, as it did not work. Thanks.
There's no way. A good rule of thumb for all your code, is to always call parent::__construct for every subclass that overrides the constructor; and explicitly comment within the constructor if you are not, and why.
In general, for functions and con/destructors, if you override something; you are also responsible for calling the parent function.
You must always use parent::__construct() if you are createing a __construct in both classes You do have an option to turn it around. You could have your parent class constructor check for the existence of a custom constructor in the child and run it.
<?php
class Options_Page_Template{
function __construct(){
if (method_exists($this,'__beforeconstruct'))
$this->__beforeconstruct();
echo "construct class<br/>";
if (method_exists($this,'__afterconstruct'))
$this->__afterconstruct();
}
function on_enqueue_scripts(){
}
}
class Options_Home extends Options_Page_Template{
function __beforeconstruct(){
echo "Extended class before<br/>";
}
function __afterconstruct(){
echo "Extended class after<br/>";
}
}
new Options_Home();
?>
output:
Extended class before
construct class
Extended class after
You could do something nasty like define your constructor as final and have a protected init method which extended classes can override but I wouldn't recommend it to be honest.
This way if someone tries to write a constructor in a child class they'll get something like:
PHP Fatal error: Cannot override final method A::__construct() in php shell code on line 5
You probably need to look at a different approach to the way you've organised your classes instead.
class Options_Home extends Options_Page_Template{
function __construct() {
parent::__construct(); // Needs to be first line so the rest of the constructor
// can assume the Options_Page_Template has been constructed.
// Various stuff here for Options_home constructor
}
}
Should work.
Just don't define a constructor the for the extending class.
I'm quite new to OOP and there are a few things I'd like to ask.
I'm writing a plugin for WordPress using OOP and I want to find out how I can allow other plugin developers to extend and redefine certain functions.
I have the main code wrapped in a class as follows and the class is instantiated at the bottom of the file:
class MyPlugin {
// .. methods here ..
public function myMethod(){
// do something
}
}
$myplugin = new MyPlugin;
However, I also want another plugin to be able to rewrite myMethod() by extending the class.
class OtherPlugin extends MyPlugin {
public function myMethod(){
// do something else
}
}
But in order for $myplugin->myMethod() to 'do something else', should I do this to override the $myplugin object:
$myplugin = new OtherPlugin;
Yes, you would want to reload that variable with the new, modified class... unless you pass by reference. Check it out... it's a neat little trick.
Happy coding! =)
I have a parent class, let's say class main { ... }, and an extension of it, let's call it class extension extends main { ... }.
My question is, how would I build another class, called class messages { ... }, which I can use inside the main class and the extended class of main, extension ? Besides the way I know, calling the class messages like this :
$messages = new messages;
$messages->someMethod();
Is there another way without having to do new ... to make the main and extension class inherit the methods inside the messages class ?
AFAIK, PHP does not support multiple inheritance, as others OOP languages do.
So, no, there is NOT another way.
And yes, you should create a property and instantiate the object inside the main class...
class main {
public $messages; // may be "protected" or "private" instead
public __construct()
{
$this->messages = new messages();
}
public do_something()
{
$this->messages->do_something_else();
}
}
However, there are alternatives to simulate a fake multiple inheritance.
An alternative would be: https://stackoverflow.com/a/356431/370290 - But I don't recommend this (even the own author doesn't).
Another alternative: https://stackoverflow.com/a/358562/370290 - IMHO, as weird as the previous one. :-)
And as of PHP 5.4.0 you can also use traits to achieve a "multiple inheritance" effect: http://php.net/manual/en/language.oop5.traits.php - This is very new at the moment.
You can't extend multiple classes and to exten the main class .. only a good thing if you extend from an abstract class.
But what you could do is add it in the construct of your main class like this:
//member variable for class main
public $_message = null;
public function __construct()
{
$this->_message = new Message();
}
Then whenever you need the message class just call $this->_message + the method you need (eg: $this->_message->addMessage())
don't forget to add this in you subclass:
public function __construct()
{
parent::__construct();
}
The problem you seem to have is that you can't do multiple inheritance (class YourClass extends main, messages).
The common feeling is that if you need multiple enheritance, you're doing something wrong in your design.
Every class is responsible for a single thing. A "extension" in this case "IS A" "main", but it is not a "messages", so it should not be a child of that. IF you need messaging capability, there is no 'shame' at all in just calling it like you suggest: you get yourself a nice object that knows how to message, and play with that. There is no real need to do it differently.
If you're looking for alternatives (which you really don't need as far as I can see!) you could make it a class with a bunch of static methods, and just call it like messages::someMethod(), but I think that would be considered an anti-pattern in this case.
Just go with it: messages are created by an object of type message. So you make one, and call the function. In the end, if you ever need big changes (database connection, logging, etc etc) for you messaging, you can do this all in your nice and cosy messaging class. Everyone happy :)
You should create a class inside a class. Just like in this question.
Then, you can use $this->someclass->function.
Note: construct needs to be $this->someclass = new Whatever() too.
i just got some more questions while learning PHP, does php implement any built in plugin system?
so the plugin would be able to change the behavior of the core component.
for example something like this works:
include 'core.class.php';
include 'plugin1.class.php';
include 'plugin2.class.php';
new plugin2;
where
core.class.php contains
class core {
public function coremethod1(){
echo 'coremethod1';
}
public function coremethod2(){
echo 'coremethod2';
}
}
plugin1.class.php contains
class plugin1 extends core {
public function coremethod1(){
echo 'plugin1method1';
}
}
plugin2.class.php contains
class plugin2 extends plugin1 {
public function coremethod2(){
echo 'plugin2method2';
}
}
This would be ideal, if not for the problem that now the plugins are dependable on each other, and removing one of the plugins:
include 'core.class.php';
//include 'plugin1.class.php';
include 'plugin2.class.php';
new plugin2;
breaks the whole thing...
are there any proper methods to doing this?
if there are not, them i might consider moving to a different langauge that supports this...
thanks for any help.
edit:
obviously it is my understanding that is lacking, so here is a
attempt at a clarification.
core.class.php contains anything...
plugin1.class.php contains anything...
plugin2.class.php contains anything...
include 'core.class.php';
include 'plugin1.class.php';
include 'plugin2.class.php';
$core = new core;
$core->coremethod1();//outputs plugin2method1
whereas:
include 'core.class.php';
include 'plugin2.class.php';
$core = new core;
$core->coremethod1();//outputs plugin1method1
I'm interested in any implementation, even one not involving classes
for example
include 'core.php';
//does core stuff
include 'core.php';
include 'plugin1';
//does extended core stuff
include 'core.php';
include 'plugin2';
//does extended core stuff
include 'core.php';
include 'plugin2';
include 'plugin1';
//does very extended core stuff
including a file needs to change the application behavior. for it to have any meaning.
I do not know what this is called either, so point me at the proper naming if there is any.
You are misusing the term "plugin". A plugin is generally a package of code that extends or alters the base functionality of a system - to make actual PHP plugins (which in the PHP world are called extensions) you'd be writing C or C++.
What you're describing here is merely including classes or class trees into the current execution for usage. And there is a way to bring them into the current execution context 'automatically', and that's via the autoload system.
If, after you've read the documentation on autoloading, you are still unsure of how to move forward, comment here and I will help you along.
EDIT
Ok, I see what you're after. You can't do exactly what you're after. When you execute new core; an instance of the class core will be returned - you can't modify that at all.
However, if you are willing to modify how you create instances of core, then I think I have something that could work for you, and it might look something like this.
class core {
public function coremethod1(){
echo 'coremethod1';
}
public function coremethod2(){
echo 'coremethod2';
}
/**
* #return core
*/
final public static function create()
{
// listed in order of preference
$plugins = array( 'plugin2', 'plugin1' );
foreach ( $plugins as $plugin )
{
if ( class_exists( $plugin ) )
{
return new $plugin();
}
}
return new self;
}
}
class plugin1 extends core {
public function coremethod1(){
echo 'plugin1method1';
}
}
class plugin2 extends plugin1 {
public function coremethod2(){
echo 'plugin2method2';
}
}
$core = core::create();
// test what we have
echo get_class( $core ), '<br>'
, $core->coremethod1(), '<br>'
, $core->coremethod2()
;
If your only concern is that not including plugin1 will create an error, then you can resort to autoloading to have plugin2 load plugin1 automatically:
From the comments in the PHP Manual on spl_autoload
// Your custom class dir
define('CLASS_DIR', 'class/')
// Add your class dir to include path
set_include_path(get_include_path().PATH_SEPARATOR.CLASS_DIR);
// You can use this trick to make autoloader look
// for commonly used "My.class.php" type filenames
spl_autoload_extensions('.class.php');
// Use default autoload implementation
spl_autoload_register();
If, however, you are looking for a traits/mixin-like feature, then the answer is no. PHP does not support this as of now. At least not without patching the core or resorting to these two APIs you do not want to use in production code.
The proper way to change how an object behaves at runtime would be to use Decorators:
$class = new BasicCache( new BasicValidators ( new Basic ) );
or Strategy patterns:
$class = new Basic;
$class->setStrategy(function() { return 'foo'} );
echo $class->callStrategy(); // foo
$class->setStrategy(function() { return 'bar'} );
echo $class->callStrategy(); // bar
See http://sourcemaking.com/design_patterns for the most common patterns.
EDIT Here is an example of how to create plugins with decorators. Assume, we have a game of some sort where some non-player characters walk around in a virtual space and greet the main character from time to time. That's all they do right now. We want some variation on how they greet though, which is why we need our plugins/decorators in this scenario.
First we create an interface that defines some methods any object able to greet should have. We don't care about what it does when these methods are invoked on a specific object. We just want to make sure that the methods are available and that they are called with a clearly defined input:
interface GreetInterface
{
public function greet($name);
public function setGreeting($greeting);
}
An interface is basically a contract any implementing object must fulfill. In our case, the contract says, if you are an object that can greet, you have to have two methods. Implement them any way you like, but have these methods.
Let's build our non-player character classes now, implementing this interface
class Dude implements GreetInterface
{
protected $greeting = 'hello';
public function greet($name)
{
return sprintf('%s %s', $this->greeting, $name);
}
public function setGreeting($greeting)
{
$this->greeting = $greeting;
return $this;
}
}
That's pretty straigtforward I guess. The Dude class just defines the two methods from the interface. When greet() is called, it will fetch the string stored in greeting and prepend to the param passed to the greet method. The setGreeting method allows us to change the greeting at runtime. Note: you could add a getter as well (I was just lazy)
Now on to the plugins. We will create an abstract GreetPlugin class to contain some shared boilerplate code, simply because we don't want to duplicate code in our actual plugins. The abstract plugin class will implement the GreetInterface, so we can make sure all subclasses implement the interface too.
Since Dude already implements the interface as well, we could have the plugins extend Dude, but that would be conceptually wrong, because extending creates an is-a relationship, but a plugin is not a Dude.
abstract class GreetPluginAbstract implements GreetInterface
{
protected $inner;
public function __construct(GreetInterface $inner)
{
$this->inner = $inner;
}
public function setGreeting($greeting)
{
$this->inner->setGreeting($greeting);
return $this;
}
public function greet($name)
{
return $this->inner->greet($name);
}
}
The plugin class accepts one argument when initialized: any class implementing the GreetInterface. The TypeHint makes sure, the class fulfills the contract. That's required, because, as you can see in the code, our plugins will need to call the methods in the interface on the class passed through the constructor. If we had extended from Dude, we would now be able to wrap dudes into dudes, which is a bit odd. Another reason for not doing it.
Now on to the first plugin. We want some of our dudes to speak with a fancy french accent, which means they use âccénts all over the place, but cannot pronounce a proper h. Disclaimer: yes, I know that's a cliche. Please bear with my examples
class FrenchPlugin extends GreetPluginAbstract
{
public function greet($name) {
return str_replace(array('h', 'e'), array('', 'é'),
$this->inner->greet($name));
}
}
Since the Plugin extends the abstract plugin, we can now focus on the actual code that modifies how a regular dude would do his greeting. When greet() is called, we call greet() on the wrapped element and then remove all h characters and turn all es into és. Everything else is unmodified abstract behavior.
In another plugin, we want to change the wording of the greeting, so we have some dudes say Heya, instead of just Hello. Just to add some variation.
class EasyGoingPlugin extends GreetPluginAbstract
{
protected $inner;
public function __construct(GreetInterface $inner) {
$this->inner = $inner->setGreeting('heya');
parent::__construct($inner);
}
}
This way we only override the constructor, because the greet method should just return whatever it will be. So we call the setGreeting method on the object passed to this plugin. Because the object has to implement the GreetInterface, we can be sure this works.
Note that I am assigning the return value of setGreeting as the inner object. This is possible because I return $this, whenever setMethod is called. This cannot be enforced through the interface, so you cannot rely on this form the interface. I just added it to show another technique: method chaining.
With two plugins done, we feel we have enough variation. Now we only need a convenient way to create Dudes. For that we create a small class like this:
class DudeBuilder
{
public static function build()
{
$dude = new Dude();
$decorators = func_get_args();
foreach($decorators as $decorator) {
$decorator .= "Plugin";
// require_once $decorator;
$dude = new $decorator($dude);
}
return $dude;
}
}
Note: I always mix up Builder and AbstractFactory, so if the above is a Factory, well, then it's a factory. Check out the design patterns links I gave earlier on ;)
All this Builder does, is create a regular dude and then wrap/decorate it into/with whatever plugins we tell it to use and than return it. Because the builder encapsulates no own state, we make the build method static.
For this example I assume you used the autoloading code I gave right on top. If not, you can include the plugin files in the foreach loop. Lazy loading them only when they are needed will give you a few microseconds faster load times over including them all on top. Hopefully, this also explains what I meant in the various comments when I argued the behavior should not be controlled by a file inclusion. The file inclusion is just a necessity. You cannot use a class that is not know to PHP. But that the class is actually used, is controlled by our code alone, by passing in the plugin names to the build method.
Let's do this now
$regularDude = DudeBuilder::build();
$frenchDude = DudeBuilder::build('French');
$easygoingDude = DudeBuilder::build('EasyGoing');
$frenchEasyGoingDude = DudeBuilder::build('French', 'EasyGoing');
This is effectively the same as doing:
$regularDude = new Dude;
$frenchDude = new FrenchPlugin(new Dude);
$easygoingDude = new EasyGoingPlugin(new Dude);
$frenchEasyGoingDude = new FrenchPlugin(new EasyGoingPlugin(new Dude));
With just two plugins, we can now create three types of Dudes. Let's have them greet you:
echo $regularDude->greet('Yuri'), PHP_EOL,
$frenchDude->greet('Yuri'), PHP_EOL,
$easygoingDude->greet('Yuri'), PHP_EOL,
$frenchEasyGoingDude->greet('Yuri'), PHP_EOL;
// gives
hello Yuri
éllo Yuri
heya Yuri
éya Yuri
We can now create additional plugins to decorate our basic classes with. If for some reason, you decide your game should have talking horses or cars as well, you could also create a class Car or Horse and have it implement the greet interface too and add a Builder for them. You can then reuse the plugins to create French EasyGoing Cars or Horses.
PHP core can be extended with PECL extensions (which are C++, I believe).
Core functions can be overridden (if you have the APD PECL extension installed) with override_function
User functions can be executed with call_user_func.
Maybe if you could explain what you are planning, we'd be able to offer a better answer?
Your code is breaking because plugin2 extends plugin1, and you're not including the plugin1 class. Why not make class plugin2 extend core? That seems to be what you're going for.