Question

I'm currently doing it this way, but seems to not be the proper way:

class Name
{
    protected $jobs2do;

    public function __construct($string) {
        $this->jobs2do[] = $this->do;
    }

        public function do() {
        ...
    }
}

Because directly assign a function will cause warning, should do something like:

function func()
{
...
}

$func_array[] = 'func';

say, put it into a string, but I don't know how to do it when it's a member function.

Is the following version OK?:

class Name
{
    public $jobs2do;

    public function __construct($string) {
        $this->jobs2do[] = array($this,'do');
    }

        public function do() {
        ...
    }
}

when call it, just:

$instance = new Name();
foreach ($instance->jobs2do as $job)
{
    call_user_func($job);
}
Was it helpful?

Solution

Write a class for Job and use factory pattern to create them. Then Write a class JobManager wihich should maintain a list ob Job instances.

interface iCallableJob
{
    public function run();
}

class Job implements iCallableJob
{
    // The parameterized factory method
    public static function factory($type)
    {
        $classname = 'Job_' . $type;
        if (class_exists($classname) && in_array('iCallableJob', class_implements('Job')))
        {
            return new $classname();
        }
        return null;
    }
    public function run() { return null; }
}

class Job_type1 extends Job 
{
    public function run() 
    {
        echo 'Job 1';
    }
}

class JobManager
{
    protected $jobs2do = array();

    public function addJob($type)
    {
        if ($job = Job::factory($type))
        {
            $this->jobs2do[] = $job;
            return $job;
        }
        return null;
    }
    public function runAll()
    {
        foreach ($this->jobs2do AS $job)
        {
            $job->run();
        }
    }
}

OTHER TIPS

There are (at least) 4 ways to do this. There are other ways but these are the most pure. The method versions require PHP5 at a minimum.

class foo {
    public function bar($a) { return $a; }
}

$anObject = new foo();
$ret = call_user_func(array($anObject,'bar'), 1);
$ret = call_user_func_array(array($anObject,'bar'), array(1));
$ret = call_user_method('bar', $anObject, array(1));
$ret = call_user_method_array('bar', $anObjectm, 1);

You can replace 'bar' with a string variable, too.

Take a look at the callable pseudo type. You can then call that function with call_user_func():

class Foo {
    function bar($str) {
        echo($str);
    }
}

$foo = new Foo();
$func_array = array();
$func_array['foo->bar'] = array($foo, 'bar');  // this is the 'callable' pseudo-type

call_user_func($func_array['foo->bar'], "Hello World");



Edit: It seems you're trying to implement the command pattern. In that case you could try something along these lines:

// define an interface for all actions
interface Executable {
    public function do();
}

// an example action
class DoSomething implements Executable {
    private $name;

    public __construct($name) {
        $this->name = $name;
    }

    public function do($str) {
        echo("Hello $str, my name is $this->name");
    }
}

$objects_to_process = array(new DoSomething("Foo"), new DoSomething("Bar"));
foreach ($objects_to_process as $obj) {
    if ($obj instanceof Executable)
        $obj->do("World");
}

There can be several possible solutions to this problem. You have Command and Factory patterns presented in other replies. This one illustrates how to use Visitor + Command pattern cooperation.

class Name {

    protected $jobs = array();

    public function addJob(IJob $j) {
        $this->jobs[] = $j;
    }

    public function do() {
        foreach ($this->jobs as $j) {
            $j->run($this);
        }
    }

}

interface IJob {

    public function run(Name $invoker);

}

class WashDishes implements IJob {

    public function run(Name $invoker) {
        echo get_class($invoker) . ' washes dishes<br/>';
    }

}

class DoShopping implements IJob {

    public function run(Name $invoker) {
        echo get_class($invoker) . ' does shopping<br/>';
    }

}

$n = new Name();
$n->addJob(new WashDishes());
$n->addJob(new DoShopping());
$n->do();

Output:

Name washes dishes
Name does shopping

A class implementing IJob interface is a command that can be passed and stored for later execution. The way Name object invokes jobs in collection (passing $this reference) is typical for Visitor pattern (this way job object has access its caller - Name object). However, true Visitor pattern is not possible in PHP due to lack of native support for explicit method overriding.

dont know if this is the correct way. but this is how i do mine.

$this->api['google']['+1Button']=function($str)
    {
        echo $str;
    };
    $this->api['google']['+1Button']("hello world");
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top