2016-09-28 22 views
5

ile gelişmiş tip doğrulaması İki arabirimi (Foo ve Bar) uygulayan türlere izin verilmemelidir, bunlardan biri değil.OptionsResolver bileşeni

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']); 

Yanlış!, Foz ve Baz örneklerine de izin vermektedir.


Ben Bar tipleri alt sınıfını değil, Bar örneklerini izin gerekiyor.

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

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

Yanlış!, Bar örneğini de sağlar.

Sınıflarım/arabirimlerimi yeniden tasarlayabilirim, ancak tasarım sorunu değil. Yani, bu bileşenle başarmak mümkün mü? Böylece bu türden olan izin verilecek

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

$allowedTypes dizeleri listesini kabul edebilir argüman ve mantık VEYA olarak kullanılır:

cevap

2

Bkz. Define a form option allowed values depending on another option value in a FormType.

Bunun için bir normalleyici kullanmalıdır:

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() imzası sadece this olduğunu - yapabileceğiniz tek şey budur ...

İstediğiniz karmaşık kombinasyonlara izin vermek için daha fazla argümana veya başka yöntemlere ihtiyacınız olduğunu unutmayın. e "bu türlerin herhangi biri", "aynı tiplerin hepsi aynı zamanda", "herhangi bir tür ama bu olanlar" ya da hayal edebileceğiniz başka bir kombinasyon isteyip istemediğinizi bilmenin bir yolu yoktur.

ikinci argüman olarak bir geriçağırım işlevini kabul eden bir yöntem sağlayabilir, böylece istediğiniz herhangi bir çılgın kontrol yapabilir, ancak mevcut olmayan AFAIK.

+0

teşekkür @MikO Cevabınız için, tavsiyene takdir (1) – yceruto

1

Son olarak, bir yol buldum ama hiç bir konvansiyonel yol olduğundan emin değilim:

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

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

DÜZENLEME:

Eh, uyku sonra ben benim yaklaşımımın yanlış olduğunu düşünün, çünkü bu zaten setAllowedValues veya addAllowedValues yöntemlerini kullanarak yapılır:

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

Bu amaçla setAllowedTypes'u kullanmak gerekmez.

+1

evet Symfony'nin 'OptionsResolver' sınıfında bakarsak,' offsetGet() 'fonksiyonu, sadece eğer' '(function_exists ($ isFunction = 'is _'. $ $))' 'için kontrol eder, yani evet, şaşırtıcı bir şekilde işe yarayacak - güzel bul! Her ne kadar korkunç bir çözüm olsa da söyleyeyim :) – MikO

+1

Evet "korkunç" kelimesidir, ancak daha da kötüsü, geçersiz tür olduğunda hata mesajıdır: 'InvalidOptionsException:" Baz "seçeneğiyle" veri "seçeneğinin" foobar "türünde olması bekleniyor ama "Baz" tipindedir. – yceruto