How to call a overrided method in child, on the parent class - php

I've got a class
class foo {
function do_something() {
load();
}
function load() {
//things
echo 'load from foo';
}
}
And another class that extends foo (a child class):
class bar extends foo {
function load() {
//things
echo 'load from bar (child)';
}
}
And then:
$obj = new bar();
What I want to know is how can I call $obj->do_something() such that the method uses the child 'load' method instead of the method declared in the foo class.
So, I want the output to be:
$obj->do_something();
Output: load from bar (child)
Is this possible with PHP?
Thanks!

You need to qualify the object context with $this. Unlike some other languages, PHP requires that you qualify the instance explicitly with $this for all method calls from within an object.
class foo {
function do_something() {
// load();
$this->load();
}
function load() {
echo 'load from foo';
}
}
class bar extends foo {
function load() {
echo 'load from bar (child)';
}
}
$obj = new bar();
$obj->do_something();
In your code (merely calling load()) the language was looking for a globally defined function named load, which of course wouldn't work (or in worse cases, would but incorrectly)
As another answer points out, you must similarly qualify static methods though the use of self or static (which I would suggest you read up on to understand the binding differences)
From an inheriting class, in an overriding method, you can also use parent to invoke the parent classes' definition of the method:
class bar extends foo {
function load() {
parent::load(); // right here
echo 'load from bar (child)';
}
}
This will invoke the parent's version of the load method, and continue execution with the child classes' definition.

I would recommend use abstract function if you want to have such a tight coupling of methods. it's going to require high maintenance and you are creating some tight couplings between classes.
i would recommend creating an abstract function in the parent that each of the children will implement with it's own logic.
Even then if you want change your parent class function to this
function do_something(){
if(method_exists($this, 'test')){
$this->test();
}
}

you can use abstract class and abstract method:
abstract class Foo{
function test() {
$this->method();
}
abstract function method();
}
class Test extends Foo {
function method() {
echo 'class Test';
}
}
$test = new Test();
$test->test();

Try this
class foo {
function do_something() {
static::load();
}
function load() {
//things
echo 'load from foo';
}
}
class bar extends foo {
function load() {
//things
echo 'load from bar (child)';
}
}
$obj = new bar;
$obj->do_something();

Related

PHP: Access Method in sub-class

I want to know how to access a method i a sub-class of a class when I'm in another sub-class of that same class...
For example:
class foo {
}
class bar extends foo {
public function something() {
//do something here
}
}
class soap extends foo {
$this->something(); //This is the method I wanna call...
}
As you can see I wanna access a subclass's method from another sub class.
How do I do this in PHP?
You can do it directly, but only if soap is also a subclass of bar:
class soap extends bar {
public function someFunction()
{
$this->something(); // This will work
}
}
If it's not, you still have an option: obtain an instance of bar and then call the method on it:
class soap extends foo {
public function someFunction(bar $bar)
{
$bar->something(); // This will also work
}
}
Barring that, there's not much else you can do. Since bar is not in soap's inheritance chain, there is no way to reference something using only $this from within any of soap's methods.

PHP - How to call function from an upstream object

I have a DB interface object, DBI, that requires authentication. I have an object, foo, that doesn't extend anything. I also have a class bar that extends the DBobject If I have an instance of foo that is a member of bar thus:
$b->$f=new foo;
How can I call somefunction() in $b from a function inside the foo class? I've tried making the somefunction() static, but I don't want the authentication info sprinkled throughout my code. And if I try having foo extend the DBI or bar classes, I wind up with an issue including the files and my foo __construct function fails because the bar class is not found. Is there another construct similar to extends/parent:: that I can use with objects that are just instances amongst each other?
The way that I've done this in the past, is create the Foo object within the Bar object within the __construct(). Then utilize the __call magic method to intercept the methods and see where it is. So the code could look something like this:
public function __call($sMethod, $aArgs) {
if(method_exists($this, $sMethod){
return call_user_func_array(array($this, $sMethod), $aArgs);
}
} elseif(method_exists($this->foo, $sMethod)) {
return call_user_func_array(array($this->foo, $sMethod), $aArgs);
}
}
public function __construct() {
$this->foo = new foo();
}
Then you can call the functions from either foo or bar, even though they are not extended. Just a though, maybe there is an easier way to do this.
** EDIT **
The benefit to this is you don't need to specify whether or not you are calling a method from foo or from bar, they will just "work".
** EDIT **
Based on the comments, you want to do this, correct? Because based on the code below, if you run it it works correctly.
class foobar {
public function test() {
echo 'This is a test';
}
}
class foo extends foobar {
}
class bar {
}
$bar = new bar();
$bar->foo = new foo();
$bar->foo->test();
or the alternative:
class foobar {
public function test() {
echo 'This is a test';
}
}
class foo extends foobar {
}
class bar {
public function testFooBar() {
$this->foo->test();
}
}
$bar = new bar();
$bar->foo = new foo();
$bar->testFooBar();
Both work at long as you know the property name you are setting for the object.
In addition to call_user_func and call_user_func_array, if you want to access methods and properties of the container object (not parent class), you need a reference to it. Here is a similar post.

Calling an overridden parent method

In the sample code below, the method test() in parent class Foo is overridden by the method test() in child class Bar. Is it possible to call Foo::test() from Bar::test()?
class Foo
{
$text = "world\n";
protected function test() {
echo $this->text;
}
}// class Foo
class Bar extends Foo
{
public function test() {
echo "Hello, ";
// Cannot use 'parent::test()' because, in this case,
// Foo::test() requires object data from $this
parent::test();
}
}// class Bar extends Foo
$x = new Bar;
$x->test();
Use parent:: before method name, e.g.
parent::test();
See parent
parent::test();
(see Example #3 at http://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php)
Just set visibility levels at $text property.
private $text = "world\n";
Calling a parent method may be considered bad practice or code smell and may indicate programming logic that can be improved in a way, that the child doesn't have to call the parent. A good generic description is provided by Wikipedia.
An implementation without calling parent would look like:
abstract class Foo
{
$text = "world\n";
public function test() {
$this->test_child();
echo $this->text;
}
abstract protected function test_child();
}// class Foo
class Bar extends Foo
{
protected function test_child() {
echo "Hello, ";
}
}// class Bar extends Foo
$x = new Bar;
$x->test();
Judging by your comments on the pastebin, I'd say you can't.
Maybe if you had something like this?
class foo {
public function foo($instance = null) {
if ($instance) {
// Set state, etc.
}
else {
// Regular object creation
}
}
class foo2 extends foo {
public function test() {
echo "Hello, ";
// New foo instance, using current (foo2) instance in constructor
$x = new foo($this);
// Call test() method from foo
$x->test();
}
}

Accessing Static Variable from child->child class php

I have the following setup:
<?php
class core {
static $var1;
}
class parent extends core {
function getStatic() {
return parent::$var1;
}
}
class child extends parent {
function getStatic() {
// I want to access core static var, how can i do it?
//return parent::$var1;
}
}
?>
I need to be able to use parent::$var1 but from within class child.. is this possible? Am I missing something?
Just reference it as self... PHP will automatically go up the chain of inheritance until it finds a match
class core {
protected static $var1 = 'foo';
}
class foo extends core {
public static function getStatic() {
return self::$var1;
}
}
class bar extends foo {
public static function getStatic() {
return self::$var1;
}
}
Now, there will be an issue if you don't declare getStatic in bar. Let's take an example:
class foo1 extends core {
protected static $var1 = 'bar';
public static function getStatic() {
return self::$var1;
}
}
class bar1 extends foo1 {
protected static $var1 = 'baz';
}
Now, you'd expect foo1::getStatic() to return bar (and it will). But what will Bar1::getStatic() return? It'll return bar as well. This is called late static binding. If you want it to return baz, you need to use static::$var1 instead of self::$var1 (PHP 5.3+ only)...
core::$var1 seems best for your needs...
The biggest problem here is that you're using the keyword parent as a class name. This makes it completely ambiguous whether your calls to parent::$var1 are intended to point to that class, or to the parent of the calling class.
I believe, if you clean this up, you can achieve what you want. This code prints 'something', for example.
class core {
static $var1 = 'something';
}
class foo extends core {
function getStatic() {
return parent::$var1;
}
}
class bar extends foo {
function getStatic() {
// I want to access core static var, how can i do it?
return parent::$var1;
}
}
$b = new bar ();
echo $b->getStatic ();
It also works if you use core:: instead of parent::. Those two will behave differently, though, if you declare a static $var1 inside of the foo class as well. As is it's a single, inherited variable.

Require a method in parent class to be called in PHP

As the title states, I'm trying to make a method in a parent class required. Although, I suppose it could be any class. For instance:
class Parent
{
function foo ()
{
// do stuff
}
}
class Child extends Parent
{
function bar ()
{
// do stuff after foo() has ran
}
}
Basically, I want foo() to be required to run or Child class doesn't run and returns an error or redirects to a different page. I could call the function, but I'm wondering If I can make it a requirement when extending the parent class.
If you leverage abstract classes and methods, you can force subclasses to implement the missing methods.
abstract class ParentClass
{
public function foo ()
{
// do stuff
$this->bar();
}
abstract protected function bar();
}
class Child extends ParentClass
{
protected function bar()
{
// does stuff
}
}
Subclasses that don't implement bar() will generate a fatal error.
What you should probably do is override Parent::foo() and then call the parent method in the overridden method like so:
class Parent
{
function foo ()
{
// do stuff
}
}
class Child extends Parent
{
function foo ()
{
if(!parent::foo()) {
throw new Exception('Foo failed');
}
// do child class stuff
}
}
Why not just set a boolean in function foo() that acts as a flag. Check to see if it has been set in the child class/functions, and you're all set.
Have the child call the function from the parent in the construct.
class Child extends Parent
{
function bar ()
{
// do stuff after foo() has ran
}
function __construct(){
parent::foo();
}
}
As already mentioned, it sounds like you want foo() to be abstract, forcing child classes to override it.
Any class containing an abstract class in PHP requires your parent class to be abstract too. This means it can't be instantiated (constructed), only derived / sub-classed. If you try to instantiate an abstract class the compiler will issue a fatal error.
http://php.net/manual/en/language.oop5.abstract.php
See the code in Peter Bailey's answer.
If you're not actually initializing any code within parent class you should use an object interface. Interface methods have to be implemented or the script will throw a fetal error.
More information on them can be found: http://us3.php.net/interface.
I think this might be the only way of implementing such functionality, as I don't think there is a built in solution.
class Parent
{
public $foo_accessed = FALSE;
function foo ()
{
$this->foo_accessed=TRUE;
// do stuff
}
}
class Child extends Parent
{
function bar ()
{
if($this->foo_accessed==TRUE) {
// do stuff after foo() has ran
} else {
// throw an error
}
}
}
Do not depend on other methods. Make sure they've ran.
class Parent
{
function foo()
{
// do stuff
}
}
class Child extends Parent
{
private function bar()
{
// do child class stuff
}
public function doFooBar()
{
parent::foo();
$this->bar();
}
}
Following approach will only ever complain after all processing has been done - however if that is fair to you it will definately make sure foo() has been called in the parent class or otherwise trigger a condition that you can act upon.
class DemandingParent {
private $hasFooBeenCalled = false;
public function foo() {
$this->hasFooBeenCalled = true;
/* do Stuff */
}
public function __destruct() {
if (!$this->hasFooBeenCalled) {
throw new Exception("Naughty Child! Call your parent's foo b4 you speak up!");
}
}
}

Categories