2016-09-28 15 views
5

我需要允許實現兩個接口的類型(FooBar),而不是其中之一。使用OptionsResolver組件進行高級類型驗證

interface Foo {}; 
interface Bar {}; 

class Foz implements Foo {}; 
class Baz implements Bar {}; 
class Foobar implements Foo, Bar {}; 

$resolver = new OptionsResolver(); 
$resolver->setRequired('data'); 
$resolver->setAllowedTypes('data', ['Foo', 'Bar']); 

錯!也允許FozBaz實例。


我需要允許Bar類型的子類,而不是Bar實例。

class Bar {}; 
class Foobar extends Bar {}; 
class FoobarBaz extends Foobar {}; 

$resolver = new OptionsResolver(); 
$resolver->setRequired('data'); 
$resolver->setAllowedTypes('data', ['Bar']); 

錯!也允許Bar實例。


我可以重新設計我的類/接口,但它不是設計問題。 那麼,有可能用這個組件實現它嗎?

回答

2

請參閱Define a form option allowed values depending on another option value in a FormType

您應該使用正規化此:

use Symfony\Component\Form\Exception\InvalidConfigurationException; 

$resolver->setNormalizer('data', function(Options $options, $data) { 
    if (!$data instanceof Foo && !$data instanceof Bar) { 
     throw new InvalidConfigurationException('"data" option must implement "Foo" and "Bar" interfaces.'); 
    } 

    return $data; 
}); 
1

OptionsResolver::setAllowedTypes()簽名只是this

setAllowedTypes(string $option, string|string[] $allowedTypes) 

的爭論$allowedTypes可以接受字符串列表,並用作邏輯OR,所以這些類型的任何將被允許 - 這就是你可以做的所有恐懼...

請注意,爲了允許複雜的組合,你需要更多的參數或其他方法,否則它需要e無法知道你是否想要「任何這些類型」,「所有這些類型在同一時間」,「任何類型,但這些」或任何其他組合,你可以想象...

我猜他們可能會提供一種接受回調函數作爲第二個參數的方法,因此您可以執行任何您想要的瘋狂檢查,但不存在(尚未)的AFAIK

+0

感謝@MikO的回答,我很欣賞你的建議(+1) – yceruto

1

最後,我找到了一種方法,但我不知道在所有的,它是一個傳統的方式:

//... 
function is_foobar($value) { 
    //return true or false; 
} 

$resolver = new OptionsResolver(); 
$resolver->setRequired('data'); 
$resolver->setAllowedTypes('data', 'foobar'); 
//... 

編輯:

好了,經過我睡,我認爲我的方法是錯誤的,因爲它已經通過使用setAllowedValuesaddAllowedValues方法完成:

$resolver->setAllowedValues('foo', function ($value) { 
    return $value instanceof Foo && $value instanceof Bar; 
}); 

因此沒有必要爲此使用setAllowedTypes

+1

是的,如果你看一下symfony中的'OptionsResolver'類中,'offsetGet ()'函數,它只是檢查'if(function_exists($ isFunction ='是_'。$ type))',所以是的,這是奇怪的,應該工作 - 很好找!雖然這是一個可怕的解決方法,讓我說:) – MikO

+1

是「可怕的」是這個詞,但更糟糕的是,它是無效類型時的錯誤消息:'InvalidOptionsException:帶有值Baz的選項「data」預計是類型「foobar」 ,但類型是「Baz」。「:) – yceruto