发布于 2015-08-27 16:54:19 | 176 次阅读 | 评论: 0 | 来源: 网络整理
The Form component can guess the type and some options of a form field by using type guessers. The component already includes a type guesser using the assertions of the Validation component, but you can also add your own custom type guessers.
In this section, you are going to build a guesser that reads information about
fields from the PHPDoc of the properties. At first, you need to create a class
which implements FormTypeGuesserInterface.
This interface requires 4 methods:
guessType() -
tries to guess the type of a field;guessRequired() -
tries to guess the value of the required
option;guessMaxLength() -
tries to guess the value of the max_length
option;guessPattern() -
tries to guess the value of the pattern
option.Start by creating the class and these methods. Next, you’ll learn how to fill each on.
namespace AcmeForm;
use SymfonyComponentFormFormTypeGuesserInterface;
class PHPDocTypeGuesser implements FormTypeGuesserInterface
{
public function guessType($class, $property)
{
}
public function guessRequired($class, $property)
{
}
public function guessMaxLength($class, $property)
{
}
public function guessPattern($class, $property)
{
}
}
When guessing a type, the method returns either an instance of
TypeGuess or nothing, to determine
that the type guesser cannot guess the type.
The TypeGuess constructor requires 3 options:
entity, you also
want to set the class option). If no types are guessed, this should be
set to an empty array;Guess class:
LOW_CONFIDENCE, MEDIUM_CONFIDENCE, HIGH_CONFIDENCE,
VERY_HIGH_CONFIDENCE. After all type guessers have been executed, the
type with the highest confidence is used.With this knowledge, you can easily implement the guessType method of the
PHPDocTypeGuesser:
namespace AcmeForm;
use SymfonyComponentFormGuessGuess;
use SymfonyComponentFormGuessTypeGuess;
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('text', 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('integer', array(), Guess::MEDIUM_CONFIDENCE);
case 'float':
case 'double':
case 'real':
return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE);
case 'boolean':
case 'bool':
return new TypeGuess('checkbox', array(), Guess::HIGH_CONFIDENCE);
default:
// there is a very low confidence that this one is correct
return new TypeGuess('text', 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;
}
}
This type guesser can now guess the field type for a property if it has PHPdoc!
The other 3 methods (guessMaxLength, guessRequired and
guessPattern) return a ValueGuess
instance with the value of the option. This constructor has 2 arguments:
Guess class).null is guessed when you believe the value of the option should not be
set.
警告
You should be very careful using the guessPattern method. When the
type is a float, you cannot use it to determine a min or max value of the
float (e.g. you want a float to be greater than 5, 4.512313 is not valid
but length(4.512314) > length(5) is, so the pattern will succeed). In
this case, the value should be set to null with a MEDIUM_CONFIDENCE.
The last thing you need to do is registering your custom type guesser by using
addTypeGuesser() or
addTypeGuessers():
use SymfonyComponentFormForms;
use AcmeFormPHPDocTypeGuesser;
$formFactory = Forms::createFormFactoryBuilder()
// ...
->addTypeGuesser(new PHPDocTypeGuesser())
->getFormFactory();
// ...
注解
When you use the Symfony framework, you need to register your type guesser
and tag it with form.type_guesser. For more information see
the tag reference.