2011-12-11 55 views
0

我正在閱讀Data Transformations我在我的代碼中修改了一些。我越來越Symfony 2如何找到自定義表單類型?

未能加載類型 「csv2tags」

我有一個自定義表單類型

class CSV2TagsType extends AbstractType { 
    public function buildForm(FormBuilder $builder, array $opts) { 
     $builder->appendClientTransformer(new CSV2TagsTransformer()); 
    } 
    public function getParent() { 
     return 'text'; 
    } 
    public function getName() { 
     return 'csv2tags'; 
    } 
} 

使用變壓器:

class CSV2TagsTransformer implements DataTransformerInterface { 
    /** 
    * @var EntityManager 
    */ 
    protected $em; 
    public function __construct(EntityManager $em) { 
     $this->em = $em; 
    } 
    // ... 
} 

services.yml

services: 
    jm.blog.csv2tagsTransformer: 
     class: JM\BlogBundle\Form\DataTransformer\CSV2TagsTransformer 
     arguments: ["@doctrine.orm.entity_manager"] 

幾個問題:

  • 我搬到EntityManager到變壓器,而不是形式的類型,行嗎?
  • 我沒有爲文檔中的變壓器服務聲明別名。我認爲表單類型的別名來自AbstractType::getName()函數?我是否需要將自定義表單類型聲明爲服務
  • 我將EntityManager移至變壓器。沒有EntityManager,我做了new CSV2TagsTransformer(),我做了正確的事嗎?

回答

3

我會剛剛完成@ greg0ire給出的答案,這幾乎是正確的。

首先,你定義的服務應該是你的表單類型(CSV2TagsType),而不是你的變壓器(CSV2TagsTransformer),因爲它是使用表單生成器表單類型。由於表單構建器期望AbstractType,因爲數據轉換器不是AbstractType,所以它不適用於您的服務定義。正如@ greg0ire所說的,您必須使用form.type標記標記您的自定義表單類型。

services: 
    jm.blog.csv2tagsType: 
    class: JM\BlogBundle\Form\Type\CSV2TagsType 
    arguments: ["@doctrine.orm.entity_manager"] 
    tags: 
     - { name: form.type, alias: csv2tags } 

由功能getName在自定義表單類型必須你給別名(cvs2tags),或者你定義的服務ID(jm.blog.csv2tagsType)匹配返回的值。這是Symfony可以找到您的自定義類型的方式。它試圖找到getName()方法給出的服務ID。

對於你的數據轉換器,有一個小問題。你正在做new CSV2TagsTransformer()但你沒有通過實體經理。這會導致錯誤。你不能這樣做,因爲沒有辦法以服務方式注入數據轉換器。

你需要做的是將實體管理器注入自定義表單類型,然後在實例化時將其傳遞給數據轉換器。

class CSV2TagsType extends AbstractType 
{ 
    protected $em; 

    public function __construct(EntityManager $em) { 
     $this->em = $em; 
    } 

    public function buildForm(FormBuilder $builder, array $opts) { 
     $builder->appendClientTransformer(new CSV2TagsTransformer($this->em)); 
    } 

    // Rest of class 
} 

這樣,你注入實體管理器在你的表單類型,因爲表單類型被定義爲服務,這是可能的。並且在表單類型中,您實例化數據轉換器並將已注入表單類型的實體管理器傳遞給構造。

另一種方法是將數據轉換器聲明爲服務,然後將其注入表單類型中。這樣,你就不會自己實例化一個數據轉換器,而是使用在表單類型的構造器中注入的那個。所以,如果你不需要表單類型的實體管理器,你可以省略注入它。下面這個替代的例子:

services: 
    jm.blog.csv2tagsTransformer: 
    class: JM\BlogBundle\Form\DataTransformer\CSV2TagsTransformer 
    arguments: ["@doctrine.orm.entity_manager"] 

    jm.blog.csv2tagsType: 
    class: JM\BlogBundle\Form\Type\CSV2TagsType 
    arguments: ["@jm.blog.csv2tagsTransformer"] 
    tags: 
     - { name: form.type, alias: csv2tags } 

class CSV2TagsType extends AbstractType 
{ 
    protected $transformer; 

    public function __construct(CSV2TagsTransformer $transformer) { 
     $this->transformer= $transformer; 
    } 

    public function buildForm(FormBuilder $builder, array $opts) { 
     $builder->appendClientTransformer($this->transformer); 
    } 

    // Rest of class 
} 

在這裏回答你的問題的一小簡歷:

  1. 這是正確的。
  2. 變壓器服務不需要別名。但正如@ greg0ire所說,你需要爲你的表單類型定義一個服務。函數getName()必須返回應該使用的id。它可以是定義的別名,也可以是直接的服務ID。通常,人們使用別名作爲getName返回的值。
  3. 這樣做new CSV2TagsTransformer()是不正確的,因爲這種方式,你沒有發送實體管理器到你的類,因爲它不能接受空值,它會在PHP中失敗。

希望這會有所幫助。

問候,
馬特

+0

+1,偉大的答案 – greg0ire

1

關於你的主要問題,在您的services.yml文件,你應該標記您的服務爲form.type,像這樣:

services: 
    jm.blog.csv2tagsTransformer: 
     class: JM\BlogBundle\Form\DataTransformer\CSV2TagsTransformer 
     arguments: ["@doctrine.orm.entity_manager"] 
     tags: 
      - { name: form.type, alias: csv2tags } 

對於其他的問題,我不知道。

相關問題