Symfony Form 的數(shù)據(jù)綁定功能是非常強(qiáng)大和方便的. 在之前的測試中已經(jīng)體現(xiàn)出來. 表單依據(jù)對象屬性來創(chuàng)建, 表單提交后, 數(shù)據(jù)自動綁定到對象屬性中. 這里有個小細(xì)節(jié)就是 Form 是通過對象的 Setter 方法來綁定數(shù)據(jù)到對象的. 這個地方對嚴(yán)謹(jǐn)?shù)拇a會引起異常. 這個在之前的已經(jīng)有提到過. Symfony4 表單驗(yàn)證 NULL 異常處理
在表單的使用過程中, 不同的框架對 Form 的指南有所不同, 在 Symfony 的用戶指南部分, 對表單的簡單介紹是通過自動綁定數(shù)據(jù)來介紹 Form 的功能. 在其他框架 比如: Zend Framework 來說. 則是比較單純的表單使用介紹. 從 Symfony 的官方表單指南來講, 這個是值得討論的地方.
-
使用 Form 的數(shù)據(jù)自動綁定模式
優(yōu)點(diǎn): 這種模式很方便, 對簡單的表單和數(shù)據(jù)處理簡潔.
缺點(diǎn): 和對象關(guān)聯(lián)的非常緊密, 如果對象定義被修改, 會涉及到 Form. -
不使用 Form 的數(shù)據(jù)綁定模式
優(yōu)點(diǎn): Form 的定義會更加的隨意性, 獨(dú)立維護(hù), 不受綁定的對象約束.
缺點(diǎn): Form 的數(shù)據(jù)需要手動的綁定到對象中去.
個人更推薦不使用 Form 的數(shù)據(jù)綁定模式, 如果一個 Form 設(shè)計(jì)到多個數(shù)據(jù)對象的更方便使用. 并且日常的項(xiàng)目中, 數(shù)據(jù)和業(yè)務(wù)邏輯的開發(fā)是分開的. Entity 等這種對象是會被工程師經(jīng)常修改的. 如果 Form 類和此類的對象進(jìn)行了綁定, 修改可能會導(dǎo)致 Form 異常.
我們來修改一下 UserType 類, 讓它脫離和 User 類的數(shù)據(jù)綁定.
- 先去掉
src/Entity/User.php中的驗(yàn)證聲明. 讓 User Entity 看起來更純粹.
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
*/
class User
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
*
* @ORM\Column(type="string", length=45)
*/
private $email = '';
/**
*
* @ORM\Column(type="string", length=32)
*/
private $passwd = '';
/**
* @ORM\Column(type="string", length=45)
*/
private $name = '';
//...
- 把表單的驗(yàn)證約束定義到表單類中. 繼續(xù)修改
src/Form/UserType.php
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email', EmailType::class, [
'empty_data' => '',
'constraints' => [
new NotBlank(['message' => 'Emaill address cannot be empty.']),
new Email(['message' => 'This email is not a valid email address.'])
]
])
->add('passwd', PasswordType::class, [
'empty_data' => '',
'constraints' => [
new NotBlank(['message' => 'Password cannot be empty character.']),
new Length([
'min' => 4,
'max' => 12,
'minMessage' => 'Your password must be at least {{ limit }} characters long',
'maxMessage' => 'Your password cannot be longer than {{ limit }} characters',
])
]
])
->add('name', TextType::class, [
'empty_data' => '',
'constraints' => [
new NotBlank(['message' => 'Your name cannot be empty.']),
new Length([
'min' => 2,
'max' => 12,
'minMessage' => 'Your name must be at least {{ limit }} characters long',
'maxMessage' => 'Your name cannot be longer than {{ limit }} characters',
])
]
])
->add('save', SubmitType::class)
;
}
}
- 在控制器中, 手動進(jìn)行數(shù)據(jù)綁定.
public function signUp(Request $request)
{
//創(chuàng)建用戶注冊表單對象
$form = $this->createForm(UserType::class);
//監(jiān)聽表單請求
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//提取表單數(shù)據(jù).
$data = $form->getData();
//綁定數(shù)據(jù)到用戶對象
$user = new User();
$user->setName($form->get('name')->getData());
$user->setEmail($form->get('email')->getData());
$user->setPasswd($form->get('passwd')->getData());
$user->setExpired(new \DateTime());
$user->setResetPasswdExpired(new \DateTime());
$user->setCreated(new \DateTime());
//持久化到數(shù)據(jù)庫
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
return $this->redirectToRoute('url_home');
//dump($user);
} else {
dump($form->getErrors());
}
return $this->render('default/sign-up.html.twig', [
'form' => $form->createView(),
]);
}
如此, 用戶對象發(fā)生改變的時候, 對 Form 的影響是非常少的. 也便于開發(fā) Form 的同學(xué)維護(hù)和重復(fù)利用.