3

コレクションでカスタム クラス バリデータを使用すると問題が発生します。エラーが見つかり、適切なプロパティ パスが取得されますが、親フォームに送信されます。コレクションの各子ではなく、親フォームにエラーがリストされる原因となります...

より関連性のあるコード:

検証.yml

My\SuperBundle\Entity\Event:
    properties:
      conflictComment:
        - NotNull: ~ # this property constraint got the right property path in the right form !
    constraints:
      - My\SuperBundle\Validator\DateIsAvailable: ~ # this one got the right property path, but in the parent form.

MultiEventType.php、サブフォーム エラーを取得する親フォーム

$builder
    ->add('events', 'collection', array(
        'type' => new \My\SuperBundle\Form\Type\EventDateType()
    ));

...

    'data_class' => 'My\SuperBundle\Form\Model\MultiEvent'  

EventDateType.php、エラーを取得するコレクション

$required = false;
$builder
    ->add('begin', 'datetime', array(
        'date_widget' => 'single_text',
        'time_widget' => 'text',
        'date_format' => 'dd/MM/yyyy',
        'label' => 'form.date.begin')
    )
    ->add('automatic', 'checkbox', compact('required'))
    ->add('conflictComment', 'textarea', compact('required'));

...

    'data_class' => '\My\SuperBundle\Entity\Event'

DateIsAvailableValidator.php

namespace My\SuperBundle\Validator;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class DateIsAvailableValidator extends ConstraintValidator
{
    private $container;

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

    public function isValid($event, Constraint $constraint)
    {
        $this->setMessage($constraint->message);

        return false;
    }
}

プロパティ パスはchildren[events][0].dataに似ていますが、コレクション行のテンプレートにあるはずのform_errors(prototype)ではなく、form_errors(multiEventForm.events)でレンダリングされます...

エラーを正しい形式で取得する方法はありますか、それともバグですか?

4

1 に答える 1

1

さて、これがこの問題を回避するために私がしたことです:

エラーを正しい形式でレンダリングするための拡張機能を作成しただけです。

SubformExtension.php

<?php

namespace My\SuperBundle\Twig;

use Symfony\Component\Form\FormView;
use Twig_Environment;
use Twig_Extension;
use Twig_Function_Method;

/**
 * Add methods to render into the appropriate form
 *
 * @author Jérémy Hubert <jhubert@eskape.fr>
 */
class SubformExtension extends Twig_Extension
{

    /**
     * {@inheritdoc}
     */
    public function initRuntime(Twig_Environment $environment)
    {
        $this->environment = $environment;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'subform_extension';
    }

    /**
     * {@inheritdoc}
     */
    public function getFunctions()
    {
        return array(
            'subform_errors' => new Twig_Function_Method($this, 'renderErrors', array('is_safe' => array('html'))),
        );
    }

    /**
     * Render errors handled by parent form of a collection in the right subform
     * @param FormView $view     The Child/Collection form which should handle the error
     * @param string   $template Template used to render the error message
     *
     * @return string
     */
    public function renderErrors(FormView $view, $template = null)
    {
        // Get the root form, where our (sub)collection errors bubbled
        $parentForm = $view;
        do {
            $parentForm = $parentForm->getParent()->getParent();
        } while ($parentForm->hasParent());
        $parentForm = $parentForm->getVars();

        // Seeking property path
        $fieldName = $view->get('full_name');
        $validationName = '[' . preg_replace('/^[a-zA-Z_]*/', 'children', $fieldName) . '.data]';

        // Render errors
        $html = '';
        foreach ($parentForm['errors'] as $error) {
            if (false !== strpos($error->getMessageTemplate(), $validationName)) {
                $message = str_replace($validationName, '', $error->getMessageTemplate());

                if (null !== $template) {
                    $html .= $this->environment->render($template, compact('message'));
                } else {
                    $html .= $message;
                }
            }
        }

        return $html;
    }

}

services.yml

parameters:
    twig.extension.subform.class: My\SuperBundle\Twig\SubformExtension

services:
    twig.extension.subform:
        class: %twig.extension.subform.class%
        tags:
            - { name: twig.extension }

errorMessage.html.twig(Twitter Bootstrapを使用)

<div class="alert alert-error no-margin-bottom">
    <div class="align-center">
        <i class="icon-chevron-down pull-left"></i>
        {{ message }}
        <i class="icon-chevron-down pull-right"></i>
    </div>
</div>

そして私のコレクションのプロトタイプでは:

{{ subform_errors(prototype, 'MySuperBundle:Message:errorMessage.html.twig') }}

これが役立つことを願っていますが、より良い解決策は提案されていません。

于 2012-10-24T07:10:01.980 に答える