views:

95

answers:

3

I currently have a search form in the search controller, so the only way I can get to it is through /search/. I have to refactor my code so that this search form appears not only in the Search Controller but also globally throughout the site.

( The code isnt exact as I had to retype some of it )

My class that extends Zend_Form is located in application/forms/forms/SearchForm.php:

class Form_SearchForm extends Zend_Form {

    public function init() {};

}

My search controller is something like..

class SearchController extends Zend_Controller_Action
{
    public function search() {
        $searchForm = new Form_SearchForm();
        $this->view->form = $searchForm;
    }
}

In my Bootstrap.php I have an autoloader for models:

protected function _initAutoload() {
    $autoLoader = Zend_Loader_Autoloader::getInstance();
    $resourceLoader = new Zend_Loader_Autoloader_Resource(
        array(
     'basePath' => APPLICATION_PATH,
     'namespace' => '',
     'resourceTypes' => array(
         'form' => array(
      'path' => 'forms',
      'namespace' => 'Form_',
         ),
         'model' => array(
      'path' => 'models/',
      'namespace' => 'Model_',
         ),
     ),
        )
    );

return $autoLoader;

}

I'm wondering where I can store my code so that globally the search form is generated in the view.

My global layout file is located in application/layouts/scripts/layout.phtml and currently spits out a dynamic content area:

<div id="main">
    <?php echo $this->layout()->content;?>
</div>

Should I just add the form to this layout.phtml or is there some generic controller I should use?

Edit: Sorry for not specifying this too, but what if for example I wanted to not include it for 1-2 special pages ( maybe an admin section ).. if I hardcoded it into layout.phtml it would still appear.. or should I serve a different layout file to say, an admin area?

+2  A: 
  1. You can create your Form in a Controller Plugin and add it to view vars somehow (by Zend_Controller_Front?), which are accessible in layout, too. But it's too complicated in current ZF version (or I'm too dumb)

  2. You can make Form_SearchForm a singleton

    class Form_SearchForm ... {
         static function getInstance() {
              static $instance;
              if (!$instance)
                  $instance = new Form_SearchForm();
              return $instance;
         }
    }
    

    Now instead of creating new Form_SearchForm() just get it as

    $form = Form_SearchForm::getInstance();
    
  3. You can put an instance of Form_SearchForm to the registry

  4. I probably have missed a very cool a simple way :)

valya
I'm sorry you lost me, do you mind expanding on that and dumbing it down for my newbie-self?
meder
which option do you prefer? I don't think I know the right way. But the most right, I think, is the first, but It's too complicated now.
valya
make a class a singleton is simple, I'll add a code for that now. How to add an instance of Form_SearchForm to the Zend_Registry you can figure out by yourself :)
valya
Just curious, what do you achieve by making it a singleton?
Richard Nguyen
Richard Nguyen exactly what's needed: I'm making sure it will be created only once, so if the form was processed it will store values and validation results
valya
+1  A: 

I would split it into a partial and a place holder.

in layout.phtml:

<?php if($searchForm = $this->placeHolder('searchForm'): ?>
  <?php echo $searchForm; ?>
<?php endif; ?>

then in your views you can call:

<?php $this->placeHolder('searchForm')->set($this->partial('search-from.phtml', 'search')); ?>

IF you wanted you could even make a search view helper that basically does the place holder call.

The Controller plugin would be better if you have more pages that dont need it than d though. I would still probably use placeholder though to accomplish it. That way you can easily override or append to it later on a view-by-view basis without calling anything on the front controller.

prodigitalson
How would he use the form from controller?
valya
you have access to the view and thus the view helpers controller.if you are talking about actually constructing the from with a Zend_Form then instead of calling the partial helper you could call the action helper going to the Search_Controller. assuming $view is a Zend_View instance... and 'form' is the name of the action which outputs the form...$view->placeHolder('searchForm')->set($view->action('form', 'search', 'default));
prodigitalson
sorry I'm confused, would I have to have the second code snippet in every single view?
meder
Yes, any view you want the form to appear on. IF you have more views that have it than dont have it then an front controller plugin is easier... less maintenance.
prodigitalson
+3  A: 

Creating a searchAction() is not good for performance because it requires a brand new dispatch cycle. If, and only if, you have very complex logic that justifies a separate action, you could create a Controller Plugin and add searchAction() to the ActionStack. If you are only instantiating/assigning the form or if you don't need the search form for every request, it's not an optimal solution.


Another possibility would be to instantiate and assign the form in the bootstrap. This kind-of breaks separation of concerns, but provides better performance.

protected function _initSearchForm()
{
    $this->bootstrap('view');

    $view = $this->getResource('view');
    $searchForm = new Form_SearchForm();

    $view->searchForm = $searchForm;
    return $searchForm;
}


Finally, my preferred solution would be a custom view helper:

<?php

class My_View_Helper_SearchForm extends Zend_View_Helper_Abstract
{
    public function searchForm()
    {
        $searchForm = new Form_SearchForm();
        return $searchForm;
    } 
}

For either of these solutions, you'd ideally output the form in your layout file to minimise duplication.

layout.phtml:

<?php echo $this->searchForm() ?>

And create an alternate layout admin.phtml for admin area pages. This gives you the flexibility to change the admin pages significantly when new requirements pop up.

Richard Nguyen