问题
Hy, I'm really new to Zend-Framework 3 and I'm practicing OOP, I can't find a simple explanation/tutorial on making a Zend Form with a fieldset and legend. Basically I'm trying to create this in HTML:
<form name="my_name">
<fieldset>
<legend>My legend value</legend>
<input type="checkbox" name="name_1" value="value_1">Value 1</input>
<input type="checkbox" name="name_2" value="value_2">Value_2</input>
<input type="checkbox" name="name_3" value="value_3">Value_3</input>
</fieldset>
<input type="button" value="Get values" id="btn"/>
</form>
I checked the official documentation about Zend Forms and Collections and Fieldsets, but it's really confusing me. Any help would be greatly appreciated.
回答1:
First, I am sorry as it is going to be a bit long one. But this would describe the form in action. So be patient please!
Assuming you are known to ZF3 default Application
module. Some folders are created in the Application
module for separation of each element. You need to create them as follows.
Let's get started by creating your fieldsets first. Zend\Form\Fieldset
component represents a reusable set of elements and is dependent on Zend\From\Form
component. This means you need to attach this to Zend\Form\Form
.
module/Application/src/Form/Fieldset/YourFieldset.php
<?php
namespace Application\Form\Fieldset;
use Zend\Form\Element;
use Zend\Form\Fieldset;
class YourFieldset extends Fieldset
{
public function __construct($name = null)
{
parent::__construct('your-fieldset');
$this->add([
'name' => 'name_1',
'type' => Element\Checkbox::class,
'options' => [
'label' => 'Value 1',
'use_hidden_element' => true,
'checked_value' => 'yes',
'unchecked_value' => 'no',
],
'attributes' => [
'value' => 'no',
],
]);
// Creates others as your needs
}
}
Now we would create the form using Zend\From\Form
attaching the fieldset created from Zend\From\Fieldset
.
module/Application/src/Form/YourForm.php
<?php
namespace Application\Form;
use Application\Form\Fieldset\YourFieldset;
use Zend\Form\Form;
class YourForm extends Form
{
public function __construct($name = null)
{
parent::__construct('your-form');
$this->add([
// This name will be used to fetch each checkbox from
// the CheckboxFieldset::class in the view template.
'name' => 'fieldsets',
'type' => YourFieldset::class
]);
$this->add([
'name' => 'submit',
'attributes' => [
'type' => 'submit',
'value' => 'Get Values',
'class' => 'btn btn-primary'
],
]);
}
}
Our from is almost ready. We need to make it serviceable if we want it to be used in any action of a controller. So let's do that.
Update your module config file. If service_manager
key does not exist then add the following snippet of code, otherwise, update only factories
and aliases
key as the following.
Fix namespaces in module config file.
module/Application/config/module.config.php
'service_manager' => [
'factories' => [
// Form service
Form\YourForm::class => Zend\ServiceManager\Factory\InvokableFactory::class,
// Other services
],
'aliases' => [
// Make an alias for the form service
'YourForm' => Form\YourForm::class,
],
],
Now the form is ready to be used. This needs to be injected into our controller. As I am working on Application
module, I would inject the form into the IndexController::class
's constructor. Then we would be using that form inside IndexController::fieldsetAction()
method.
module/Application/src/Controller/IndexController.php
<?php
namespace Application\Controller;
use Zend\Form\FormInterface;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class IndexController extends AbstractActionController
{
protected $YourForm;
public function __construct(FormInterface $YourForm)
{
$this->YourForm = $YourForm;
}
public function fieldsetAction()
{
$request = $this->getRequest();
$viewModel = new ViewModel(['form' => $this->YourForm]);
if (! $request->isPost()) {
return $viewModel;
}
$this->YourForm->setData($request->getPost());
if (! $this->YourForm->isValid()) {
return $viewModel;
}
$data = $this->YourForm->getData()['fieldsets'];
echo '<pre>';
print_r($data);
echo '</pre>';
return $viewModel;
}
}
As this controller is taking argument in its constructor, we need to create a factory for this controller (a factory creates other objects).
module/Application/src/Factory/Controller/IndexControllerFactory.php
<?php
namespace Application\Factory\Controller;
use Application\Controller\IndexController;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class IndexControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
// We get form service via service manager here
// and then inject controller's constructor
$YourForm = $container->get('YourForm');
return new IndexController($YourForm);
}
}
Once again, we need to update the module config file. We would add this time the factory under controllers
key as follows
'controllers' => [
'factories' => [
Controller\IndexController::class => Factory\Controller\IndexControllerFactory::class,
],
],
At the end, echo the form in the view template as follows:
module/Application/view/application/index/fieldset.phtml
<h1>Checkbox Form</h1>
<?php
$form = $this->form;
$form->setAttribute('action', $this->url());
// Here is the catch, remember this name from the CheckboxForm::class
$fieldset = $form->get('fieldsets');
$name_1 = $fieldset->get('name_1');
$name_2 = $fieldset->get('name_2');
$name_3 = $fieldset->get('name_3');
$submit = $form->get('submit');
$submit->setAttribute('class', 'btn btn-primary');
$form->prepare();
echo $this->form()->openTag($form);
?>
<fieldset>
<legend>My legend value</legend>
<?= $this->formElement($name_1) ?>
<?= $this->formLabel($name_1) ?>
<?= $this->formElement($name_2) ?>
<?= $this->formLabel($name_2) ?>
<?= $this->formElement($name_3) ?>
<?= $this->formLabel($name_3) ?>
<?= $this->formSubmit($submit) ?>
</fieldset>
<?php
echo $this->form()->closeTag();
Hope this would help you!
回答2:
Actually the example you are looking for is in "collections" part of zend form. Its not the exact one but kinda like.
Here you are a little example. I ignored namespaces and hope so there's no typo :)
class myFieldset extends Fieldset {
public function init(){
$this
->add([
'name' => 'name_1,
'type' => 'text',
])
->add([
'name' => 'name_2,
'type' => 'text',
])
->add([
'name' => 'name_3,
'type' => 'text',
]);
}
}
class MyForm extends Form {
public function init(){
$this->add([
'type' => myFieldset,
'name' => 'fieldset'
])->add([
'type' => 'button',
'name' => 'action'
]);
}
}
And in view file;
<?=$this-form($form);?>
来源:https://stackoverflow.com/questions/47149722/zend-framework-3-form-fieldset