Something good written with the Zend Framework

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

User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

I'm game.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

wish I could say the same... I've got my hands in too many things right now. I could spare some time to write a little bit of documentation, but I've got too many projects as it is.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

I was just thinking that we should first do a (probably long) discussion thread here to air the issues. My list is a start at that discussion. Obviously code snippets would be part of the discussion.

My concern is that there is not one best implementation, though there is probably a reasonable basic one. I really have not see an independent discussion that goes through the process of trying to use the ZF (instead of design/build it). There would probably be enough material in that discussion to build a reasonable demonstration application.
(#10850)
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

Air some issues
Certainly. The issue I'm having at the moment is one of code reuse in controllers. I have a controller called JobController with the following methods.
  • indexAction() - redirects to listAction()
  • listAction() - displays a list of records and provides buttons to access any of the other actions
  • deleteAction() - deletes one or many jobs
  • modifyAction() - modify an existing job
  • newAction() - create a new job
Now these all appear in the same controller primarily because its what I've seen other people do and because it makes for user friendly URLs --- but actually the functional requirements of these actions are very different. The result is a classs with very poor cohesion and difficulties from complex or duplicative instantiation issues which have led many to over globalise objects. *cough* OK that was a very complicated sentence...allow me to qualify this with my recent real world experience.

Basically I have a pool of objects that I'm using: Paginator, DbQuerier, View, PostDataRetriever, MessageSet (for error and notifications), Validator etc. All these objects are nice and simple and working very well. But I'm experiencing difficulties where only some of these objects are needed some of the time. For instance I only need MessageSet and Validator in newAction() and modifyAction() when a submission is made and then I need View in all the actions apart from indexAction() and deleteAction().... The fact that this is the case leads me to think that some of these things are only partly related and shouldn't be placed directly together. So what I would like to do is to bind different requests to various different types of controller actions each equiped with all the objects to achieve a certain task. I'm quite sure ZF is capable of doing such a thing without any modification. So for instance something like this:

Code: Select all

// $controller->bind($url, $requestType, $binding);
// Binding::__construct($className, $function, $paramsToSend) 
 
$controller->bind('Job/new',    Controller::RQST_TYPE_GET, new Binding('JobNewModify', 'emptyPrint', false));
$controller->bind('Job/modify', Controller::RQST_TYPE_GET, new Binding('JobNewModify', 'emptyPrint', true));
$controller->bind('Job/new',    Controller::RQST_TYPE_POST, new Binding('JobNewModify', 'create', false));
$controller->bind('Job/modify', Controller::RQST_TYPE_POST, new Binding('JobNewModify', 'create', true));
$controller->bind('Job/delete', Controller::RQST_TYPE_POST, new Binding('JobUpdate', 'markAsDelete'));
$controller->bind('Job/list',   Controller::RQST_TYPE_ANY, new Binding('Lists', 'job'));
$controller->bind('Job', Controller::RQST_TYPE_ANY, new RedirectBinding('Job/list'));
 
 
Here classes JobNewModify, JobUpdate and List can be different and are able to specialise in a certain type of functionality and thus remain cohesive.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

That is a good place to start as it fits with the first thing on my list which was "Basic concepts." I guess part of the bargain when you sell your soul to a controller architecture is that you have to use the tools that it provides. The modern "controller/action" style dispatch maps nicely onto classes and methods, but sometimes you don't want it to.

Here are some of the possible options:

1. Each "controller/action" maps to a class/method that contains the actual Controller code.

2. Each "controller/action" maps to a class/method that loads the Controller code only if called.

3. A dispatched "controller/action" class/method forwards to another Action Controller

4. The Router maps "controller/action" onto specified (different) class/method

If there are more then please mention them. I have listed them in my order of preference that I would apply them (but that order may change as we discuss).
(#10850)
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

What are the reasons behind your preferences?
matthijs
DevNet Master
Posts: 3360
Joined: Thu Oct 06, 2005 3:57 pm

Post by matthijs »

1. Each "controller/action" maps to a class/method that contains the actual Controller code.
Is this also related to the URLs or do you have a router between this as well? Or is that no 4?

And if so, why do you prefer 1 over 4? I would imagine that decoupling of the interface (URLs) from the actual controller/action-architecture would be a good thing.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

ole wrote:What are the reasons behind your preferences?
I am assuming that everything is going through the Router. The reason for my preferences is that the code for the requested "controller/action" gets more distant from the "normal" place with each option. The less "normal" the more chances for mistakes and the more time to deal with the code.

1. is the normal dispatch "controller/action" where the actions are all methods in "controller" and the code for each action is in the method.

2. is normal dispatch and when you look in the action methods you can see where the code is included

3. since one or more of the action methods forward then you need to find a different controller to see the code

4. since the "controller/action" does not match the name of the actual controller file you need to look at the Router's rules to find the code that is dispatched.
(#10850)
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

OK if you worried about risk and complexity I think you can relax because I've figured it out. It was actually quite easy once I figured out the bit I needed to extend.

Code: Select all

class DevNet_Controller_Router_BindBased extends Zend_Controller_Router_Abstract
{
    public function route(Zend_Controller_Request_Abstract $request)
    {
        // Here a request object comes in and you can examine it and set where its action and controller names
        $request->setActionName('bar');
        $request->setControllerName('Foo');  // in this case the this is always going to go to one place always
        $request->setModuleName('module');
 
        return $request; // this will then go off to the dispatcher
    }
    public function addBinding() {} // can add this stuff
}
$controller = Zend_Controller_Front::getInstance();
$controller->setControllerDirectory('controllers');
$controller->setRouter(new DevNet_Controller_Router_BindBased());
$controller->dispatch();
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

ole wrote:OK if you worried about risk and complexity I think you can relax because I've figured it out. It was actually quite easy once I figured out the bit I needed to extend.
Well ... I think risk and complexity are key issues in design, but I don't think they were what I was talking about above. My main point was that if we are going to generally follow the Convention over Configuration style then you do the most obvious (conventional) thing first and resort to other schemes in the order of their unobviousness. My list above just lists the possible solutions in the order of how easy it would be to find the dispatched code. That is certainly not the only goal, but it will have a direct effect on maintainability.

I am not sure where you are going with your code. I don't think we should attempt to replace a standard ZF class until we have proven that it just does not work when everything around it is implemented properly.
(#10850)
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

OK fine, I can go along with that.
Shall we get started then? Is everyone OK with the CD organiser idea?
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

ole wrote:OK fine, I can go along with that.
Shall we get started then? Is everyone OK with the CD organiser idea?
Do you want to use Rob Allen's code as a base and expand it -- or start from scratch? Expanding that code might be interesting, but as Rob is already doing that it also might be good to do something else. Obviously having part to the application be a CRUD controller would be good. There are also other simple applications that would be similar, like a very simple blog or shop. Another direction would be to focus on reuslable building blocks like CRUD controller or a Pager.
(#10850)
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

Hmmm now you mention it a shop would be quite good I've never actually done one of those.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

We could start with the basic product display and admin pages, so the ability to display a list of products and a product detail page, plus the an administration section with CRUD to edit the product records. All those pages are still pretty generic for a simple database application (blog, collection, shop, etc.).

The first place to expand would be adding authentication to the admin section. Sorting that out would be a great thing for us to do as an example.

Beyond that there, on the e-commerce front, are the shopping cart, checkout, and admin order management. That the core. Beyond that it is all customizations like product categories, etc.
(#10850)
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

Sounds great. I guess we should start with the admin stuff first and we'll need a db schema.
Post Reply