late static binding | without modifying parent class with `static` keyword - php

I have following parent and child class.
class Parent_class {
protected static function method_one() {
echo "I am in Parent_class in method_one";
}
protected function execute() {
static::method_one();
}
public function start() {
$this->execute();
}
}
class Child_class extends Parent_class {
protected static function method_one() {
echo "I am in Child_class in method_one";
}
}
$obj = new Child_class();
$obj->start();
Result - it is calling Child class method.
The result is as expected because of static late binding is supported in php5.3 with the already reserved keyword static.
But the issue is, I do not have write access to Parent class, hence I can not use static while calling methode_one and hence it is not performing late static binding.
Is there any way out using which I can access overriding method ?
Parent class is a defined library, and I can not modify it.
Way out is to modify the parent class or drop this thought completely, but can you suggest any other alternative ?

Why not implement execute or start in child class?

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? :)

Determine the name of the calling class (parent or child) in parent class method

Looking for a clean way to determine the class (in this case, either parent or child class) of the method that calls a method in the parent class.
I thought late static binding could handle this, but seems like that only really works for calling a static method directly, and not from within an instantiated object's method.
Consider the following:
abstract class ParentClass {
public function parentMethod() {
self::_log("parent.non.static");
}
public static function parentStatic() {
self::_log("parent.static");
}
public static function getClassName() {
return __CLASS__;
}
protected static function _log($key) {
$prefix = 'graphite.key.prefix';
$class = static::getClassName(); // gets the object's class, not calling class
$g_key = "{$prefix}.{$class}.{$key}";
echo "{$g_key} \n";
// Graphite::increment($g_key);
}
}
class ChildClass extends ParentClass {
public function childMethod() {
self::_log("child.non.static");
}
public static function childStatic() {
self::_log("child.static");
}
public static function getClassName() {
return __CLASS__;
}
}
$obj = new ChildClass;
$obj->childMethod(); // graphite.key.prefix.ChildClass.child.non.static
$obj->parentMethod(); // graphite.key.prefix.ChildClass.parent.non.static
ParentClass::parentStatic(); // graphite.key.prefix.ParentClass.parent.static
ChildClass::childStatic(); // graphite.key.prefix.ChildClass.child.static
Looking for a clean way to get the class that calls the _log() method without having to pass it in as a parameter. Doesn't have to be static at all, but I was playing around with the late static binding, because I thought that would work, but it just gets the name of the instantiated object, not the child/parent class of the method that calls the _log() method :-/
Edit:
Just to be clear, I'm after getting the class name of the method that called _log() from within the instantiated object (like parentMethod() and childMethod()) Don't care if _log() is static or not. If that makes it easier, fine. But the static ParentClass::parentStatic() and ChildClass::childStatic() were just to show late static bindings and what I figured might work, but not from calling within an instantiated object
http://php.net/manual/en/function.get-called-class.php
class One {
public static function test() {
echo get_called_class() . PHP_EOL;
}
}
class Two extends One {}
One::test();
Two::test();
Output:
One
Two
Also, according to the top comment in the docs static::class also works as of PHP 5.5.
get_class will get the class name of a class instance. This can also be called on $this within a class. If you have a class that extends/implements another, $this will refer the the instantiated class, meaning the child class.
Another option is to use debug_backtrace to get the stack of functions that lead up to where you currently are. You can parse the returned array to get whatever you need including line numbers, classes, functions, methods, whatever.

self::method() call uses parent method instead of called class

I have two classes:
class JController{
public static function getInstance()
{
//some source, not important...
self::createFile();//
}
public static function createFile()
{
// this is base class method
}
}
class CustomController extends JController{
public static function createFile()
{
// this is overriden class method
}
}
And I am trying to call static method on derived class which calls parents method and not overriden. Is it expected behaviour?
That's how I try to use it:
$controllerInstance = CustomController::getInstance();
My question is: why doesn't CustomController::getInstance() call on CustomController::createFile()?
That is expected behavior. Before php 5.3 static methods will only call the method from the first definition in the hierarchy. 5.3+ has late static binding support and with that the ability to use the method directly on the child class. To do this you need to use the static keyword instead of self:
public static function getInstance()
{
//some source, not important...
static::createFile();//
}
Late Static Binding:
use
static::createFile();
instead of
self::createFile();

How do I call a static child function from parent static function?

How do I call child function from parent static function ?
In php5.3 there is a built in method called get_called_class() to call child method from parent class. But my server is running with php 5.1.
Is there any way can do this ?
I want to call it from a static function . So that I can not use "$this"
So i should use "self" keyword.
Below example my parent class is "Test123" , from the parent class static function "myfunc" am trying to call child class function like this "self::test();"
abstract class Test123
{
function __construct()
{
// some code here
}
public static function myfunc()
{
self::test();
}
abstract function test();
}
class Test123456 extends Test123
{
function __construct()
{
parent::__construct();
}
function test()
{
echo "So you managed to call me !!";
}
}
$fish = new Test123456();
$fish->test();
$fish->myfunc();
Edit: What you try to achieve is not possible with PHP 5.1. There is no late static bindings PHP Manual in PHP 5.1, you need to explicitly name the child class to call the child function: Test123456::test(), self will be Test123 in a static function of the class Test123 (always) and the static keyword is not available to call a static function in PHP 5.1.
Related: new self vs new static; PHP 5.2 Equivalent to Late Static Binding (new static)?
If you are referring to a static parent function, then you need to explicitly name the parent (or child) for the function call in php 5.1:
parentClass::func();
Test123456::test();
In PHP 5.3 you can do this instead with the static keyword PHP Manual to resolve the called class' name:
static::func();
static::test();
If those are non-static, just use $this PHP Manual:
$this->parentFunc();
$this->childFunc();
Or if it has the same name, use parent PHP Manual:
parent::parentFunc();
(which is not exactly what you asked for, just putting it here for completeness).
Get_called_class() has been introduced for very specific cases like to late static bindings PHP Manual.
See Object Inheritance PHP Manual
I suspect you are a bit confused abuot parent / child, class / object and function / method.
IonuČ› G. Stan has provided the explanation of how to invoke a method which is not declared in a parent class (which as he says should be abstract or implement the __call() method).
However if you mean how do invoke a method which has been overridden in a child class from the parent, then it is not possible - nor should it be. Consider:
Class shape {
...
}
Class circle extends shape {
function area() {
}
}
Class square extends shape {
function area() {
}
}
If it is your intent to call the area method on an instance of 'shape' (which does not have an area method) then which child should it use? Both the child methods would depend on properties which are not common / not implemented by the shape class.
try this:
<?php
class A {
public static function newInstance() {
$rv = new static();
return $rv;
}
public function __construct() { echo " A::__construct\n"; }
}
class B extends A {
public function __construct() { echo " B::__construct\n"; }
}
class C extends B {
public function __construct() { echo " C::__construct\n"; }
}
?>

Access parent properties in child using $this

I am trying to create a simple MVC my personal use and I could really use an answer to this simple question
class theParent extends grandParent{
protected $hello = "Hello World";
public function __construct() {
parent::__construct();
}
public function route_to($where) {
call_user_func(array("Child", $where), $this);
}
}
class Child extends theParent {
public function __construct() {
parent::__construct();
}
public function index($var) {
echo $this->hello;
}
}
$x = new theParent();
$x->route_to('index');
Now Child::index() this throws a fatal error: Using $this when not in object context but if I were to use echo $var->hello, it works just fine.
I know I can use $var to access all properties in the parent, but I would rather use $this.
By writing call_user_func(array("Child", $where), $this) you are calling the method statically. But as your method isn't static you need some kind of object instance:
call_user_func(array(new Child, $where), $this);
Documentation on callback functions.
You don't have an instance of Child to call a non-static method upon when you're doing $x->route_to('index'); The way you're calling the method, without having made an instance first, is implied static.
There are two ways to correct it. Either make the Child class's methods static:
class Child extends theParent {
public function __construct() {
parent::__construct();
}
static public function index($var) {
echo self::$hello;
}
}
...or make an instance of the child class for the parent to use:
class theParent extends grandParent{
protected $hello = "Hello World";
private $child = false
public function __construct() {
parent::__construct();
}
public function route_to($where) {
if ($this->child == false)
$this->child = new Child();
call_user_func(array($this->child, $where), $this);
}
}
Of course, both of these samples are rather generic and useless, but you see the concept at hand.
$this gives you access to everything visible/accessible in the current object. That can either be in the class itself (this) or any of it's parents public or protected members/functions.
In case the current class overrides something of a parent class, you can access the parent method explicitly using the parent keyword/label, whereas you add :: to it regardless if it is not a static method.
Protected variables exist only once, so you can not use parent to access them.
Is this info of use?

Categories