call_user_func_array() and inheritance

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
smudge
Forum Contributor
Posts: 151
Joined: Sun May 20, 2007 12:13 pm

call_user_func_array() and inheritance

Post by smudge »

Hello, I'm working on a simple framework, and the way I'm doing controllers is this:
DefaultController.php:

Code: Select all

class DefaultController extends Controller
{
  public function index(){
    $this->_display();
  }
}
Controller.php:

Code: Select all

class Controller
{
  function init($name,$action='index',$params=array()){
    call_user_func_array($action,$params);
  }
  ...
}
Now, when I do this:

Code: Select all

$class=new DefaultController;
$class->init('DefaultController','index');
It says that the first argument of call_user_func_array() is supposed to be a valid callback, and 'index' is not.
I'm almost certain this has to do with the fact that index() was not defined in the parent class. How do I fix/get around this?
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

If memory serves me, you cannot call a child's methods unless they are overloads of the parent's methods (in the scope of the parent.) The child can call any of its methods and the parent's methods however.
smudge
Forum Contributor
Posts: 151
Joined: Sun May 20, 2007 12:13 pm

Post by smudge »

So how would you recommend I get around this? I've been trying to wrap my head around this for 20 minutes now, and can't come up with a good solution.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

For object method calls you have to provide the object context, in this case $this.

Code: Select all

<?php
class Controller
{
  function init($name,$action='index',$params=array()){
    call_user_func_array(array($this,$action),$params);
  }
}

class DefaultController extends Controller
{
  public function index(){
    $this->_display();
  }
  
  protected function _display() {
  	echo __METHOD__;
  }
}

$class=new DefaultController;
$class->init('DefaultController','index');
But why don't you just override init($params) in DefaultController ?
smudge
Forum Contributor
Posts: 151
Joined: Sun May 20, 2007 12:13 pm

Post by smudge »

DefaultController is the controller I'm using as a (for lack of better term) default controller. Being a framework, there will be other controllers like it, and it seems 'unclean' to have to override init() in each new controller. Besides that, I have seen other frameworks where this is not necessary.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

And calling some arbitrary method with arbitrary parameters is cleaner?
I don't think so but that's something for Theory and Design (which for me translates to: Have it your way ;)).
smudge
Forum Contributor
Posts: 151
Joined: Sun May 20, 2007 12:13 pm

Post by smudge »

Thanks a lot, that worked, but what do you mean by an arbitrary method with arbitrary parameters?
User avatar
superdezign
DevNet Master
Posts: 4135
Joined: Sat Jan 20, 2007 11:06 pm

Post by superdezign »

smudge wrote:Thanks a lot, that worked, but what do you mean by an arbitrary method with arbitrary parameters?
It's extremely generic. In my opinion, too much so. There's nothing wrong with overloading a method.
smudge
Forum Contributor
Posts: 151
Joined: Sun May 20, 2007 12:13 pm

Post by smudge »

If you are talking about init(), I see what you mean. I just designed it that way because of flexibility within the framework.
So far, I haven't gotten mod_rewrite to work, so routes are presented as framework/index.php/controller/action/param/param/...
There must be a controller, action may or may not exist, and there are any number of params, so I designed init() that way. The real init (not what I showed here) assigns the arguments to properties which are stored for use by other methods such as _display(), which require()s views/$name/$action.php
So far everything in the framework generally works except for a few bugs. Maybe when I'm finally done I'll put in critique...
Post Reply