跳到內容

建立自訂類型猜測器

編輯此頁

表單組件可以透過使用類型猜測器來猜測表單欄位的類型和某些選項。此組件已包含使用驗證組件的斷言的類型猜測器,但您也可以新增自己的自訂類型猜測器。

Symfony 也會在橋接器中提供一些表單類型猜測器

猜測器僅在下列情況下使用

建立 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_CONFIDENCEMEDIUM_CONFIDENCEHIGH_CONFIDENCEVERY_HIGH_CONFIDENCE。在執行所有類型猜測器之後,將會使用信心程度最高的類型。

有了這些知識,您可以實作 PhpDocTypeGuesserguessType() 方法

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() 方法。當類型為浮點數時,您無法判斷長度(例如,您希望浮點數小於 55.512313 無效,但 length(5.512314) > length(5) 有效,因此模式會成功)。在這種情況下,值應設定為 null,並具有 MEDIUM_CONFIDENCE

註冊類型猜測器

如果您使用自動裝配自動設定,您就完成了!Symfony 已經知道並正在使用您的表單類型猜測器。

如果您沒有使用自動裝配和自動設定,請手動註冊您的服務,並使用 form.type_guesser 標記它

1
2
3
4
5
6
# config/services.yaml
services:
    # ...

    App\Form\TypeGuesser\PhpDocTypeGuesser:
        tags: [form.type_guesser]

如果您在 PHP 專案中單獨使用表單組件,請使用 addTypeGuesser()addTypeGuessers()FormFactoryBuilder 來註冊新的類型猜測器

1
2
3
4
5
6
7
8
9
use App\Form\TypeGuesser\PhpDocTypeGuesser;
use Symfony\Component\Form\Forms;

$formFactory = Forms::createFormFactoryBuilder()
    // ...
    ->addTypeGuesser(new PhpDocTypeGuesser())
    ->getFormFactory();

// ...

提示

執行下列命令以驗證表單類型猜測器是否已成功在應用程式中註冊

1
$ php bin/console debug:form
這項工作,包括程式碼範例,已根據 Creative Commons BY-SA 3.0 授權條款授權。
目錄
    版本