2017-07-17 74 views
6

編輯字段使用Symfony3表單驗證:這裏的github有完整的代碼來重現問題不要求通過模型變壓器

我有以下實體

class Place 
{ 
    use Traits\HasId; 

    /** 
    * Used for form. 
    * 
    * @Assert\Image(
    *  mimeTypes = {"image/png", "image/jpeg"}, 
    *  minWidth = 50, 
    *  maxWidth = 1000, 
    *  minHeight = 50, 
    *  maxHeight = 1000, 
    *  maxSize = "1M" 
    *) 
    */ 
    private $imageFile = null; 

    /** 
    * @ORM\OneToOne(targetEntity="MyImage", orphanRemoval=true, cascade={"persist"}) 
    */ 
    protected $image; 

} 

用下面的表格

class AdminPlaceType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $transformer = new HasImageTransformer(); 
     $builder->add('imageFile')->addModelTransformer($transformer); 
    } 

    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults(['data_class' => 'AppBundle\Entity\Place']); 
    } 
} 

而下面的模型變壓器

class HasImageTransformer implements DataTransformerInterface 
{ 
    public function transform($hasImage) 
    { 
     return $hasImage; 
    } 

    /** 
    * reverse transforms. 
    */ 
    public function reverseTransform($hasImage) 
    { 
     $file = $hasImage->getImageFile(); 
     $myImage = new MyImage(); 
     $myImage->setData(file_get_contents($file->getPathName())) 
     $myImage->setMimeType($file->getMimeType()); 

     $hasImage->setImage($myImage); 
    } 
} 

我可以上傳正確的圖像,並將表格正確保存在數據庫中。

但是如果我提交了不正確的圖像(如.txt文件),形式仍然沒有任何錯誤保存在數據庫

但是,如果我從表單中刪除addModelTransformer,然後我得到了正確的驗證錯誤

這個文件是不是有效的圖像

我的變壓器不修改原始imageFile場,我想知道,是什麼引發了這個問題。

我使用PHP7和symfony3.3.4

+0

UPDATE:我的錯,只注意到你有設置兩個不同的特性。 ''MyImage''是Symfony \ Component \ HttpFoundation \ File \ File的後繼嗎? Symfony的ImageValidator可能不知道如何處理你的對象,所以它只是忽略它。 –

+0

實際上,「MyImage」不是具有驗證器裝飾器集的人,它是數據庫中的實體(出於某種奇怪的原因,它是圖像存儲在BLOB字段中),imageFile字段是具有驗證器的字段,並且包含「 UploadedFile「對象。轉換器從UploadedFile創建一個MyImage對象 –

+0

我試圖重現問題,但我有很多錯誤和問題...嘗試編寫所有文件,因爲這些不夠用... -1 – pooler

回答

4

答案竟是非常愚蠢

的原因是,我忘了在reverseTransform

/** 
* reverse transforms. 
*/ 
public function reverseTransform($hasImage) 
{ 
    $file = $hasImage->getImageFile(); 
    $myImage = new MyImage(); 
    $myImage->setData(file_get_contents($file->getPathName())) 
    $myImage->setMimeType($file->getMimeType()); 

    $hasImage->setImage($myImage); 
    // this was missing :(
    return $hasImage; 
} 

這回是導致整個實體形式模型被轉化爲「null」,但實體本身沒有被銷燬,因爲我仍然在控制器中引用它,因爲它是通過標準的

public function createAction(Request $request) 
    { 
     $place = new Place(); 

     $form = $this->createForm(AdminPlaceType::class, $place); 
     $form->handleRequest($request); 
    } 

所以$place被包含正確的數據,並具有形式null它不觸發驗證....

+0

我有一個類似的事情,但Controller沒有返回任何事......我忘記了'return'聲明。適用於我們所有人:) –

+0

@ allan.simon代碼的作品並不意味着它是最好的方式來做到這一點。你正在使用一個表單變換器來達到它不打算的目的。變壓器只能將輸入轉換爲另一種不同的格式作爲輸出。 A - [變換] - > B和B - [inverseTransform] - > A您的代碼沒有這樣做,因此將它添加到變換中並不合適。你的代碼在做A - [Trasnform] - > A和A - [inverseTransform] - > A',所以如果你有A' - [Trasnform] - > A'這不是它應該如何工作。你可以做到,但我只是想讓你知道這是不對的。 – albert

2

你的變壓器由MyImage實體更換UploadFileFile對象。我假設你的MyImage不延伸FileUploadFile。這不是變壓器的預期用途。變壓器將一個輸入改變爲另一種輸入。

將建議刪除變壓器並將變壓器的代碼添加到Place->setImageFile。然後,您將按照預期進行imageFile驗證,並且每次通過另一個文件更改圖像時,即使不使用表單,也會重新創建MyImage

如果你真的想這樣做,在表單代碼,而不是在地方實體代碼,您應該使用FormEventshttps://symfony.com/doc/current/form/events.htmlFormEvents :: POST_SET_DATA

+0

我沒有更換,我正在轉換上傳文件到一個新的領域,MyImage,我認爲這是做佳能的方式? (文檔中的示例需要一個數字來將其轉換爲實體),即UploadFIle/File是我實體的ImageFile屬性,而我的轉換器設置了MyImage類型的Image字段部分,所以我的實體的初始數據還沒有被觸動? –

+0

我已經添加了一個鏈接到一個github包含全功能和最小代碼,重現問題 –

0

引起驗證錯誤,拋出TransformationFailedException。但傳遞給此異常的消息不會顯示給用戶。您將使用invalid_message選項設置該消息(請參閱下文)。 https://symfony.com/doc/current/form/data_transformers.html

+0

但我不能扔一個,因爲從我的變壓器的角度來看一切都很好吧?我的理解是,如果您在轉換過程中發生錯誤(例如,如果您將某個實體的id轉換爲實體並且它不存在等),您將拋出此類異常。 –