tags:

views:

136

answers:

6

Hi all, I have a big problem. How to get called subclass method from a superclass. Please execute below code.

class Model {

    public function render(){
     echo '<br />class: '.get_class($this).' -- function: '.__FUNCTION__;
    }
}

class Product extends Model {

    public function show(){
     $this->render();
    }
}

class User extends Model {

    public function index(){
     $this->render();
    }
}


$p = new Product();
$u = new User();

echo $p->show();
echo $u->index();
result :
class: Product -- function: render
class: User -- function: render

How to get subclass method name instead of render?

Thanks.

+2  A: 

You can get that information using debug_backtrace().

I am curious as to why you want this - it could indicate a flaw with your design if you need this for anything other than debugging.

Greg
+1 for design flaw
Philippe Gerber
A: 

Couldn't you simply change it to the following?

class Model {

    protected $_type='unspecified';

    public function render(){
        echo '<br />class: '.$this->_type.' -- function: '.__FUNCTION__;
    }
}

class Product extends Model {

    public function __construct(){
        $this->_type = 'product';
    }

    public function show(){
        $this->render();
    }
}

class User extends Model {

    public function __construct(){
        $this->_type = 'user';
    }

    public function index(){
        $this->render();
    }
}

Or is there any reason why that doesn't work for you?

André Hoffmann
Thank you for tried. But condition is i don't want to use variable or params /__FUNCTION__/ in render method ?
+1  A: 

The __FUNCTION__ thingie is replaced at compile-time by the name of the function it is in. So no matter how your object model is structured, you'll get the function where __FUNCTION__ is met by PHP's preprocessor.

The best you can do here, if you want to know the name of the method being called, is to add it as a parameter to the method render() :

class Model {
    public function render($methodName){
        echo '<br />class: '.get_class($this).' -- function: '. $methodName;
    }
}

And add the name in the method calls :

class Product extends Model {
    public function show(){
        $this->render(__FUNCTION__);
    }
}

class User extends Model {
    public function index(){
        $this->render(__FUNCTION__);
    }
}
Nicolas
Thank you for tried. But condition is i don't want to use variable or params /__FUNCTION__/ in render method !!!
Then I'm afraid you can't, without much refactoring :/
Nicolas
+1  A: 

Could you go into detail as to why you need this?

I'm not sure what you are trying to do, but especially when you are developing a PHP framework you should restrict yourself to the basic rules of inheritance.

Maybe you could illustrate a little better what you're trying to achieve with this.

André Hoffmann
A: 

You could move the logic which works out what you are rendering into the superclass, e.g.:

class Model {

    public function render($type){
        echo '<br />class: '.get_class($this).' -- function: '.$type;
    }

    public function show() {
        $this->render('show');
    }

    public function index() {
        $this->render('index');
    }
}

class Product extends Model {
 public function show(){
        //some stuff
        parent::show();
    }
}

class User extends Model {

    public function index(){
        parent::index();
    }
}
Tom Haigh
A: 

I don't really recommend this to you, but what you could do is throw an exception and catch it right away.

Then you can use the stack trace of this exception to find out which function called your render method.

I know that it works, but both performancewise and codingwise this is not a good option.

UPDATE:

<?php

class bla {
    function test1() {
     $this->test2();
    }

    function test2() {
     $method = "";
     try {
      throw new Exception("bla");
     } catch(Exception $e) {
      $trace = $e->getTrace();
      $method = $trace[1]['function']);
     }

     echo $method; //will echo test1
    }
}

$blub = new bla();
$blub->test1();

Hope you get what I'm trying to illustrate.

André Hoffmann