创建自定义的类型猜测器
通过使用type guesser(类型猜测器),表单组件可以猜出字段的“类型及部分选项”。本组件自带了一个“使用Validator组件的assertions(断言)”的type guesser,但你也可以添加自定义的type guesser。
创建一个PHPDoc Type Guesser ¶
本节,你要建立一个guesser,可以从属性上面的PHPDoc中读取字段信息。首先,你要创建一个类,令其实现FormTypeGuesserInterface
接口。该接口有4个方法:
guessType()
- 尝试猜测一个字段类型;guessRequired()
- 尝试猜测一个required选项;guessMaxLength()
- 尝试猜测一个maxlength
input属性的值;guessPattern()
- 尝试猜测pattern
input属性的值。
先用这几个方法把类建立起来。然后,你要学习如何填充每个方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
namespace Acme\Form;
use Symfony\Component\Form\FormTypeGuesserInterface;
class PHPDocTypeGuesser implements FormTypeGuesserInterface
{
public function guessType($class, $property)
{
}
public function guessRequired($class, $property)
{
}
public function guessMaxLength($class, $property)
{
}
public function guessPattern($class, $property)
{
}
} |
类型猜测 ¶
猜测一个类型时,方法返回的是TypeGuess
实例,或什么也不返回以确定guesser不能猜测出这个类型。
TypeGuess
类的构造器有三个参数:
类型的名称(需是form types之一);
附加选项(例如,当类型是
entity
时,你同时希望设置其class
选项)。如果没有任何类型被猜中,此处被设置为一个空数组;猜出来的类型“有多正确”之confidence(自信度)。它可以是
Guess
类中的常量里的一个:LOW_CONFIDENCE
,MEDIUM_CONFIDENCE
,HIGH_CONFIDENCE
,VERY_HIGH_CONFIDENCE
。当所有的guessers都被执行过之后,最高自信度的类型将被采纳。
在这些知识的帮助下,你可以去实现PHPDocTypeGuesser
的guessType
方法了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
namespace Acme\Form;
use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Guess\TypeGuess;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
class PHPDocTypeGuesser implements FormTypeGuesserInterface
{
public function guessType($class, $property)
{
$annotations = $this->readPhpDocAnnotations($class, $property);
if (!isset($annotations['var'])) {
return; // guess nothing if the @var annotation is not available
}
// otherwise, base the type on the @var annotation
switch ($annotations['var']) {
case 'string':
// there is a high confidence that the type is text when
// @var string is used
return new TypeGuess(TextType::class, array(), Guess::HIGH_CONFIDENCE);
case 'int':
case 'integer':
// integers can also be the id of an entity or a checkbox (0 or 1)
return new TypeGuess(IntegerType::class, array(), Guess::MEDIUM_CONFIDENCE);
case 'float':
case 'double':
case 'real':
return new TypeGuess(NumberType::class, array(), Guess::MEDIUM_CONFIDENCE);
case 'boolean':
case 'bool':
return new TypeGuess(CheckboxType::class, array(), Guess::HIGH_CONFIDENCE);
default:
// there is a very low confidence that this one is correct
return new TypeGuess(TextType::class, array(), Guess::LOW_CONFIDENCE);
}
}
protected function readPhpDocAnnotations($class, $property)
{
$reflectionProperty = new \ReflectionProperty($class, $property);
$phpdoc = $reflectionProperty->getDocComment();
// parse the $phpdoc into an array like:
// array('type' => 'string', 'since' => '1.0')
$phpdocTags = ...;
return $phpdocTags;
}
} |
猜测字段选项 ¶
另外3个方法(guessMaxLength()
,guessRequired()
,guessPattern()
)返回的是带有选项值的ValueGuess
实例。其构造器有2个参数:
选项的值;
所猜之值有多正确的“自信度”(使用
Guess
类中的常量)。
若猜为null
则表示你认为这个选项不应该被设置。
你应该非常小心地使用guessPattern()
方法。当类型是float时,你不能用它来决断这个浮点的min值或max值(比如,你希望一个浮点大于5
,那么4.512313
是无效的,不过length(4.512314) > length(5)
却是有效的,进而匹配成功)。在这个例子中,参数的取值应该分别设为null
和MEDIUM_CONFIDENCE
。
注册一个type gueesser ¶
你要做的最后一件事,是用addTypeGuesser()
方法或addTypeGuessers()
方法来注册你的自定义type guesser:
1 2 3 4 5 6 7 8 9 |
use Symfony\Component\Form\Forms;
use Acme\Form\PHPDocTypeGuesser;
$formFactory = Forms::createFormFactoryBuilder()
// ...
->addTypeGuesser(new PHPDocTypeGuesser())
->getFormFactory();
// ... |
使用Symfony框架时,需要注册你的type guesser,并为它打上form.type_guesser
标签。更多信息请阅读tag参考。