Require a method in parent class to be called in PHP - 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!");
}
}
}

Related

How to access the method from trait after changing its visibility in the exhibiting class? [duplicate]

here is the class structure. I want Observer:callme() to be callable from Children too.
class Observer
{
protected callme()
{
}
}
class Parent extends Observer
{
function createChild()
{
$this->callme(); // this is OK
return new Child ($this);
}
}
class Child
{
private $this myParent;
public function __constructor ($myParent)
{
$this->myParent = $myParent;
}
public function __destroy()
{
$this->myParent->callme(); // FAIL!
}
}
so how to make FAIL work? (without making it public, because its only for used inside "Parent" and its "Children")
The problem is that a protected method is only accessed from the same class or the class children. What you can do is extend your Child class from Parent, like this:
class Child extends Parent
{
public function __constructor ()
{
parent::__constructor();
}
public function __destroy()
{
$this->callme(); // Should work!
}
}
Or just change the method to public.
And, btw, is this code some kind of real code that you will use? That constructor receiving the parent object seems to be so wrong. What are you trying to accomplish?
protected means that you can call that method only from the same class and from subclasses. What you want to do is not possible. The protected keyword would be pointless if you could call these methods from everywhere.
In C++ there is the friend keyword to achieve what you want: you could define Child as friend of Observer (this has to be done from within Observer), and then you can call all methods in Observer (including private and protected) from within methods of Child. But such a keyword does not exist for PHP.
My comment on your question explains why it doesn't work. This answer shows a way to accomplish what you asked based upon your clarification that MyChild should not extend MyParent.
This is a hack example that makes it work by exploiting the fact that php doesn't care if you call protected methods on other instances than yourself as long as you share the ancestor of the protected method.
I had to change the code some to make it valid php. __constructor is not the name of a php constructor.
hacky.php
<?php
class Observer
{
protected function callme()
{
echo 'I was called from ' . get_called_class(), PHP_EOL;
}
}
class MyParent extends Observer
{
public function createMyChild()
{
$this->callme(); // this is OK
return new MyChild ($this);
}
}
class MyChild extends Observer // hackey extends
{
private $myMyParent;
public function __construct($myMyParent)
{
$this->myMyParent = $myMyParent;
$this->myMyParent->callme();
}
}
$p = new MyParent;
$c = $p->createMyChild();
Result:
$ php hacky.php
I was called from MyParent
I was called from MyParent
I think I found the solution:
class Parent extends Observer
{
function createChild()
{
$this->callme(); // this is OK
return new Child (function() { $this->callme(); });
}
}
class Child
{
private $gatewayFunction;
public function __constructor (Closure $gatewayFunction)
{
$this->gatewayFunction = $gatewayFunction;
}
public function __destroy()
{
$this->gatewayFunction->__invoke();
}
}
Who is going to crap himself? :)

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

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();

Can I make a function child of another Class without extends Class?

My Class is independant from another Class.
Inside my Class, a function is doing the same but refined job as a function in another Class. Can I use parent:: function_in_another_class() and get my function join that parent funciton's job flow?
No.
In PHP you can only extend from none or one class. As you write both classes are independent to each other, there is no information where to find the one or the other class.
But what you're looking for is probably this:
class A
{
function myFunction() {}
}
class B
{
private $a;
public function __construct(A $a)
{
$this->a = $a;
}
public function myFunction()
{
$this->a->myFunction();
}
}
If any class method already doing the same thing why would you bother call join it?
You can not do it. If you want the same job flow best way to do is to instantiate the other class and invoke that very same method. Thats why we use OOP.
See the example,
interface Fable()
{
public function f();
}
class OtherClass implements Fable
{
public function f()
{
// job flow
}
}
class MyClass
{
private $fable;
public function __construct(Fable $f)
{
$this->fable = $f;
}
public function method1($args){
return $this->fable->f($args);
}
}
If the current class is a child of another class, yes, you can. parent references to the parent class.
From php.net:
<?php
class A {
function example() {
echo "I am A::example() and provide basic functionality.<br />\n";
}
}
class B extends A {
function example() {
echo "I am B::example() and provide additional functionality.<br />\n";
parent::example();
}
}
$b = new B;
// This will call B::example(), which will in turn call A::example().
$b->example();
?>
The best you can do here is to extend Class B from Class A
Class B extends Class A
But, you can also:
class ClassA {
function do_something($args) {
// Do something
}
}
class ClassB {
function do_something_inclassA($args) {
classA::do_something($args);
}
}
Important: calling classa::do_something(); is a static call, in other words with error reporting E_STRICT you will get a static notice warning because function do_something() is not static function do_something()
Also, calling this function statically (i.e. classa::do_something()) means that class a's function cannot refer to $this within it

Are there pure virtual functions in PHP like with C++

I would have thought lots of people would have wondered whether this is possible but I can't find any duplicate questions... do correct me.
I just want to know whether PHP offers pure virtual functions. I want the following
class Parent {
// no implementation given
public function foo() {
// nothing
}
}
class Child extends Parent {
public function foo() {
// implementation of foo goes here
}
}
Thanks very much.
You can create abstract functions, but you need to declare the parent class as abstract, too:
abstract class Parent {
// no implementation given
abstract public function foo();
}
class Child extends Parent {
public function foo() {
// implementation of foo goes here
}
}
Declare the method as abstract in the Parent class:
abstract public function foo();
There are abstract classes!
abstract class Parent {
// no implementation given
abstract public function foo();
}
}
class Child extends Parent {
public function foo() {
// implementation of foo goes here
}
}
Yes, that type of solution is possible, it's called polymorphism, you can do it without declaring an abstract class or an interface.

PHP: How to call function of a child class from parent class

How do i call a function of a child class from parent class?
Consider this:
class whale
{
function __construct()
{
// some code here
}
function myfunc()
{
// how do i call the "test" function of fish class here??
}
}
class fish extends whale
{
function __construct()
{
parent::construct();
}
function test()
{
echo "So you managed to call me !!";
}
}
That's what abstract classes are for. An abstract class basically says: Whoever is inheriting from me, must have this function (or these functions).
abstract class whale
{
function __construct()
{
// some code here
}
function myfunc()
{
$this->test();
}
abstract function test();
}
class fish extends whale
{
function __construct()
{
parent::__construct();
}
function test()
{
echo "So you managed to call me !!";
}
}
$fish = new fish();
$fish->test();
$fish->myfunc();
Okay, this answer is VERY late, but why didn't anybody think of this?
Class A{
function call_child_method(){
if(method_exists($this, 'child_method')){
$this->child_method();
}
}
}
And the method is defined in the extending class:
Class B extends A{
function child_method(){
echo 'I am the child method!';
}
}
So with the following code:
$test = new B();
$test->call_child_method();
The output will be:
I am a child method!
I use this to call hook methods which can be defined by a child class but don't have to be.
Technically, you cannot call a fish instance (child) from a whale instance (parent), but since you are dealing with inheritance, myFunc() will be available in your fish instance anyway, so you can call $yourFishInstance->myFunc() directly.
If you are refering to the template method pattern, then just write $this->test() as the method body. Calling myFunc() from a fish instance will delegate the call to test() in the fish instance. But again, no calling from a whale instance to a fish instance.
On a sidenote, a whale is a mammal and not a fish ;)
Ok, well there are so many things wrong with this question I don't really know where to start.
Firstly, fish aren't whales and whales aren't fish. Whales are mammals.
Secondly, if you want to call a function in a child class from a parent class that doesn't exist in your parent class then your abstraction is seriously flawed and you should rethink it from scratch.
Third, in PHP you could just do:
function myfunc() {
$this->test();
}
In an instance of whale it will cause an error. In an instance of fish it should work.
Since PHP 5.3 you can use the static keyword to call a method from the called class. i.e.:
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // Here comes Late Static Bindings
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>
The above example will output:
B
source: PHP.net / Late Static Bindings
I'd go with the abstract class....
but in PHP you don't have to use them to make it work. Even the invocation of the parent class' constructor is a "normal" method call and the object is fully "operational" at this point, i.e. $this "knows" about all the members, inherited or not.
class Foo
{
public function __construct() {
echo "Foo::__construct()\n";
$this->init();
}
}
class Bar extends Foo
{
public function __construct() {
echo "Bar::__construct()\n";
parent::__construct();
}
public function init() {
echo "Bar::init()\n";
}
}
$b = new Bar;
prints
Bar::__construct()
Foo::__construct()
Bar::init()
i.e. even though class Foo doesn't know anything about a function init() it can call the method since the lookup is based on what $this is a reference to.
That's the technical side. But you really should enforce the implementation of that method by either making it abstract (forcing descendants to implement it) or by providing a default implementation that can be overwritten.
I know this is probably a bit late for you, but I had to get around this problem as well. To help others understand why this is sometimes a requirement, here's my example:
I'm building an MVC framework for an application, I have a base controller class, which is extended by each individual controller class. Each controller will have different methods, depending on what the controller needs to do. Eg, mysite.com/event would load the event controller. mysite.com/event/create will load the event controller and call the 'create' method. In order to standardise the calling of the create function, we need the base controller class to access the methods of the child class, which will be different for every controller. So code-wise, we have the parent class:
class controller {
protected $aRequestBits;
public function __construct($urlSegments) {
array_shift($urlSegments);
$this->urlSegments = $urlSegments;
}
public function RunAction($child) {
$FunctionToRun = $this->urlSegments[0];
if(method_exists($child,$FunctionToRun)) {
$child->$FunctionToRun();
}
}
}
Then the child class:
class wordcontroller extends controller {
public function add() {
echo "Inside Add";
}
public function edit() {
echo "Inside Edit";
}
public function delete() {
echo "Inside Delete";
}
}
So the solution in my case was to pass the child instance itself back to the parent class as a parameter.
The only way you could do this would be through reflection. However, reflection is expensive and should only be used when necessary.
The true problem here is that a parent class should never rely on the existence of a child class method. This is a guiding principle of OOD, and indicates that there is a serious flaw in your design.
If your parent class is dependent on a specific child, then it cannot be used by any other child classes that might extend it as well. The parent-child relationship goes from abstraction to specificity, not the other way around. You would be much, much better off to put the required function in the parent class instead, and override it in the child classes if necessary. Something like this:
class whale
{
function myfunc()
{
echo "I am a ".get_class($this);
}
}
class fish extends whale
{
function myfunc()
{
echo "I am always a fish.";
}
}
It's very simple. You can do this without abstract class.
class whale
{
function __construct()
{
// some code here
}
/*
Child overridden this function, so child function will get called by parent.
I'm using this kind of techniques and working perfectly.
*/
function test(){
return "";
}
function myfunc()
{
$this->test();
}
}
class fish extends whale
{
function __construct()
{
parent::construct();
}
function test()
{
echo "So you managed to call me !!";
}
}
Even if this is an old question, this is my solution using ReflectionMethod:
class whale
{
function __construct()
{
// some code here
}
function myfunc()
{
//Get the class name
$name = get_called_class();
//Create a ReflectionMethod using the class and method name
$reflection = new \ReflectionMethod($class, 'test');
//Call the method
$reflection->invoke($this);
}
}
The benefit of using the ReflectionMethod class is that you could pass an array of arguments and check which one is needed in the method you are calling:
//Pass a list of arguments as an associative array
function myfunc($arguments){
//Get the class name
$name = get_called_class();
//Create a ReflectionMethod using the class and method name
$reflection = new \ReflectionMethod($class, 'test');
//Get a list of parameters
$parameters = $reflection->getParameters()
//Prepare argument list
$list = array();
foreach($parameters as $param){
//Get the argument name
$name = $param->getName();
if(!array_key_exists($name, $arguments) && !$param->isOptional())
throw new \BadMethodCallException(sprintf('Missing parameter %s in method %s::%s!', $name, $class, $method));
//Set parameter
$list[$name] = $arguments[$name];
}
//Call the method
$reflection->invokeArgs($this, $list);
}
From whale instance you can't call this function. but from fish instance you can do
function myfunc()
{
static::test();
}
If exists a method in the child class, method will be called from the parent class (as an optional callback if exists)
<?php
class controller
{
public function saveChanges($data)
{
//save changes code
// Insert, update ... after ... check if exists callback
if (method_exists($this, 'saveChangesCallback')) {
$arguments = array('data' => $data);
call_user_func_array(array($this, 'saveChangesCallback'), $arguments);
}
}
}
class mycontroller extends controller
{
public function setData($data)
{
// Call parent::saveChanges
$this->saveChanges($data);
}
public function saveChangesCallback($data)
{
//after parent::saveChanges call, this function will be called if exists on this child
// This will show data and all methods called by chronological order:
var_dump($data);
echo "<br><br><b>Steps:</b><pre>";
print_r(array_reverse(debug_backtrace()));
echo "</pre>";
}
}
$mycontroller = new mycontroller();
$mycontroller->setData(array('code' => 1, 'description' => 'Example'));
That's a little tricky
if you talk about OOP concepts that's not possible
but if you use your brain then it can be :)
OOP say's you cannot call child class function from parent class and that's correct because inheritance is made of inheriting parent functions in child
but
you can achieve this with Static class
class Parent
{
static function test()
{
HelperThread::$tempClass::useMe();
}
}
class child extends parent
{
// you need to call this. functon everytime you want to use
static function init()
{
HelperThread::$tempClass = self::class;
}
static function useMe()
{
echo "Ahh. thank God you manage a way to use me";
}
}
class HelperThread
{
public static $tempClass;
}
that's just a solution to my problem.
i hope it helps with your problem
Happy Coding :)
what if whale isn't extended? what would that function call result in? Unfortunately there is no way to do it.
Oh, and does a fish extend a whale? A fish is a fish, a whale is a mammal.

Categories