John Smith John Smith - 1 month ago 5
Java Question

Php, is this a disgusting sollution? Execute all methods begin with a string

class Processer
{
private function processChat() { }
private function processUsers() { }
private function processBuys() { }
private function processOrders() { }
}


I normally would use this:

public function do()
{
$this->processChat();
$this->processUsers();
$this->processOrders();
}


but its easy to forget to call the new function (as I intentionally missed the
processBuys()
method).

If I refactor it like that:

public function do()
{
foreach (get_class_methods($this) as $m)
{
if (substr($m, 0,7) == 'process')
{
$this->$m();
}
}
}


it works but seems to be ugly (not doable in Java, for example)

Answer

That's definitely an ugly solution. Call the methods explicitly or refactor your code.

easy to forget to call the new function

I disagree. Noone should be expecting that a newly added method will get automagically called by default. Also, if someone is modifying existing code without understanding how it works first, this will not be the only thing that they might get wrong.


Regarding your design choices - why is a single class handling both "chat" and "orders"? I suggest moving the logic to separate classes:

(This is just an example how it can be implemented without resorting to magic.)

interface Process
{
    function execute();
}

class Processor
{
    private $processes;

    function addProcess(Process $process)
    {
        $this->processes[] = $process;
    }

    function process()
    {
        foreach ($this->processes as $process) {
            $process->execute();
        }
    }
}

class ChatProcess implements Process { function execute() { echo "Executing chat\n"; } }
class UsersProcess implements Process { function execute() { echo "Executing users\n"; } }
class PurchasesProcess implements Process { function execute() { echo "Executing purchases\n"; } }
class OrdersProcess implements Process { function execute() { echo "Executing orders\n"; } }

// test
$processor = new Processor();

$processor->addProcess(new ChatProcess());
$processor->addProcess(new UsersProcess());
$processor->addProcess(new PurchasesProcess());
$processor->addProcess(new OrdersProcess());

$processor->process();

Output:

Executing chat
Executing users
Executing purchases
Executing orders