# Calling methods of parent/ancestor classes in PHP5

- Thread: https://externals.io/message/7933
- Original archive: https://news-web.php.net/php.internals/7933
- Started by Brad Fisher on 2004-02-17T20:01:20+00:00
- Messages: 2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #7933 — Brad Fisher — 2004-02-17T20:01:20+00:00

URL: https://externals.io/message/7933#7933

Since you can no longer assign to $this in PHP5, how would one call a
method defined in a particular ancestor class that has been overridden
by the current class or a more recent ancestor?  In PHP4 doing this was
hackish, but worked.

For example:

class A {
  function foo() {
    echo "A::foo";
    // Do stuff with $this (not a static method)
  }
}

class B extends A {
  function foo() {
    echo "B::foo";
  }
}

class C extends B {
  function bar() {
    // Inside C, i should be able to do the following since $this is an
instance of A:
    A::foo();
  }
}

class D {
  function bar() {
    $c = new C;
    // I'd like to call the A::foo method of C here...
    //    In PHP4, I could do something like:
    $othis = &$this;
    $this = &$c;
    A::foo();
    $this = &$othis;
  }
}

How would one emulate the same sort of functionality as in D::bar with
PHP5?  The best I've been able to figure out is to build the appropriate
code in a method and eval it: (add the following method to class A)

  function call_user_method_array($method, $args = null) {
    if (is_array($method))
      $method = $method[0] .'::'. $method[1];
    else
      $method = '$this->'. $method;

    $code = 'return '. $method .'(';

    if (isset($args)) {
      $n = count($args);
      if ($n >= 1) {
        $code .= '$args[0]';
        for ($i = 1; $i < $n; ++$i) {
          $code .= ',$args['.$i.']';
        }
      }
    }

    $code .= ');';

    return eval($code);
  }

Then D::bar would be more like:

  function bar() {
    $c = new C;
    $c->call_user_method_array("A::foo");
  }

I'd assume this has big performance penalties compared to the old PHP4
way.  It would be nice if call_user_func/call_user_func_array could be
used instead of an eval, but doing so results in $this not being set in
the called method.  For example, the following does not work as I'd
expect it to when $method is given as Array(ancestor_class_name,
method_name) since it seems to treat it as a static method call ($this
is not set within the called method):

  function call_user_method_array($method, $args = null) {
    if (!is_array($method))
      $method = Array(&$this, $method);
    return call_user_func_array($method, $args);
  }

Also, it is not possible to do something like the following because PHP5
dies on the assignment to $this during parsing, and not execution:

  function call_user_method_array($method, $args = null) {
    if (preg_match('/^4/', PHP_VERSION)) {
      $othis = &$this;
      $this = &$c;
      A::foo();
      $this = &$othis;
    } else {
      ... PHP 5 code with eval here ...
    }
  }

The only way to make the above example work is to eval the PHP4 version
(or perhaps include it?), thus incurring a performance penalty yet
again.

Any suggestions how this could be more efficient?  Personally, I'd like
to see syntax directly in the engine to support this:

$c = new C;
$c->A::foo();

Though the static version "C::A::foo()" looks a little wierd....

-Brad Fisher

---

## #7950 — Ferdinand Beyer — 2004-02-18T14:01:59+00:00

URL: https://externals.io/message/7933#7950 · In reply to: #7933

> class D {
>   function bar() {
>     $c = new C;
>     // I'd like to call the A::foo method of C here...
>     //    In PHP4, I could do something like:

Why should one want to do that? Why should PHP allow this?

$c is not an A, it is a C. Of course C is a special version of A, so it is 
compatible to A. But it still is a C.

There will be a reason why C has overridden the A implementation of 
foo(). It is possible that the original implementation is not compatible 
to C, so it could be a risk to call the old method.

The feature you are asking for is not available in any OO language 
and it even conflicts with the OOP ideology!

-- 
Ferdinand Beyer
<fb@fbeyer.com
