Command pattern

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
rimian
Forum Newbie
Posts: 9
Joined: Wed Apr 30, 2008 5:33 am

Command pattern

Post by rimian »

Hi,

I'm building myself a framework and I'm wondering about my controller (using the Command Pattern)... Should I use use one controller class for my node (module) with a switch or split it up into separate classes like:

Code: Select all

 
class Node_Command extends Command{
    function execute( $op ){
        switch($op){
            case 'add':
            //do add stuff
            break;
            case 'edit':
            //do edit stuff
            break;
 
            //etc etc
 
    }
}
 
OR!

Code: Select all

class Node_Add_Command extends Command{
    function execute( Command_Context $context ){
        //node add stuff
    }
}
class Node_Edit_Command extends Command{
    function execute( Command_Context $context ){
        //node edit stuff
    }
}
Any help much appreciated!
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Re: Command pattern

Post by Chris Corbyn »

Switch statements in OO code often indicate a smell and suggest you should be using a strategy-like pattern. I'd say use your multiple objects if you're going to go down the command pattern route.

Take a look at the page controller pattern though; it's much more suited.

PS: If you're writing a framework I strongly urge you to start using PHP5 code. You're currently writing code in PHP4 by the look of things which is deprecated.
User avatar
onion2k
Jedi Mod
Posts: 5263
Joined: Tue Dec 21, 2004 5:03 pm
Location: usrlab.com

Re: Command pattern

Post by onion2k »

Chris Corbyn wrote:PS: If you're writing a framework I strongly urge you to start using PHP5 code. You're currently writing code in PHP4 by the look of things which is deprecated.
The type hinting (function execute( Command_Context $context )) would imply it's PHP5.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Re: Command pattern

Post by Chris Corbyn »

:oops: You got me! Usually when I've seen the Command pattern employed it's been via interface rather than a base class.

Code: Select all

interface Command {
  public function execute();
}
rimian
Forum Newbie
Posts: 9
Joined: Wed Apr 30, 2008 5:33 am

Re: Command pattern

Post by rimian »

Yes, I am definately using php5. I didn't include the abstract class in my example for the sake of reading. I will take the advice on smelly code. Thanks! And I will also look at the page controller pattern.

I've avoided a switch statement by dynamically calling the function like so:

Code: Select all

 
class Node_Add_Command extends Command{
    function execute( Command_Context $context ){
        $operation = $context->get_op();
        $node = new Node();
        $node->$operation(); //must check my syntax here  
    }
}
 
Now I am wondering how to map the user authentication into this... and is this good practice? Will security be hard to enforce?

Thanks Chris, Onion2k.

PS: I will release this under GPL.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Command pattern

Post by Christopher »

You should really look at current practice. The code you showed above with the switch, and your double-dispatch code above is missing what is currently being implementing -- Action Controllers. Don't go back to Page Controllers. The whole point of using the Command pattern is because then all Actions have a common interface so they can be dispatched by a Front Controller. That is where the Command pattern comes into play.

Code: Select all

 
class Fooextends ActionController {  // it uses the Command pattern, but don't call it that
    function execute(){
    }
 
    function add(){
    }
 
    function edit(){
    }
 
    //etc etc
    }
}
The execute() or run() or index() action is the default action. Sometimes they add standard prefixes to everything:

Code: Select all

 
class FooController extends ActionController {
    function addAction(){
    }
 
    function editAction(){
    }
 
    //etc etc
    }
}
(#10850)
rimian
Forum Newbie
Posts: 9
Joined: Wed Apr 30, 2008 5:33 am

Re: Command pattern

Post by rimian »

Yes! That's why I am here! To find out what the current practice is. I am reading through a few text books and studying hard but I need to apply these skills. This discussion is very helpful.

Thanks Christopher. I had revised my last example (in my head) and came up with something similar to what you just mentioned but not quite as elegant.
koen.h
Forum Contributor
Posts: 268
Joined: Sat May 03, 2008 8:43 am

Re: Command pattern

Post by koen.h »

What's the current practice with a more complex layout? Eg I can imagine a forum application integrated in a CMS. The CMS uses a frontcontroller that calls an actioncontroller. Like in the examples that would be "forum extends actioncontroller".

But a forum itself could delegate to different controllers. Eg different commands for a topic (delete, edit, create, approve), for a category (edit, delete, etc).

Following the current practice example, having one forum controller, would that be implemented as this:

Code: Select all

 
class Forum extends ActionController {
    public createTopic()
    public deleteTopic()
    public createCategory()
    etc
}
 
This would lead to a bloated forumcontroller. So what to do in this case (when you would want to split up commands)?
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Command pattern

Post by Christopher »

You would probably create multiple Action controllers to handle that:

Code: Select all

class Topic extends ActionController {
    public create()
    public delete()
    public edit()
    etc
}
 
class Category extends ActionController {
    public create()
    public delete()
    public edit()
    etc
}
So your URLS would be like "mysite.com?controller=topic&action=edit&id=5" or mysite.com/topic/delete/5".
(#10850)
koen.h
Forum Contributor
Posts: 268
Joined: Sat May 03, 2008 8:43 am

Re: Command pattern

Post by koen.h »

arborint wrote:You would probably create multiple Action controllers to handle that:

Code: Select all

class Topic extends ActionController {
    public create()
    public delete()
    public edit()
    etc
}
 
class Category extends ActionController {
    public create()
    public delete()
    public edit()
    etc
}
So your URLS would be like "mysite.com?controller=topic&action=edit&id=5" or mysite.com/topic/delete/5".
Guess that's more or less what they do in ZF with the addition that it would be " mysite.com/blog/topic/delete/5" to determine the topiccontroller from which app is called. Unless there's only one application but then the scenario of one class with commands is used.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Command pattern

Post by Christopher »

koen.h wrote:Guess that's more or less what they do in ZF with the addition that it would be " mysite.com/blog/topic/delete/5" to determine the topiccontroller from which app is called. Unless there's only one application but then the scenario of one class with commands is used.
ZF followed Rails in the URLs and Action Controllers. The code I posted would be the same in a module. The module parameter only selects the base directory to use for to find the controllers, models, views, etc.
(#10850)
Post Reply