I’ve got a form that looks like this:
class Cas_Form_Company extends Zend_Form
{
/**
* @param Cas_Model_Company|null $company
*/
public function __construct(Cas_Model_Company $company = null)
{
parent::__construct();
$id = new Zend_Form_Element_Hidden('id');
$name = new Zend_Form_Element_Text('name');
$name->addValidator('stringLength', false, array(2,45));
$name->addValidator(new Cas_Model_Validate_CompanyUnique());
$name->setLabel('Name');
$submit = new Zend_Form_Element_Submit('Submit');
if ($company)
{
$id->setValue($company->GetId());
$name->setValue($company->GetName());
}
$this->addElements(array($id, $name, $submit));
$this->setMethod('post');
$this->setAction(Zend_Controller_Front::getInstance()->getBaseUrl() . '/Asset/company');
}
public function Commit()
{
if (!$this->valid())
{
throw new Exception('Company form is not valid.');
}
$data = $this->getValues();
if (empty($data['id']))
{
Cas_Model_Gateway_Company::Create($data['name']);
}
else
{
$company = Cas_Model_Gateway_Company::FindById((int)$data['id']);
$company->SetName($data['name']);
Cas_Model_Gateway_Company::Commit($company);
}
}
}
Now, this form depends on a controller, which looks something like this:
public function companyAction()
{
if ($this->getRequest()->isPost())
{
if ($this->getRequest()->getParam('submit') == 'Delete')
{
Cas_Model_Gateway_Company::Delete(Cas_Model_Gateway_Company::FindById((int)$this->getRequest()->getParam('id')));
$this->_helper->redirector->setCode(303)->gotoSimple('companies');
}
$form = new Cas_Form_Company();
if ($form->isValid($this->getRequest()->getParams()))
{
$form->Commit();
$this->_helper->redirector->setCode(303)->gotoSimple('index');
}
$this->view->form = $form;
}
else if ($id = $this->getRequest()->getParam('id'))
{
$form = new Cas_Form_Company(Cas_Model_Gateway_Company::FindById($id));
$this->view->form = $form;
}
else
{
$this->view->form = new Cas_Form_Company();
}
$this->_helper->viewRenderer->setScriptAction('formrender');
}
It seems like the controller action is doing “too much” here, but I don’t see an easy way to work around this. Generally speaking, I think the form should be the one worried about whether it’s an add or edit or delete operation. But I can’t seem to find a good way of going about doing that.
Is this a normal pattern for someone using Zend_Form or have I done something wrong?
That’s perfectly fine, all you are doing is sending values to your form and handling the response, redirecting a bit and handling the view.
Each of these things fits really good and would be a hassle to find if you’ve placed them elsewhere. I wouldn’t think of “fat controllers” as in “requires more LOC than other controllers/actions” but rather “contains business logic”. If you feel the cyclomatic complexity is becoming too large, try splitting your action into smaller ones.
edit: Actually, I would refactor the
$form->Commit();part to something like$repository->create($form->getValues()since a) nothing internal is used inCas_Form_Company::Commit(), and; b) you will want to have storage related functions separated from validating & displaying your form. Think about debugging/changing the way your data is stored and you will now where to look if all f.ex. classes containing queries are doing that and only that – handling the DAL.