2009年4月20日星期一

Re: [fw-mvc] Nested / complex views

Thanks for the feedback, everyone, but let's take this a step further.  The Twitter example may have been a little too simple.  What happens when more and more Model data needs to get wired together in order to present a view?  A view helper isn't going to hold up as the program gets more and more complex.  Honestly, I'd LOVE to see the ability to nest Layouts as well as Views.

Really, nesting Action calls seems like the way to go here.  Think about it, do you REALLY want to wire up all the breadcrumb, access control, and customized menu Models for EVERY Action that needs to display a header?  No, you don't, that would be silly.  It seems like it would be much preferable to recursively hand those calls off to the respective controllers and let them handle that work for you, taking the top-level action's state into account. 

Consider the following.

NavigationController extends Zend_Controller_Action
{
   public function indexAction()
   {
       $bc = new BreadCrumbs();
       $bc->add($referrer);
       $this->view->breadcrumb = $bc

       $this->view->menu = new Menu($ACL);
   }
}

SiteController extends Zend_Controller_Action
{
   public function headerAction()
   {
       $imgRotator = new RandImage();
       $this->view->logo = $imgRotator->getLogo();
       $this->view->background = $imgRotator->getBG();

       $this->view->nav =
           $this->_helper->actionStack('index', 'navigation');
   }
}

IndexController extends Zend_Controller_Action
{
   public function indexAction()
   {
       $this->view->header = $this->_helper->actionStack('header','site');
       $this->view->footer = $this->_helper->actionStack('footer','site');

       $this->view->tweets = $this->_helper->actionStack('recent', 'twitter');
       $this->view->blog = $this->_helper->actionStack('curmonth', 'blog');
       ...
   }
}

Would you REALLLLY advocate creating a view helper for each of those, and then having to create the ACL, BreadCrumbs, RandImage, and Menu objects on EACH page that used a header?  What if you found a better object with which to calculate breadcrumbs or just wanted to remove them altogether?  You'd have to search through all your Controllers and pull out the BreadCrumbs object for each Action that used it, instead of just one place.


Ryan Hagan
ryan@ryanhagan.net


On Mon, Apr 20, 2009 at 5:46 PM, Remy Damour <remy.damour@gmail.com> wrote:
Why don't you use view helpers? 

They're done just for this: http://framework.zend.com/manual/en/zend.view.helpers.html

Let's say you create your twitter helper to output recent feeds, under /application/views/helpers/TwitterRecent.php:

class View_Helper_TwitterRecent extends Zend_View_Helper_Abstract
{
 public function twitterRecent($tweets)
{
  $output = '';
   foreach ($tweets as $tweet) {
     $output .= <<<EOF


<div class="tweet">
<p>{$tweet->text}</p><br/>
<em>via {$tweet->source}</em>
</div>
EOF;
    }

}

}

and then inside your view scripts, you just call $this->twitterRecent($tweets) anywhere you want.

Just my two cents

++ Remy


On Mon, Apr 20, 2009 at 11:38 PM, Ryan Hagan <ryan@ryanhagan.net> wrote:
Cool, for most of the stuff I'm doing, I agree 100%.  But what about
reusing views?  I mean, this is an extremely simple case, but I really
don't want to have to copy and paste my HTML code from my
twitter.phtml page to my index.phtml page.  If I want to change the
div class I now have to remember to change it in two places, more as I
start to reuse the Twitter code in other areas of the site.

Also, headers and footers?  The view is going to be mostly the same
based on where I am on the site, but the content will change.  Again,
something like this would be desirable.

NavigationController extends Zend_Controller_Action
{
   public function indexAction()
   {
       $bc = new BreadCrumbs();
       $bc->add($referrer);
       $this->view->breadcrumb = $bc

       $this->view->menu = new Menu($ACL);
   }
}

SiteController extends Zend_Controller_Action
{
   public function headerAction()
   {
       $imgRotator = new RandImage();
       $this->view->logo = $imgRotator->getLogo();
       $this->view->background = $imgRotator->getBG();

       $this->view->nav = $this->_helper->actionStack('index', 'navigation');
   }
}

IndexController extends Zend_Controller_Action
{
   public function indexAction()
   {
       $this->view->header = $this->_helper->actionStack('header','site');
       $this->view->footer = $this->_helper->actionStack('footer','site');

       $this->view->tweets = $this->_helper->actionStack('recent', 'twitter');
       $this->view->blog = $this->_helper->actionStack('curmonth', 'blog');
       ...
   }
}

This could end up being a lot of View code that I don't want to
duplicate, but that easily gets reused all over the site.


On 4/20/09, Cory D. Wiles <kwylez@gmail.com> wrote:
> You don't need to use actions for twitter, blogs, et. al.  What you need to
> do is to create models for those and then assign those models to our view
> scripts.
>
> // Twitter Model
>
> class Twitter {
>
>   public function getRecentTweets() {}
>   .....
>   .....
> }
>
> IndexController extends Zend_Controller_Action
> {
>    public function indexAction()
>    {
>        $twitter = new Twitter();
>
>        $this->view->tweets = $twitter->getRecentTweets();
>    }
> }
>
> On Mon, Apr 20, 2009 at 3:03 PM, Ryan Hagan <ryan@ryanhagan.net> wrote:
>
>> Hello,
>>
>> I'm trying to figure out the best way to handle slightly (very
>> slightly) complex views with Zend and constantly running into a road
>> block.  I'm hoping you guys can help guide me down the right path
>> here.
>>
>> Basically, I have several elements that get used in different parts of
>> the system in different ways.  The elements are things like Twitter
>> updates, blog posts, current media, etc.  Each element has its own
>> view script which I want to include at higher levels.  For instance,
>> twitter updates get displayed in different places on my index page
>> than they do on my dedicated Twitter page, but the basic view is the
>> same in all cases.  It's the layout that is different.
>>
>> Here is some pseudo-code.  I'm primarily concerned with how to handle
>> the view aggregation from the controller side.
>>
>> TwitterController extends Zend_Controller_Action
>> {
>>    public function recentAction()
>>    {
>>        $this->view->headLink()->appendStylesheet('css/twitter.css');
>>        $twitter = new Zend_Service_Twitter('username','password');
>>        $this->view->tweets = $twitter->status->userTimeLine('me');
>>    }
>> }
>>
>> recent.phtml
>> <?php foreach ($this->tweets as $tweet) { ?>
>>    <div class="tweet">
>>        <p><?= $tweet->text ?></p><br/>
>>        <em>via <?= $tweet->source ?></em>
>>    </div>
>> <?php } ?>
>>
>>
>> IndexController extends Zend_Controller_Action
>> {
>>    public function indexAction()
>>    {
>>        $this->_helper->actionStack('recent', 'twitter');
>>        $this->_helper->actionStack('curmonth', 'blog');
>>        $this->_helper->actionStack('curlistening', 'media');
>>        $this->_helper->actionStack('curwatching', 'media');
>>        $this->_helper->actionStack('curreading', 'media');
>>    }
>> }
>>
>> index.phtml
>> <div id="blog-col">
>>    <?= $this->blog ?>
>> </div>
>>
>> <div id="whatnow-col">
>>    <?= $this->tweets ?>
>>    <?= $this->songs ?>
>>    <?= $this->shows ?>
>>    <?= $this->books ?>
>> </div>
>>
>>
>> Obviously, actionStack doesn't work like I want it to.  What I would
>> REALLY like, is something along these lines...
>>
>> IndexController extends Zend_Controller_Action
>> {
>>    public function indexAction()
>>    {
>>        $this->view->tweets = $this->_helper->actionStack('recent',
>> 'twitter');
>>        $this->view->blog = $this->_helper->actionStack('curmonth',
>> 'blog');
>>        $this->view->songs =
>> $this->_helper->actionStack('curlistening', 'media');
>>        $this->view->shows =
>> $this->_helper->actionStack('curwatching', 'media');
>>        $this->view->books = $this->_helper->actionStack('curreading',
>> 'media');
>>    }
>> }
>>
>>
>> Thank you!!
>>
>> --
>>
>> Ryan Hagan
>> ryan@ryanhagan.net
>>
>>
>
>
> --
> Cory Wiles
> kwylez@gmail.com
> http://www.corywiles.com/
> http://www.randomthoughtprocess.com/
>


--

Ryan Hagan
ryan@ryanhagan.net


没有评论: