Po experimentování s frameworkem Nette jsem si oblíbil event-driven přístup k formulářům. Proto jsem zde pro své čtenáře připravil jednoduchý způsob, jak jednoduchý přístup k formulářům implementovat i v Zend_Form.
Rešení není zcela dokonalé, mezi hlavní nevýhody patří to, že je nápad omezen na jednoduchý výčet několika Zend_Form_Elementů, zatímco Vy si mužete elementu, které mužou zpusobit submit, nadefinovat nekonečno. Další problém, na který jsem narazil, byl v Zend_Registry v metodě offsetExists, kde jsem musel explicitne přetypovat $this na pole (return array_key_exists($index, (Array)$this);). Testováno na PHP 5.3.0alpha3-dev a Zend Frameworku 1.7.0.
Tak zde je kód:
set_include_path("library" . PATH_SEPARATOR . get_include_path());
require "Zend/Form.php";
require "Zend/View.php";
class MyForm extends Zend_Form
{
/**
* @param string|Array $callback
* @param string $name
* @return mixed
*/
public function onClick($callback, $name)
{
$post = $_POST;
if (! array_key_exists($name, $post) || ! in_array($name, $post))
return false;
if (! $this->isValid($post))
return false;
$element = $this->getElement($name);
$type = $element->getType();
$types = array(
"Zend_Form_Element_Submit",
"Zend_Form_Element_Input",
"Zend_Form_Element_Button",
"Zend_Form_Element_Image"
);
if (in_array($type, $types))
return call_user_func($callback, $this);
else
return false;
}
/**
* @param string|Array $callback
* @return mixed
*/
public function onSubmit($callback)
{
$post = $_POST;
$found = false;
$elements = $this->getElements();
foreach ($elements as $element)
{
if (array_key_exists($element->getName(), $post))
$found = true;
}
if (! $found)
return false;
if ( !$this->isValid($post))
return false;
$elements = $this->getElements();
foreach ($elements as $element)
{
if (! array_key_exists($element->getName(), $post))
continue;
$type = $element->getType();
$types = array(
"Zend_Form_Element_Submit",
"Zend_Form_Element_Input",
"Zend_Form_Element_Button",
"Zend_Form_Element_Image"
);
if (in_array($type, $types))
return call_user_func($callback, $this);
}
return false;
}
}
function submit1_click(MyForm $form)
{
$text = $form->getElement("text")->getValue();
echo "submit1_click: {$text}<br />";
}
function submit2_click(MyForm $form)
{
$text = $form->getElement("text")->getValue();
echo "submit2_click: {$text}<br />";
}
function myform_submit(MyForm $form)
{
$text = $form->getElement("text")->getValue();
echo "myform_submit: {$text}<br />";
}
$form = new MyForm;
$form->addElement("text", "text", array("required"=>true));
$form->addElement("submit", "submit1");
$form->addElement("submit", "submit2");
$form->addElement("submit", "submit3");
$form->onClick("submit1_click", "submit1");
$form->onClick("submit2_click", "submit2");
$form->onSubmit("myform_submit");
echo $form->render(new Zend_View);
Jak můžete vidět, celé je to velmi jednoduché. Již jsem tento přístup (mírně obměněný) použil i v praxi a skutečně se mi osvědčil.
Další proti: Při ukládání pravděpodobně použijete $form->getValues(), která ale prožené funkci definovanými filtry, takže hodnoty, které budete validovat, se mohou lišit.