Get called class name in Another class - php

we have one class
class A
{
// I am using class B here
public function whatever()
{
$class_b = new B;
$class_b->show_caller();
}
}
and other
class B
{
public function show_caller()
{
// show me the caller class (should output "A")
}
}
I need to get the caller class name.
P.S. Inheritance is not an option!

Pass class A as a parameter to B::show_caller() and output it's class name using get_class():
class A
{
// I am using class B here
public function whatever()
{
$class_b = new B;
$class_b->show_caller($this);
}
}
class B
{
public function show_caller($class)
{
echo get_class($class);
}
}

We can't provide the knowledge about of where your method is executing to method's class without parameters. Late static binding will work only with inheritance, so it's not your case. The only approach, I can give you, is to use your IDE ability to find method usage in your project (ctrl+mouse1 in PhpStorm). If you're not using any IDE - it's a time to start.

Related

PHP Traits: How to circumvenient constructors or force them to be called?

Have a look at the following trait:
trait PrimaryModelRest {
use RestController;
protected $primaryModel;
public function __construct() {
$mc = $this->getPrimaryModelClass();
try {
$this->primaryModel = new $mc();
if(!($this->primaryModel instanceof Model)) {
throw new ClassNotFoundException("Primary Model fatal exception: The given Class is not an instance of Illuminate\Database\Eloquent\Model");
}
} catch (Exception $e) {
throw new WrongImplementationException("Primary Model Exception: Class not found.");
}
}
/**
* #return string: Classname of the primary model.
*/
public abstract function getPrimaryModelClass();
// various functions here
}
As you can see the trait makes sure that the using class holds a certain model instance and it implements certain methods. This works as long as the implementing class does not override the constructor.
So here is my question: I want to make sure that either the constructor is called or a better solution, such that I can instantiate this model on initialization.
Please make in answer which respects Multiple inheritance as well es Multi-Level inheritance.
I think you are trying to make the trait do a job it is not designed for.
Traits are not a form of multiple inheritance, but rather "horizontal reuse" - they're often described as "compiler-assisted copy-and-paste". As such, the job of a trait is to provide some code, so that you don't have to copy it into the class manually. The only relationship it has is with the class where the use statement occurs, where the code is "pasted". To aid in this role, it can make some basic requirements of that target class, but after that, the trait takes no part in inheritance.
In your example, you are concerned that a sub-class might try to access $primaryModel without running the constructor code which initialises it, and you are trying to use the trait to enforce that; but this is not actually the trait's responsibility.
The following definitions of class Sub are completely equivalent:
trait Test {
public function foo() {
echo 'Hello, World!';
}
}
class ParentWithTrait {
use Test;
}
class Sub inherits ParentWithTrait {
}
vs:
class ParentWithMethodDefinition {
public function foo() {
echo 'Hello, World!';
}
}
class Sub inherits ParentWithMethodDefinition {
}
In either case, class Sub could have its own definition of foo(), and by-pass the logic you'd written in the parent class.
The only contract that can prevent that is the final keyword, which in your case would mean marking your constructor as final. You can then provide an extension point that can be overridden for sub-classes to add their own initialisation:
class Base {
final public function __construct() {
important_things(); // Always run this!
$this->onConstruct(); // Extension point
}
protected function onConstruct() {
// empty default definition
}
}
class Sub {
protected function onConstruct() {
stuff_for_sub(); // Runs after mandatory important_things()
}
}
A trait can also mark its constructor as final, but this is part of the code being pasted, not a requirement on the class using the trait. You could actually use a trait with a constructor, but then write a new constructor as well, and it would mask the trait's version completely:
trait Test {
final public function __construct() {
echo "Trait Constructor";
}
}
class Noisy {
use Test;
}
class Silent {
use Test;
public function __construct() {
// Nothing
}
}
As far as the trait is concerned, this is like buying a bottle of beer and pouring it down the sink: you asked for its code and didn't use it, but that's your problem.
Crucially, though, you can also alias the methods of the trait, creating a new method with the same code but a different name and/or a different visibility. This means you can mix in code from traits which declare constructors, and use that code in a more complex constructor, or somewhere else in the class altogether.
The target class might also use the "final + hook" pattern:
trait TestOne {
final public function __construct() {
echo "Trait TestOne Constructor\n";
}
}
trait TestTwo {
final public function __construct() {
echo "Trait TestTwo Constructor\n";
}
}
class Mixed {
final public function __construct() {
echo "Beginning\n";
$this->testOneConstructor();
echo "Middle\n";
$this->testTwoConstructor();
echo "After Traits\n";
$this->onConstruct();
echo "After Sub-Class Hook\n";
}
use TestOne { __construct as private testOneConstructor; }
use TestTwo { __construct as private testTwoConstructor; }
protected function onConstruct() {
echo "Default hook\n";
}
}
class ChildOfMixed extends Mixed {
protected function onConstruct() {
echo "Child hook\n";
}
}
The trait hasn't forced the Mixed class to implement this pattern, but it has enabled it, in keeping with its purpose of facilitating code reuse.
Interestingly, the below code doesn't work, because the as keyword adds an alias, rather than renaming the normal method, so this ends up trying to override the final constructor from Mixed:
class ChildOfMixed extends Mixed {
use TestTwo { __construct as private testTwoConstructor; }
protected function onConstruct() {
$this->testTwoConstructor();
echo "Child hook\n";
}
}
Use a base class, this will let you handle the trait as a parent.
<?php
trait StorageTrait
{
public function __construct()
{
echo "Storage Trait";
}
}
class StorageAttempt
{
use StorageTrait;
public function __construct()
{
parent::__construct();
echo " - Storage Attempt";
}
}
abstract class StorageBase
{
use StorageTrait;
}
class MyStorage extends StorageBase
{
public function __construct()
{
parent::__construct();
echo ' - My Storage';
}
}
new StorageAttempt(); // won't work - will trigger error
new MyStorage(); // will display "Storage Trait - My Storage"
Also if you are using traits you can also work with properties and getters & setters.
Example: A Storage trait involves that a Storage Engine will be used. You can add the storageEngine property and its getters and setters. (with or without Type Hinting)
interface StorageEngineInterface{}
trait StorageTrait
{
/**
* #var StorageEngineInterface
*/
protected $storageEngine;
/**
* #return StorageEngineInterface
*/
public function getStorageEngine(): StorageEngineInterface
{
return $this->storageEngine;
}
/**
* #param StorageEngineInterface $storageEngine
*/
public function setStorageEngine(StorageEngineInterface $storageEngine)
{
$this->storageEngine = $storageEngine;
return $this;
}
}
Note: this is just an explanation so you can better understand how Traits work
UPDATE
To avoid conflict you can use aliases for trait methods. This way you can use both constructors (from trait and from extended class) you can do the following
class DifferentStorage
{
public function __construct()
{
echo ' diff ';
}
}
class MyDifferentStorage extends DifferentStorage
{
use StorageTrait {
StorageTrait::__construct as otherConstructor;
}
public function __construct()
{
parent::__construct();
self::otherConstructor();
}
}
You could use the interface injection pattern: implement an interface iPrimaryModelRest into the same class that uses the trait PrimaryModelRest:
interface iPrimaryModelRest {
public function init();
public abstract function getPrimaryModelClass();
}
The class that uses the trait woud look like this:
class cMyClass implements iPrimaryModelRest {
use PrimaryModelRest;
}
Then, whenever the class is instantiated (not only autoloaded) you could call a special factory-like initialisation function like this:
class cMyApp {
public function start() {
/** #var cMyClass $oClass */ // enlighten IDE
$oClass = $this->init(new cMyClass);
}
public function init($oClass) {
if ($oClass instanceof iPrimaryModelRest) {$oClass->init();}
if ($oClass instanceof whateverinterface) {
// pass optional stuff, like database connection
}
}
}
The interface is used to determine the capabilities of the class, and sets data/runs corresponding functions. If I'm not mistaken then this pattern is called a Service Locator.
I needed a trait for database connection. To avoid using the __construct in a trait, I've used a magic getter instead:
trait WithDatabaseConnection
{
public function __get(string $name)
{
if ($name === 'pdo') {
return App::make(\PDO::class);
}
trigger_error("Property $name does not exist.");
return null;
}
}
class Foo {
use WithDatabaseConnection;
public function save() {
$this->pdo->query('...');
}
}

Dynamic binding in static method php

class A
{
static function get_name_derived_class()
{
//This function must return the name of the real class
//Is it possible without insert a methon in B class?
{
}
class B extends A
{
}
B::test()
I'd like to have a static methon in base class which returns the name of real (derived) class, without insert a specific method in it. is it possible?
thanx
<?php
class A
{
static function test()
{
return get_called_class();
}
}
class B extends A
{
}
echo B::test();
Requires PHP >= 5.3.0. See PHP's manual entry on Late Static Bindings

Calling parent method of inherited class from base class

The following example does not work because when parent is called in class A, php looks for the parent class of class A but it doesn't exist. I would rather this line to call Test() in class B.
Is this possible?
(I know this seems like a stupid example but it has a practical application)
abstract class A {
function CallParentTest()
{
return call_parent_method('Test');
}
}
abstract class B extends A {
function Test()
{
return 'test passed';
}
}
class C extends B {
function Test()
{
return $this->CallParentTest();
}
}
$object = new C();
echo $object->Test();
Thanks!
EDIT
I changed the parent keyword to the made up method call_parent_method because I think that may have been confusing people. I know there is no way to do this using the keyword.
Just as David Harkness pointed out, I am trying to implement the Template Method pattern but instead of using two different method names, I'm using one. B::Test() will be the default method unless substituted with alternate functionality.
You can use reflection to bypass the natural calling order for overridden methods. In any context simply create a ReflectionMethod for the method you'd like to call and invoke it. You don't need to do this from the class itself, but you will need to call setAccessible(true) if the method isn't public.
class A {
public function bypassOverride() {
echo "Hi from A\n";
$r = new ReflectionMethod('B', 'override');
$r->invoke($this);
}
}
class B extends A {
public function override() {
echo "Hi from B\n";
}
}
class C extends B {
public function override() {
echo "Hi from C\n";
$this->bypassOverride();
}
}
$c = new C;
$c->override();
The output from this is
Hi from C
Hi from A
Hi from B
You could make bypassOverride() more generic and move it to a helper class if you need to do this a lot.
Is this possible?
No.
It makes no sense to use the parent keyword except in child classes. It's only purpose is to be used by child classes to call methods that it as overridden. Think about multi-level parent calls where a child calls its parent's method of the same name and, in turn, that parent calls its parent's method of the same name.
webbiedave is correct regarding parent, but it looks like you're trying to implement the Template Method pattern where the abstract base class calls a method that subclasses are expected to implement. Here's an example that demonstrates a horrible way to handle errors in your applications.
abstract class ExceptionIgnorer {
public function doIt() {
try {
$this->actuallyDoIt();
}
catch (Exception $e) {
// ignore the problem and it might go away...
}
}
public abstract function actuallyDoit();
}
class ErrorThrower extends ExceptionIgnorer {
public function actuallyDoIt() {
throw new RuntimeException("This will be ignored");
}
}
$thrower = new ErrorThrower;
$thrower->doIt(); // no problem
Here doIt() is the template method as it defines the overall algorithm to follow.

Is there any polymorphism in PHP?

Suppose both base and son class have a method method_1,
and there's another method method_2 of base.
inside base::method_2,how can I point $this->method_1 to base::method_1 no matter whether $this is a instance of base or son?
If I understand you correctly, you want something like this:
<?php
class base {
public function method1() {
echo "base:method1\n";
}
public function method2() {
if(get_class($this) == 'base') {
$this->method1();
}
else {
parent::method1();
}
echo "base:method2\n";
}
}
class son extends base {
public function method1() {
echo "son:method1\n";
}
}
$obj = new son();
$obj->method2();
where the call to method2 would always use the base version of the method1.
The best way I could do it is as above, but this code won't work since base has no parent. I'm pretty sure what you're trying to do isn't possible.
This is the error you will get:
PHP Fatal error: Cannot access parent:: when current class scope has no parent in
This will do what you want. Props to dbers for the example code (even if his didn't quite work).
<?php
class base {
public function method1() {
echo "base::method1\n";
}
public function method2() {
if (get_parent_class($this) === FALSE) {
echo get_class($this)." has no parent\n";
$this->method1();
} else {
echo get_class($this)." has parent\n";
call_user_func(array(get_parent_class($this), 'method1'));
}
}
}
class son extends base {
public function method1() {
echo "son::method1\n";
}
}
$b = new base();
$b->method2();
$s = new son();
$s->method2();
?>
Outputs:
base has no parent
base::method1
son has parent
base::method1
Make the function private:
<?php
class A
{
public function __construct()
{
$this->foo();
$this->bar();
}
private function foo() { echo "A::foo()\n"; }
public function bar() { echo "A::bar()\n"; }
}
class B extends A
{
public function foo() { echo "B::foo()\n"; }
public function bar() { echo "B::bar()\n"; }
}
new B();
?>
The output is:
A::foo()
B::bar()
Yes it does. It's singular (one parent).
son->method_1 can add to or override ALL of base->method_1 functionality.
son->method_1 can simply add an additional function, and utilize the rest of the functionality of it's parent's instance of method_1
So calling $this->method_1 would use base->method_1, and son->method_1 as long as what you want to use from base isn't overridden in son.
If you call a method that doesn't exist in your subclass, PHP will traverse the class hierarchy until it finds an ancestor class which implements the function you want. This means that if your son class doesn't implement method_2, PHP will automatically look for the nearest ancestor which does. In your case, it will call method_2 of base as you want.
If you are overriding the method_2 in your son class, and you want to do your own implementation of method_2 and also call the base::method_2 implementation then you can use the parent keyword:
class son extends base {
public function method_2() {
parent::method_2();
//do son::method_2()-specific stuff here
}
}
You can't chain parent calls together, so if base was a subclass of GrandparentClass you couldn't do something like this:
parent::parent::method_2(); // trying to call grandparent::method_2
// but this call will fail
But you can directly refer to ancestor classes by name, so this would work:
GrandparentClass::method_2();
And just to take it a little further, there is also a function called class_parents() which returns an array of every ancestor class your class inherits from. This could help if you wanted to go back, say, two ancestors, but you didn't know its specific name for some reason, you could still call the function using eval().
For example, this code would call GrandparentClass::method_2() without directly referencing the class by name in your code:
$parents = class_parents($this);
eval(end($parents) . "::method_2();");
Hope that helps.

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