2009年12月4日星期五

Re: [fw-mvc] PageController + ActionStack vs. Simple MVC

Sorry I didn't want to act close-minded. I am just curious how others solve
this issue and I haven't seen a complete example yet. I also think I was not
able to state my problem clearly enough.

I'll try to read your other ressources soon - btw. I closely followed
Paddy's blog back 2 years ago when the first discussion about partials and
view helpers came up which I supported gladly.

I understand the three major dont's why not to use the action stack except
the separation of concerns - we do not have any view / presentation logic in
our controllers. Maybe I explained the sth wrong:


weierophinney wrote:
>
>> Therefore I can either use:
>>
>> (1) a single action for that page that renders several of those view
>> templates, each with different categories -> now, the logic "which
>> articles
>> to display in which order" remain in this action
>
> No, not really. That's *display* logic, and should be in the _view_. And
> just because an application view is triggered from a given action does
> not mean you cannot inject information into that view from elsewhere,
> nor does it mean it needs to be the only view you render. It's perfectly
> acceptable to trigger other views from your controller plugins, action
> helpers, etc.
>

I meant to set any parameters which affect the data that is retrieved from a
model (number of items, sorting mode, ...) This has to be done somewhere and
I surely don't want to to that in a layout file by calling a view helper
with those parameters statically.

I am still asking about the solution for a central, configurable page
renderer based upon Zend MVC.

Spreading this logic over plugins, layout files and templates (via view
helpers) is, as I said, not globally and centrally configurable. Where do I
configure what is displayed on a page alltogether being easily adjustable
without changing PHP code? All examples I've seen so far always would need
ro register additional plugins or manually specifying the rendering of
additional templates for a specific page.

Maybe I just got to the point (like Ralph Schindler mentioned) where I
realize, that Zend MVC cannot be used the way I need the system to be build.
This would finally mean: use only Zend_View and replace the FrontController
architecture by a PageController architecture. Furthermore, do not try to
build a PageController upon a FrontController system :)

Finally - thank you a lot for your time spent on answering my questions and
don't get me wrong - I love the Zend Framework :D

weierophinney wrote:
>
> -- Christian Ehmig <ehmig@boerse-go.de> wrote
> (on Friday, 04 December 2009, 07:16 AM -0800):
>> Yes, I understand how to construct a view helper for this case - but this
>> simply does not solve the "usage issue". The view script you mentioned
>> will
>> be used by a specific action which passes the category 'zend_framework'
>> to
>> the view script. But this just renders one simple news box. Now I like to
>> re-use the view script several times within a given page.
>
> The example I showed was simply returning the articles -- but it could
> very easily also perform the markup.
>
> And don't forget: you can also re-use view scripts:
>
> <?php echo $this->render('controller/action.phtml') ?>
>
> I think you're getting stuck in your current implementation and not
> really trying or experimenting with other solutions due to your
> familiarity with ActionStack. As I mentioned, read Paddy's blog, read my
> blog, read the ZF manual, google for examples -- but most importantly,
> perform some experiments, and see what might work. ActionStack is an
> expedient means to an end -- but one that many of us have realized is
> both expensive and hard to maintain and test.
>
>> Therefore I can either use:
>>
>> (1) a single action for that page that renders several of those view
>> templates, each with different categories -> now, the logic "which
>> articles
>> to display in which order" remain in this action
>
> No, not really. That's *display* logic, and should be in the _view_. And
> just because an application view is triggered from a given action does
> not mean you cannot inject information into that view from elsewhere,
> nor does it mean it needs to be the only view you render. It's perfectly
> acceptable to trigger other views from your controller plugins, action
> helpers, etc.
>
>> - to change the displayed
>> article categories, the number or articles per rendered view template ...
>> I
>> need to adjust the controller (passing those parameters via REQUEST is
>> obviously no choice). this action would be called something like
>> "homepageAction", "page1Action", "page2Action" for each single page. This
>> is
>> not configurable.
>>
>> (2) one global "pageAction" which reads a $pageId parameter from REQUEST
>> and
>> the config for that page from db. Now it assembles the page based upon
>> the
>> configuration e.g. display the view script 3 times with the categories a,
>> b
>> and c. So this is exactly the case I mentioned - you would have a "single
>> action" system where there is no need for any other action since the
>> whole
>> output is generated via one pageAction (any request can be handled by
>> that
>> action) - this would justify the use of view helpers but deny the usage
>> of
>> controllers and actions in general. To "break up" the code one would
>> maybe
>> _forward to other actions within the pageAction, but this is even worse
>> to
>> configure and maintain.
>>
>> To state it again, neither (1) or (2) are acceptable for me - are there
>> any
>> other solutions about "configuring" the page rendering process from
>> "outside
>> controllers and views"?
>
> Listen, ZF is flexible enough to allow you to develop however you want.
> You asked for some ideas, and several of us have presented our opinions;
> you do not agree with them, obviously.
>
> I'll state the why's behind why several of us recommend not using action
> stack and instead building rich models and view helpers:
>
> * First, and most importantly: they're testable, and controllers, while
> we have the ControllerTestCase, are tricky to test. I can test my
> models in isolation, and I can actually test my view helpers fairly
> easily in isolation. This allows me to ensure consistency within the
> most important aspects of my application.
>
> * Proper separation of concerns. Put display logic in the views,
> business logic in the models. Your controllers should only be acting
> as traffic cops, determining what models and views to use, and
> injecting the appropriate dependencies.
>
> * ActionStack is expensive. Dispatching actions is expensive due to the
> use of reflection and I/O stat calls in the dispatcher. Additionally,
> every time you run through the dispatch loop, you're triggering
> plugins -- and the more plugins you have, the slower the loop will
> be.
>
> You can configure your views and layouts -- including what will render,
> and where -- in a variety of locations, including the view and layout
> scripts themselves. There's no reason to get locked into thinking only
> the controllers can determine what views to run.
>
>> weierophinney wrote:
>> >
>> > -- Christian Ehmig <ehmig@boerse-go.de> wrote
>> > (on Friday, 04 December 2009, 05:15 AM -0800):
>> >> weierophinney wrote:
>> >> > -- Christian Ehmig <ehmig@boerse-go.de> wrote
>> >> > (on Friday, 04 December 2009, 02:39 AM -0800):
>> >> >> I've read some discussions about the "evil" ActionStack in this
>> forum
>> >> and
>> >> >> specifically here:
>> >> >>
>> >>
>> http://www.rmauger.co.uk/2009/03/why-the-zend-framework-actionstack-is-evil/
>> >> >>
>> >> >> I commented on that (#19).
>> >> >>
>> >> >> Now my question is - how do you setup Zend MVC for complex, highly
>> >> >> configurable websites or portals (not only simple blog applications
>> >> with
>> >> >> basic CRUD operations). In particular, websites that consist of
>> many
>> >> >> conrete
>> >> >> pages that make use of (hopefully) reusable components.
>> >> >>
>> >> >> For me the best solution is still:
>> >> >>
>> >> >> 1. Writing a Zend_Controller_Plugin that hooks into routeShutdown()
>> >> >> 2. in routeShutdown() compile the set of actions, their parameters,
>> >> >> templates and layout targets from a given page configuration (xml
>> >> file,
>> >> >> database) and the layout file to be used for that page
>> >> >> 3. Push these actions to the ActionStack
>> >> >> 4. done
>> >> >>
>> >> >> Any other approaches seem not reusable and "hard-coded" for me. I
>> can
>> >> >> give
>> >> >> further details on my implementation if needed. I am just curious
>> how
>> >> >> others
>> >> >> solve the issue "a page consists of several actions and their
>> >> respective
>> >> >> views".
>> >> >
>> >> > I've spoken and blogged a ton on this in the last year. The answer:
>> >> this
>> >> > stuff is typically either part of your domain model or part of your
>> >> view
>> >> > layer, but has nothing to do with your controllers.
>> >> >
>> >> > If the reason you're using ActionStack is to re-use business
>> logic...
>> >> > then that logic should be pushed into your models. If the reason
>> you're
>> >> > using ActionStack is to re-use view scripts, then simply consume
>> those
>> >> > view scripts. A judicious use of view placeholders and view helpers
>> can
>> >> > achieve some tremendous results.
>> >>
>> >> I tried to find some posts / blogs about this subject - I would be
>> happy
>> >> if
>> >> you could provide me with some links to your posts.
>> >
>> > Most recently, a talk at ZendCon:
>> >
>> > http://www.slideshare.net/weierophinney/architecting-your-models
>> >
>> > I've also blogged on the subject a few times, though most of the
>> entries
>> > are a bit dated in regards to how I actually code now:
>> >
>> > http://weierophinney.net/matthew/plugin/tag/mvc
>> >
>> > Paddy also has some great articles; browse his blog at:
>> >
>> > http://blog.astrumfutura.com/
>> >
>> >> About ActionStack - we are using it to re-use both business logic and
>> >> view
>> >> scripts. If working with only one action per request where is the
>> point
>> >> in
>> >> having more than one action anyway? I am talking about sth like a
>> >> "PageController" architecture. A request is handled by a
>> PageController
>> >> which knows (from configuration) how to render the page. This includes
>> >> the
>> >> layout, the actions + their parameters and templates. If you try to
>> >> implement re-usable actions, a single page will always consist of
>> several
>> >> action calls.
>> >
>> > The PageController pattern is different than the FrontController
>> > pattern. Your description of PageController is spot on -- but it's not
>> > how FrontController works. FrontController decomposes a request, and
>> > from there determines what actions to take. The workflow is different,
>> > in that there is not an assumption of a single course of action, or of
>> a
>> > specific handler for a given request. As such, a "controller" is merely
>> > a group of related actions -- typically actions that operate on a
>> common
>> > resource. This is the rationale for multiple actions per controller.
>> >
>> > Within the ZF FrontController implementation, there are several other
>> > components where responsibility may be delegated: front controller
>> > plugins, action helpers (which also can be used to automate, via init()
>> > and pre/postDispatch() hooks), even bootstrap resources.
>> >
>> > Another thing: view helpers can be aware of models, and make calls on
>> > them. This provides some tremendous flexibility in regards to re-usable
>> > presentation logic.
>> >
>> >> Simple example:
>> >>
>> >> listArticlesAction() which lists a set of articles using a given
>> template
>> >> -
>> >> the action itself queries it's data from the model:
>> $model->getArticles()
>> >> by
>> >> passing parameters.
>> >>
>> >> Now, you like to display different sets of articles on different pages
>> >> and
>> >> it should be completely configurable - much like in a typical CMS with
>> db
>> >> backend.
>> >>
>> >> I cannot see any benefit from using view helpers or placeholders here
>> >> instead of an ActionStack. Where would you effectively configure which
>> >> set
>> >> of articles to display on a given page. Also think of several
>> different
>> >> sets
>> >> of articles per page. This sould easily be re-configurable in any
>> point
>> >> of
>> >> time.
>> >
>> > This is actually *trivial* to do with a well-defined model and a view
>> > helper.
>> >
>> > Consider this helper definition:
>> >
>> > class Blog_View_Helper_Articles extends Zend_View_Helper_Abstract
>> > {
>> > protected $_model;
>> >
>> > public function articles($set = null)
>> > {
>> > if (null === $set) {
>> > return $this;
>> > }
>> >
>> > return $this->getModel()->fetchArticlesBySet($set);
>> > }
>> >
>> > public function setModel(Blog_Model_Article $model)
>> > {
>> > $this->_model = $model;
>> > }
>> >
>> > public function getModel()
>> > {
>> > if (null === $this->_model) {
>> > $this->setModel(new Blog_Model_Article);
>> > }
>> > return $this->_model;
>> > }
>> > }
>> >
>> > Within a view script, you would then do something like this:
>> >
>> > <ul>
>> > <?php foreach ($this->articles('zend_framework') as $article): ?>
>> > <li>
>> > "<?php echo $this- url(array('id' => $article->id),
>> > 'blog-entry') ?>">
>> > <?php echo $this->escape($article->title) ?>
>> >
>> > </li>
>> > <?php endforeach ?>
>> > </ul>
>> >
>> > Because the helper takes an argument, you can then re-use it several
>> > times on the page. This takes less overhead than dispatching multiple
>> > actions in the request, and pushes the business logic to an easily
>> > _testable_ layer as well (view helpers and models are more easily
>> tested
>> > than controllers).
>> >
>> > Hopefully this example and the above resources will give you some ideas
>> > for how to accomplish these goals.
>> >
>> > --
>> > Matthew Weier O'Phinney
>> > Project Lead | matthew@zend.com
>> > Zend Framework | http://framework.zend.com/
>> >
>> >
>>
>> --
>> View this message in context:
>> http://n4.nabble.com/PageController-ActionStack-vs-Simple-MVC-tp948403p948601.html
>> Sent from the Zend MVC mailing list archive at Nabble.com.
>>
>
> --
> Matthew Weier O'Phinney
> Project Lead | matthew@zend.com
> Zend Framework | http://framework.zend.com/
>
>

--
View this message in context: http://n4.nabble.com/PageController-ActionStack-vs-Simple-MVC-tp948403p948692.html
Sent from the Zend MVC mailing list archive at Nabble.com.

没有评论: