1

(Zend Framework 2.2.4 を使用)

私のバリデーターファクトリーは、検証時に「存在」していないようです。フォームが格納されているコントローラーからバリデーターをインスタンス化しようとすると、逆に正常に動作します。

これは機能します...

$mycustomvalidator = $this->getServiceLocator()
    ->get('ValidatorManager')
    ->get('LDP_PinAvailable');

これは、コード内で他の方法で設定されている方法です。問題を見つけることができないようで、理解するために ZF2 ソースを開かないことを望んでいました。ドキュメントとして、それは正しいようです。

モジュール構成

public function getValidatorConfig()
{
    return array(
       'abstract_factories' => array(
           '\LDP\Form\Validator\ValidatorAbstractFactory',
       ),
    );
}

ファクトリークラス

namespace LDP\Form\Validator;

use Zend\ServiceManager\AbstractFactoryInterface,
    Zend\ServiceManager\ServiceLocatorInterface;

class ValidatorAbstractFactory implements AbstractFactoryInterface
{
    public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
    {
        return stristr($requestedName, 'LDP_PinAvailable') !== false;
    }


    public function createServiceWithName(ServiceLocatorInterface $locator, $name, $requestedName)
    {
        // baked in for sake of conversation
        $validator = new \LDP\Form\Validator\PinAvailable();

        if( $validator instanceof DatabaseFormValidatorInterface )
            $validator->setDatabase( $locator->get('mysql_slave') );

        return $validator;
    }
}

カスタムバリデーター

namespace LDP\Form\Validator;

class PinAvailable extends \Zend\Validator\AbstractValidator implements DatabaseFormValidatorInterface
{

    /**
     * @var \Zend\Db\Sql\Sql
     */
    private $database;

    public function setDatabase( \Zend\Db\Sql\Sql $db )
    {
        $this->database = $db;
    }


    public function isValid( $value )
    {
        $DBA = $this->database->getAdapter();
        // do the mixed database stuff here
        return true;
    }
}

最後に、配列のフォーム フィールド バリデータ構成部分:

'pin' => array(
    'required' => true,
        'filters'  => array(
            array('name' => 'alnum'),
            array('name' => 'stringtrim'),
        ),
        'validators' => array(
            array( 'name' => 'LDP_PinAvailable' )
        ),
    ),
),

すべてをつなぎ合わせると、フォームが読み込まれ、送信されると、以下のスタック トレースが実行されます。

2013-10-28T17:09:35-04:00 ERR (3): Exception:
1: Zend\Validator\ValidatorPluginManager::get was unable to fetch or create an instance for LDP_PinAvailable
Trace:
#0 /Users/Saeven/Documents/workspace/Application/vendor/zendframework/zendframework/library/Zend/ServiceManager/AbstractPluginManager.php(103): Zend\ServiceManager\ServiceManager->get('LDP_PinAvailabl...', true)
#1 /Users/Saeven/Documents/workspace/Application/vendor/zendframework/zendframework/library/Zend/Validator/ValidatorChain.php(82): Zend\ServiceManager\AbstractPluginManager->get('LDP_PinAvailabl...', Array)
4

3 に答える 3

4

ValidatorPluginManager は Zend\ServiceManager\AbstractPluginManager を拡張します。AbstractPluginManager には、デフォルトで有効になっている「autoAddInvokableClass」という機能があります。

基本的に、これが意味することは、要求されたサービス名が ValidatorPluginManager によって解決できない場合、その名前が有効なクラス名であるかどうかをチェックするということです。その場合、呼び出し可能なクラスとしてオンデマンドで単純に追加されます。つまり、抽象ファクトリにフォールバックすることはありません。

この動作を回避する最も簡単な方法は、実際には実際のクラス名に解決されないサービス名に抽象ファクトリが応答するようにすることです。

参照: AbstractPluginManager.php#L98-L100

于 2013-10-28T18:27:40.210 に答える
2

さらに掘り下げると、問題が見つかりました。Zend\Validator\ValidatorChain の行 80 あたりの次の行に蒸留されました。

public function plugin($name, array $options = null)
{
    $plugins = $this->getPluginManager();
    return $plugins->get($name, $options);
} 

コンテキストで利用できるプラグイン マネージャーはありませんでした。

コントローラーでフォームを準備したときに、これを行う必要があることを見つけるのに約 3 秒かかりました。

 $validators = $this->getServiceLocator()->get('ValidatorManager');
 $chain      = new ValidatorChain();
 $chain->setPluginManager( $validators );
 $form->getFormFactory()->getInputFilterFactory()->setDefaultValidatorChain( $chain );

うまくいけば、これは他の誰かに役立ちます。このように設定すると、通常の古いクラス名を使用できます。クラス名をワープする必要はありません

于 2013-10-29T02:29:20.290 に答える
0

ZF3/Laminasでは、バリデーターが として登録されていれば、フォームinvokable内でバリデーターを呼び出すことができ、getInputFilterSpecification()問題ありません。ファクトリを使用してバリデータをインスタンス化すると、問題が発生します。私の理解が正しければ、フォームがこのように登録されていても

'form_elements' => [
    'factories' => [
        SomeForm::class => SomeFormFactory::class,
    ]
]

そしてあなたのバリデータ:

'validators' => [
    'factories' => [
        SomeValidator::class => SomeValidatorFactory::class,
    ]    
]

ファクトリ経由でバリデータをインスタンス化することはありません。その理由は、フォーム ファクトリ (のようなもの$form->getFormFactory()) に入力フィルタ ファクトリがあり、そこにデフォルトのバリデータ チェーンがあるためです。そして、このバリデータチェーンには何もValidatorManager添付されていません。がないValidatorManagerと、デフォルト チェーンはバリデーター名をバリデーター ファクトリにマップできません。

このすべての問題を解決するには、コントローラ ファクトリで次のようにします。

$form->('FormElementManager')->get(SomeForm::class);
$form->getFormFactory()->getInputFilterFactory()
        ->getDefaultValidatorChain()->setPluginManager($container->get('ValidatorManager'));

そしてあなたの悩みは終わりました。

于 2020-04-18T09:59:07.077 に答える