yuchimiriのブログ

ころがるPHPer

2011-12-13

[Symfony]カスタムバリデータで特定のフィールドに対してエラーメッセージを設定する

カスタムバリデータ作った時、エラーメッセージが特定のフィールドじゃなくてフォーム全体に対して設定されて困った。


特定のフィールドに対して設定するにはPropertyPathを書き換えてaddViolationでエラーを追加すればばよいらしい...

// isValid()の中で
$propertyPath = $this->context->getPropertyPath();                                  
$this->context->setPropertyPath($propertyPath .'.'. $constraint->field);
$this->context->addViolation($constraint->message, $params, $invalidValue);

あとこのあとreturn false;とかするとフォーム全体に対してエラー判定がかかってしまって、空エラーみたいのが入ったりするので注意

2011-12-08

Symfony2でカスタムバリデータを作る3ステップ

こんにちはyuchimiriです。

このブログはSymfony Advent Calendar JP 2011 8日目の記事です。
昨日の担当はmadapajaさんでした。


去年のAdvent Calendarでは「SymfonyEventDispatcher→Symfony2(PR4)EventDispatcherの変更点」という記事を書いたのですが、今年はもう少し実践的なものを書きたいな…ということでSymfony2でのカスタムバリデータの作成方法についてご紹介します。


Symfony2では、Symfony\Component\Validator\ConstraintクラスとSymfony\Component\Validator\ConstraintValidatorクラスを拡張して独自のバリデータを作ることができます。


今回は簡単な例として、テキストエリアに改行区切りで入力された文字列がすべて日付であることをチェックするバリデータを4ステップで作ってみます。
(フォームなどは既に用意してある前提です。)


1. 任意のディレクトリ内に、Symfony\Component\Validator\Constraintクラスを継承した制約クラスを作成
vi src/Acme/DemoBundle/Validator/DatesCollection.php

<?php

namespace Acme\DemoBundle\Validator;

use Symfony\Component\Validator\Constraint;

/**
 * Date collection.
 *
 */
class DateCollection extends Constraint
{
    public $emptyMessage = '入力は必須です';
    public $message = '日付でないものが含まれています';
}


3. Symfony\Component\Validator\ConstraintValidatorクラスを継承したバリデーションクラスを作成

vi src/Acme/DemoBundle/Validator/DatesCollectionValidator.php

<?php

namespace Acme\DemoBundle\Validator;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Constraints\Date;
use Symfony\Component\Validator\Constraints\DateValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Date collection validator.
 *
 */
class DateCollectionValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function isValid($value, Constraint $constraint)
    {

        $dates = array_filter(array_map('trim', explode("\n", $value)));

        if (count($dates) < 1) {
            $this->setMessage($constraint->emptyMessage);

            return false;
        }

        $dateConstraint = new Date(array('message' => $constraint->message));
        $dateValidator = new DateValidator($this->context);

        foreach ($dates as $date) {
            if (false === $dateValidator->isValid(str_replace('/', '-', $date), $dateConstraint)) {
                $this->setMessage($dateValidator->getMessageTemplate(), $dateValidator->getMessageParameters());

                return false;
            }
        }

        return true;
    }
}


3. 作成した制約クラスを使うように、validation.ymlに設定
vi src/Acme/DemoBundle/Resources/config/validation.yml

namespaces:
    Demo: Acme\DemoBundle\Validator\

Acme\DemoBundle\Data\Dates:
    properties:
        dates:
            - Demo:DateCollection: ~

Symfonyはここで設定した制約クラス(DateCollection)を見て、「制約クラス名+Validator」という名前のクラスを探し、その中のisValid()メソッドを使ってバリデーションを行います。


ちょっと複雑なバリデーションをしたいときでも簡単に作れそうですね。


明日のAdventCallendarは@Kiskeさんです。

2011-11-28

ハンドルネームの決め方

みなさんは自分のハンドルネーム、どうやって決めましたか?

最近「yuchimiri(ゆちみり)」というハンドルネームの由来についてよく聞かれます。


私が最初にこの名前を使ったのは確か高校生の頃...


友だちに誘われて某携帯ゲームのサイトに登録することにしたんですが、そこで使うニックネームが必要になりました。

最初は本名の「ゆき」をもじって「ゆち」にしようとしたんですが、そこでふと「ここに機種依存文字入れたらどうなるんだろう」と思って名前の後に「㍉」という文字を入れてみることにしました。(無事登録できました)


「ゆち」+「㍉」=「ゆち㍉」


こうして「ゆちみり」という名前が生まれました(どーん
一歩間違えてたら「ゆち㍍」とか「ゆち㌭」になっていたかもしれないですね!


当時はこの名前で呼ばれる日が来るなんて考えもしなかったのですが、今となってはインターネット上で「私」を表す唯一の名前なので大切にしていきたいなと思っています(*^_^*)


ちなみに人からは「ゆち」とか「ゆちみり(ちゃん)」とか「ゆっち」とか呼ばれることが多いです。好きに呼んでください(^Q^)


それにしても当時の私は、その携帯ゲームを実際に作ってる人と数年後友達になってるとか思いもしなかっただろうなー。
そう考えると感慨深いものがありますね。


みんなのHNの由来も知りたいな〜!



余談ですが一般の人にハンドルネームって言っても通じないので「はんどるねーむって何?」って聞かれたら「源氏名のことだよ!」って教えてあげることにしてます。