Page 1 of 1

Best practices with Zend Framework

Posted: Wed Apr 23, 2008 6:46 am
by shiznatix
Ok as I said earlier, I think I need some guidance with the Zend Framework. I am using the Zend Framework because my company demanded that I use a framework that other people would know incase I got hit by a bus or something so I chose Zend.

Here is how I go about doing stuff with it. I have my bootstrap file and calls everything and all that figured out no problem. I am also using PHPtal as my templating engine with my own translation system worked in. I have 1 main template class for the different main templates (admin side, users side, and another for different sections) so what really happens when a page is loaded is that the controller for that page loads the inner content, then passes it on to the main template which builds itself and just throws the passed content in the main body of the page. All is well.

Were I think I am having a problem is in my controller section. Here is how a controller of mine might look (this is just a general idea)

Code: Select all

 
<?php
 
class NewsController extends Zend_Controller_Action
{
    private $NEWS;
    
    private $TEMPLATES;
    
    private $title;
    
    public function init()
    {
        Zend_Loader::loadClass('News');
        $this->NEWS = new News;
                
        Zend_Loader::loadClass('Templates');
        $this->TEMPLATES = new Templates;
 
        $this->c = new Zend_View_Phptal;
        $this->c->setScriptPath(Zend_Registry::get('config')->paths->view->path);
        
        Functions::loadLanguageFile('user/news/view');
        
        $this->title = '';
    }
    
    public function indexAction()
    {
        $news = $this->NEWS->fetchAll(null, 'id DESC');
        
        if (!count($news))
 
        {
 
            $template['isNews'] = false;
 
            $template['newsContent'] = USERS_ARTICLES_THERE_ARE_CURRENTLY_NO_ARTICLES;
 
        }
 
        else
 
        {
 
            $template['isNews'] = true;
 
 
 
            foreach ($news as $headline)
 
            {
                $template['newsContent'][] = array(
                    'headline'   => $headline->headline,
                    'shortStory' => Functions::substrAtWord($headline->short_story, 140),
                    'viewHref'   => 'news/'.$headline->url_headline.'/',
                );
 
            }
 
        }
        
        $this->c->set('USERS_NEWS_RAKEBACK_COM_NEWS', USERS_NEWS_RAKEBACK_COM_NEWS);
 
        $this->c->set('USERS_NEWS_READ_MORE',         USERS_NEWS_READ_MORE);
 
 
 
        $this->c->set('isNews',      $template['isNews']);
 
        $this->c->set('newsContent', $template['newsContent']);
        
        try
        {
            $this->TEMPLATES->main($this->c->render('user/news/index.html'), $this->title);
        }
        catch (exception $e)
        {
            dump($e);
            die();
        }
    }
}
 
Now originally this seamed to be fine any dandy. The problem comes when I start having ajax make calls to this and having their own "action" and then saving/updating the database with the error checking for each field...my files can become quite long and it seams a bit much.

What I was doing in my home-grown templating system was I would have the templates then a view class then a controller class then a model class (if that particular section has a table to go with it). I would set all the variables in the view class that would be passed to the template. If someone submitted a forum or passed an action, that action would be processed in the controller class that would do all the other work but wouldn't be loaded unless it was needed. Right now with the larger controllers I am loading a several thousand line file of which very little will be used. It's not so much a problem of file length as it is of maintaining such a huge file. It gets bad, and it was better when things were separate.

A quick skeleton of what a bigger file would look like is this:

Code: Select all

 
<?php
 
class UsermapController extends Zend_Controller_Action
{
    public function init()
    {
    }
    
    public function indexAction()
    {
    }
    
    public function searchAction()
    {
    }
    
    public function downloadAsCSVAction()
    {
    }
    
    public function chooseEmailAction()
    {
    }
    
    //this method is only called through ajax
    public function approveDenyAction()
    {
    }
    
    public function commentsAction()
    {
    }
    
    //this method is only called through ajax
    public function updateCommentsAction()
    {
    }
    
    //this method is only called through ajax
    public function onHoldAction()
    {
    }
    
    //this method is only called through ajax
    public function updateUsernameAction()
    {
    }
    
    //this method is only called through ajax
    public function updateAdditionalFieldAction()
    {
    }
    
    //this method is only called through ajax
    public function getEmailBodyAction()
    {
    }
    
    private function _getUserInfoFromQuery($usermap, $show)
    {
    }
    
    private function _setEmailVariables($email, $fields)
 
    {
 
    }
}
 
which each function being roughly 50 to 300 lines, this is a bit much. This file alone with full code is 1244 lines but thats not even the biggest or the most complex.

So what would be a better way to go about this? Why does this just feel so dirty to me?

Re: Best practices with Zend Framework

Posted: Wed Apr 23, 2008 9:02 am
by John Cartwright
If your worried about your controllers getting too long, you could subclass them into more specific objects. Although 1200 lines for a controller seems to be very large. My controllers usually never exceed 2-300 lines of code, since generally the controller should not be doing all that much in the first place.

Re: Best practices with Zend Framework

Posted: Wed Apr 23, 2008 11:23 am
by Maugrim_The_Reaper
1. Do not use Zend_Loader::loadClass(). Either require the class directly in the PHP header, or use autoloading. Most of Zend_Loader is a deep dark cavern of totally unnecessary and very costly checking and validation.

2. Is there any way of pushing translations into the templates? They will be one source of controller bloat over time. That's one of the main reasons Zend_Translate finally got a View Helper before people's controllers and custom solutions imploded ;).

3. Personal quirk - I try to avoid capitalised variable names simply because it reduces my typing fingers by 5 each time.

4. You could try and eliminate some of the View setup/assignment/render calls by introducing something like the built in ViewRenderer Action plugin. Usually I have disliked the ViewRenderer but it seems over the months somebody got around to refactoring it into something approaching an understandable class.

Code: Select all

$this->c->set('USERS_NEWS_RAKEBACK_COM_NEWS', USERS_NEWS_RAKEBACK_COM_NEWS);
 
$this->c->set('USERS_NEWS_READ_MORE', USERS_NEWS_READ_MORE);
5. Somebody may kill you for this ;). Again, if you push translation into the templates in some way, you can reduce the amount of crud in controllers, and simplify how translation works. I like seeing something like:

Code: Select all

<? echo $this->_('USERS_NEWS_READ_MORE') ?>

Re: Best practices with Zend Framework

Posted: Mon May 05, 2008 7:22 am
by shiznatix
Maugrim_The_Reaper wrote:

Code: Select all

$this->c->set('USERS_NEWS_RAKEBACK_COM_NEWS', USERS_NEWS_RAKEBACK_COM_NEWS);
$this->c->set('USERS_NEWS_READ_MORE', USERS_NEWS_READ_MORE);
5. Somebody may kill you for this ;). Again, if you push translation into the templates in some way, you can reduce the amount of crud in controllers, and simplify how translation works. I like seeing something like:

Code: Select all

<? echo $this->_('USERS_NEWS_READ_MORE') ?>
The problem with this is I am kinda married to PHPtal and it just won't let me do stuff like put php directly into code. Maybe I should move away from it but it seams to be so damn helpful when dealing with designers who know nothing about php and tend to just break stuff.

Also, what is thie built in ViewRenderer Action plugin you speak so highly of?
Jcart wrote:If your worried about your controllers getting too long, you could subclass them into more specific objects. Although 1200 lines for a controller seems to be very large. My controllers usually never exceed 2-300 lines of code, since generally the controller should not be doing all that much in the first place.
The biggest problem with my controllers is variable assignment to be passed to the template. If I want all the news items that are active I have to build the query, run it, check if there even are any, then setup the template variables. This makes my views get big quite quick. I don't think subclassing anything would help except just to put things into smaller files but then again, I guess thats what you are giving me advice on so yeah.