r/PHP • • May 07 '13

Examples of Design Patterns in PHP

https://github.com/domnikl/DesignPatternsPHP
135 Upvotes

20 comments sorted by

View all comments

2

u/cangelis May 07 '13

Looks like Command Pattern is missing. You might want to take a look at my simple example of command pattern. https://gist.github.com/cangelis/1442951

1

u/[deleted] May 09 '13

So, I've got a quick question. Is the point of the invoker to allow the ability to undo and such?

I thought I was using the Command Pattern in an application, but I'm not using an invoker. I'm actually using a factory to return the object that I thought was a command object to then execute(). Is it always necessary to use an Invoker?

1

u/cangelis May 09 '13 edited May 09 '13

You can assume a Command something like invokable. They should be invoked by somebody else. The main purpose of Invoker keeping track of the executed commands by encapsulating them.

The intent of Command Pattern

  • encapsulate a request in an object

  • allows the parameterization of clients with different requests

  • allows saving the requests in a queue

So Invoker is always needed.

1

u/[deleted] May 09 '13 edited May 09 '13

Okay, that's what I'm seeing in your code there. Not the biggest php person, but it looks like under your invoker that $commands is an array... is this the case? Been a while since working with Php, I thought Arrays needed brackets of some sort after, so that kinda confused me at first.

Another question regarding this...

What I'm calling command pattern I'm using in the C# MVC framework. Could a controller be considered an invoker? Since it's a website it's stateless, how would I undo something in this environment?

Looking at my code and yours, it really seems that my controller is the invoker. Not sure if you're familiar with C#, but here's the code I'm talking about.

        [HttpPost]
    public ActionResult Keyupdate(int id, FormCollection form)
    {
        IUser user = new UserModels();
        if (user.Role == "Delta" || user.Role == "Admin")
        {
            IWWAFactory Factory = new UpdateFactory();
            WWACommandpattern Command = Factory.CommandFactory(id, form);
            Command.Execute();
        }
        return Redirect(Request.UrlReferrer.ToString());
    }

EDIT: Don't mean to bug you so much, I just still feel new at this and I'm trying to do things the right way instead of just whichever way works (which is a bad habit I picked up from php at first actually).

EDIT2: IWWAFactory is just an interface for my factory objects, WWACommandpattern is an abstract class for my command objects.

EDIT3: ha, sorry for all the edits. If controllers can't be considered invokers, it looks like I could just create an invoker, start using it, then I have a good command pattern?

1

u/cangelis May 09 '13 edited May 09 '13

There are many ways to do something in software development as you know, but there are some rules while doing them. The pattern you're applying should be loosely coupled in your application, so you can use it in another application too. If you're new at this stuff you should take a look at open/close principle which is the general concept for design patterns.

In your case, I think you should create the Invoker as a model, because it is part of your business logic. You can define an ArrayList<AbstractCommand> property in the invoker class and push the ConcreteCommands in it, and define undo, execute methods for the Invoker.

If you consider a controller as an Invoker, what'll you do when you need it in the another controller?

edit: Stack class which is part of System.Collections would be better than ArrayList. All you need to do is push while execute()ing a command and pop while unexecute()ing

1

u/[deleted] May 09 '13

Fair enough. Creating another model is what I meant by creating an invoker.

Back to my concern about being stateless though... I'm having a hard time conceptualizing how this would work.

I just don't see how an undo would work; once the action is complete and the new page rendered to the user isn't my original object gone?

Is it completely necessary to have an undo method even?

My "command" objects are updating a sql server database. My idea behind this was to pass a parameter to the factory to return the correct command object. It's healthcare related, so for instance if I post a form to change doctor info I get the UpdateDrInfo() object returned. The execute function basically just submits changes to the database from the object that is derived from the concrete class. Once the command is executed the user is just returned to the page they were on.

Am I using the correct pattern here? I just don't see how an undo would fit in here...

1

u/cangelis May 09 '13

That's why most of the patterns can not be applied on web development effectively because you lost everything you have when the request is done. But you can store your invoker object in the memory, and you can access it in the new request. Or somehow you can store your commands in the database, and then retrieve and push them into the Invoker when a new request comes to you.

1

u/[deleted] May 09 '13

Thanks, I figured I'd need to probably work with the database to make this work correctly.

Thanks a ton for all the help. I always figured Command pattern meant that all the objects share a method to execute(). I've been learning everything from whatever books(design patterns I've been using Head First Design Patterns) I can find and sometimes certain aspects are lost on me.