ZF and mysite.com/blog/topic/delete/5

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

koen.h
Forum Contributor
Posts: 268
Joined: Sat May 03, 2008 8:43 am

Re: ZF and mysite.com/blog/topic/delete/5

Post by koen.h »

arborint wrote: If code separation is your goal then you might want to think of a callback style design. An Application Controller drives this kind of implementation. An example is the Skeleton Form Controller where you assign separate callback methods for the init, submit and done states of a form. Each is called based on the state of the form. Not sure that is what you are looking for either though...
I think this is an interesting idea and closer to what I intend (at least if I understand it correctly).

Let's say on any page in the sidebar I have a login form. The action url is the same page. That gives action1 = login, action2 = display of that page (totally different controller). The first action maps to LoginController::login(). This LoginController class implements a LoginController::done() method that is automatically called after the login action finishes. It could then eg call another controller for action2 or redirect.
koen.h
Forum Contributor
Posts: 268
Joined: Sat May 03, 2008 8:43 am

Re: ZF and mysite.com/blog/topic/delete/5

Post by koen.h »

pytrin wrote:
koen.h wrote: Take this example:

Code: Select all

class AuthorController extends Zend_Controller_Action
{
// Some code
   
}
The login action does all sorts of things depending on the request parameters and ultimately leads to some html ouput through various means. I'd like to seperate responsabilities here. The login action is for logging in, not for knowing what action it should call to display html.
A login request initiated from a html form ideally contains 2 actions. The first being the login action itself, the second the action that should display the html page after unsuccessful/successful login attempt.

I hope this clears up my problem.
Let it be clear that I didn't want to criticize that code. I just used it to make my point that what is usually done is mixing updating/deleting/etc and viewing within one action. Your own code actually is a shorter example of this :-) I don't know much about REST but I think it's similar to having requests seperate CRUD actions/concerns.

I think the problem in that example is that too much happens in the controller. I ussually have a login action like this:

Code: Select all

 
class AuthorController extends Zend_Controller_Action
{
   
    public function loginAction()
    {
        if ($this->getRequest()->isPost()) {
             $result = Auth::login($_POST); // A separate class handles login validation
             if($result === true) {
                  $this -> _redirect('/index'); // Login successful, redirect to index or do something else
             } else {
                  $this -> initView() -> errors = $result; //Inject login errors into the view
             }
        }
 
        echo $this -> render(); //If we're here we either failed login or just got to the login page
    }
}
 
When its kept simple, I don't see a need for separate actions to handle login. Everything is a case by case scenario.
User avatar
Eran
DevNet Master
Posts: 3549
Joined: Fri Jan 18, 2008 12:36 am
Location: Israel, ME

Re: ZF and mysite.com/blog/topic/delete/5

Post by Eran »

It all depends on how you want the flow of your application to work. It makes sense to me to have both the form handling and form view in the same place, since if the form validation fails I usually put the validation error in the form view. So in my opinion this setup reduces complexity instead of constantly redirecting / forwarding between actions.

And not all (most) web application are implementation of REST architecture...
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: ZF and mysite.com/blog/topic/delete/5

Post by Christopher »

koen.h wrote:I think this is an interesting idea and closer to what I intend (at least if I understand it correctly).

Let's say on any page in the sidebar I have a login form. The action url is the same page. That gives action1 = login, action2 = display of that page (totally different controller). The first action maps to LoginController::login(). This LoginController class implements a LoginController::done() method that is automatically called after the login action finishes. It could then eg call another controller for action2 or redirect.
If you are interested I can post some code to show the two different styles. We had a discussion about this because the two different style solutions share the same base code. So the question was: are they both needed? I think they are a essentially different ways to organize the code. So I think there are some reasons why one might be better than the other when building reusable base controllers.
(#10850)
koen.h
Forum Contributor
Posts: 268
Joined: Sat May 03, 2008 8:43 am

Re: ZF and mysite.com/blog/topic/delete/5

Post by koen.h »

Yes I'm very much interested.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: ZF and mysite.com/blog/topic/delete/5

Post by Christopher »

The standard form logic uses if's:

Code: Select all

class foo extends ActionController {
    function index() {
        if ($this->form->isValid()) {
            // redirect to done page
        } else {
            if (! $this->form->isSubmitted()) {
                // initialize default form values
            }
            // show form
        }
    }
}
The state base one looks like this:

Code: Select all

class foo extends FormController {
    function init() {
        // initialize default form values
        // show form
    }
 
    function submit() {
        // show form
    }
 
    function init() {
        // redirect to done page
    }
}
Technically the differences are minor. For simple forms the standard style at the top clearly shows the logic. However, maybe as the code gets bigger or if you want to inherit common functionality, the second callback style might have some advantages. The second maybe looks cleaner because there is no if structure to clutter things up.
(#10850)
User avatar
Eran
DevNet Master
Posts: 3549
Joined: Fri Jan 18, 2008 12:36 am
Location: Israel, ME

Re: ZF and mysite.com/blog/topic/delete/5

Post by Eran »

Regarding the code getting bigger - in my opinion that would be outside the scope of the controller. Fat controllers are a code smell as far as I'm concerned.
koen.h
Forum Contributor
Posts: 268
Joined: Sat May 03, 2008 8:43 am

Re: ZF and mysite.com/blog/topic/delete/5

Post by koen.h »

arborint wrote:

Code: Select all

class foo extends FormController {
    function init() {
        // initialize default form values
        // show form
    }
 
    function submit() {
        // show form
    }
 
    function init() {
        // redirect to done page
    }
}
This reminds me of setup() and tearDown() from unit testing. There's one quote that comes to mind (http://www.phpunit.de/pocket_guide/3.3/en/fixtures.html)
If you really have a different setUp(), you need a different test-case class. Name the class after the difference in the setup.
In a way, if I can draw the analogy, your example/idea should lead to better design. If somehow a controller contains actions that need different inits/ends, they belong in a different (sub)controller.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: ZF and mysite.com/blog/topic/delete/5

Post by Christopher »

koen.h wrote:This reminds me of setup() and tearDown() from unit testing. There's one quote that comes to mind (http://www.phpunit.de/pocket_guide/3.3/en/fixtures.html)

In a way, if I can draw the analogy, your example/idea should lead to better design. If somehow a controller contains actions that need different inits/ends, they belong in a different (sub)controller.
No it is actually different because setup()/tearDown() run in addition to your method. In the example I showed, only one if the three methods runs each request -- init() runs the first time in, submit() runs if there is an error, and done() runs if all fields are valid...
(#10850)
Post Reply