建立自訂類型猜測器
表單組件可以透過使用類型猜測器來猜測表單欄位的類型和某些選項。此組件已包含使用驗證組件的斷言的類型猜測器,但您也可以新增自己的自訂類型猜測器。
猜測器僅在下列情況下使用
- 使用 createForProperty() 或 createBuilderForProperty();
- 在父表單已定義資料類別的情境中,呼叫 add() 或 create() 或 add() 時沒有明確的類型。
建立 PHPDoc 類型猜測器
在本節中,您將建置一個猜測器,從屬性的 PHPDoc 讀取欄位相關資訊。首先,您需要建立一個實作 FormTypeGuesserInterface 的類別。此介面需要四個方法
- guessType()
- 嘗試猜測欄位的類型;
- guessRequired()
- 嘗試猜測 required 選項的值;
- guessMaxLength()
- 嘗試猜測
maxlength
輸入屬性的值; - guessPattern()
- 嘗試猜測
pattern
輸入屬性的值。
從建立類別和這些方法開始。接下來,您將學習如何填寫每個方法
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
// src/Form/TypeGuesser/PhpDocTypeGuesser.php
namespace App\Form\TypeGuesser;
use Symfony\Component\Form\FormTypeGuesserInterface;
use Symfony\Component\Form\Guess\TypeGuess;
use Symfony\Component\Form\Guess\ValueGuess;
class PhpDocTypeGuesser implements FormTypeGuesserInterface
{
public function guessType(string $class, string $property): ?TypeGuess
{
}
public function guessRequired(string $class, string $property): ?ValueGuess
{
}
public function guessMaxLength(string $class, string $property): ?ValueGuess
{
}
public function guessPattern(string $class, string $property): ?ValueGuess
{
}
}
猜測類型
在猜測類型時,此方法會傳回 TypeGuess 的執行個體,或不傳回任何內容,以判斷類型猜測器無法猜測類型。
TypeGuess
建構子需要三個選項
- 類型名稱(表單類型之一);
- 其他選項(例如,當類型為
entity
時,您也會想要設定class
選項)。如果未猜測到任何選項,則應將其設定為空陣列; - 猜測類型正確的信心程度。這可以是 Guess 類別的常數之一:
LOW_CONFIDENCE
、MEDIUM_CONFIDENCE
、HIGH_CONFIDENCE
、VERY_HIGH_CONFIDENCE
。在執行所有類型猜測器之後,將會使用信心程度最高的類型。
有了這些知識,您可以實作 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
// src/Form/TypeGuesser/PhpDocTypeGuesser.php
namespace App\Form\TypeGuesser;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Guess\TypeGuess;
class PhpDocTypeGuesser implements FormTypeGuesserInterface
{
public function guessType(string $class, string $property): ?TypeGuess
{
$annotations = $this->readPhpDocAnnotations($class, $property);
if (!isset($annotations['var'])) {
return null; // guess nothing if the @var annotation is not available
}
// otherwise, base the type on the @var annotation
return match($annotations['var']) {
// there is a high confidence that the type is text when
// @var string is used
'string' => new TypeGuess(TextType::class, [], Guess::HIGH_CONFIDENCE),
// integers can also be the id of an entity or a checkbox (0 or 1)
'int', 'integer' => new TypeGuess(IntegerType::class, [], Guess::MEDIUM_CONFIDENCE),
'float', 'double', 'real' => new TypeGuess(NumberType::class, [], Guess::MEDIUM_CONFIDENCE),
'boolean', 'bool' => new TypeGuess(CheckboxType::class, [], Guess::HIGH_CONFIDENCE),
// there is a very low confidence that this one is correct
default => new TypeGuess(TextType::class, [], Guess::LOW_CONFIDENCE)
};
}
protected function readPhpDocAnnotations(string $class, string $property): array
{
$reflectionProperty = new \ReflectionProperty($class, $property);
$phpdoc = $reflectionProperty->getDocComment();
// parse the $phpdoc into an array like:
// ['var' => 'string', 'since' => '1.0']
$phpdocTags = ...;
return $phpdocTags;
}
// ...
}
現在,如果屬性具有 PHPDoc,此類型猜測器就可以猜測其欄位類型!
猜測欄位選項
其他三個方法(guessMaxLength()
、guessRequired()
和 guessPattern()
)會傳回具有選項值的 ValueGuess 執行個體。此建構子有 2 個引數
- 選項的值;
- 猜測值正確的信心程度(使用
Guess
類別的常數)。
當您認為不應設定選項的值時,會猜測 null
。
警告
您應非常小心使用 guessMaxLength()
方法。當類型為浮點數時,您無法判斷長度(例如,您希望浮點數小於 5
,5.512313
無效,但 length(5.512314) > length(5)
有效,因此模式會成功)。在這種情況下,值應設定為 null
,並具有 MEDIUM_CONFIDENCE
。
這項工作,包括程式碼範例,已根據 Creative Commons BY-SA 3.0 授權條款授權。