class PseudoValidator extends sfValidatorBase
{
    public function configure($options = array(), $messages = array()) 
    {
        // @todo ajout d'options et de messages
    }

    public function doClean($value)
    {
        // @todo validation de la valeur du champs $value
    }
}

Ajoutons maintenant le code nécessaire dans nos deux méthodes afin de valider le champ et de définir le message qui sera affiché en cas d'échec de la validation.
Dans un premier temps nous allons définir un message "invalid" dans la méthode configure(). Ensuite dans la méthode doClean() nous allons utiliser une méthode permettant de vérifier si le pseudo existe ou non en base. Dans le cas où le pseudo existe, la valeur du champ n'est donc pas valide, et nous allons lancer une exception de type sfValidatorError avec le message "invalid". Si le pseudo n'existe pas en base il n'y a rien de spécial faire, la méthode doClean() retourne la valeur.

class PseudoValidator extends sfValidatorBase
{
    public function configure($options = array(), $messages = array()) 
    {
        $this->setMessage('invalid', 'Le pseudo "%pseudo%" est déjà utilisé.');
    }

    public function doClean($value)
    {
        // Dans une classe de votre modèle, créez une méthode permettant de savoir si le pseudo $value existe en base.
        // Pour l'exemple je suppose que checkPseudo() retourne un booléen.
        $exist = YourClass::checkPseudo($value);

        if($exist) 
        {
            throw new sfValidatorError($this, 'invalid', array('pseudo' => $value));
        }
        
        return $value;
    }
}

Pour aller un peu plus loin dans l'exemple nous allons ajouter deux options à notre validateur, "trim" et "min_length", cette dernière sera une option obligatoire.

class PseudoValidator extends sfValidatorBase
{
    public function configure($options = array(), $messages = array()) 
    {
    	$this->addOption('trim');
    	$this->addRequiredOption('min_length');
    	
    	$this->addMessage('min_length_msg', 'Au moins %min% caractères.'); // message par défaut
        $this->setMessage('invalid', 'Le pseudo "%pseudo%" est déjà utilisé.');
    }

    public function doClean($value)
    {
    	if($this->hasOption('trim') && $this->getOption('trim'))
    	{
    		$value = trim($value);
    	}
    	
    	if($this->hasOption('min_length') && $this->getOption('min_length') > strlen($value))
        {
            throw new sfValidatorError($this, 'min_length_msg', array('min' => $this->getOption('min_length')));	
        }
    	
        $exist = YourClass::checkPseudo($value);

        if($exist) 
        {
            throw new sfValidatorError($this, 'invalid', array('pseudo' => $value));
        }
        
        return $value;
    }
}

Pour utiliser notre validateur, rien de plus simple, un petit symfony cc pour réinitialiser l'autoloading et il suffit d'associer le validateur au champ.

$myFormObject->setValidator('my_field', new PseudoValidator(array('min_length' => 4, 'trim' => true), array('min_length_msg' => "Le pseudo doit contenir au moins %min% caractères.")));