Zend - refactoring to include a form globally on site
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 glo开发者_如何学JAVAbally 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?
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.
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)
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();
You can put an instance of Form_SearchForm to the registry
I probably have missed a very cool a simple way :)
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.
精彩评论