2012-03-18 2 views
1

Je travaille sur un ensemble de classes de validation et je suis en train de construire des plugins pour l'application de diverses règles de validation. Je l'ai construit la classe suivante pour valider un code postal Royaume-Uni:Limitation de ligne d'une expression régulière complexe

class PostcodeUk extends abstr\Prop implements iface\Prop 
{ 
    const 

     /** 
     * Defines the regular expression against which to test postal code 
     * 
     * @see http://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom#Validation UK postal code validation rules on Wikipedia 
     */ 
     PATTERN = '/^(GIR 0AA)|(((A[BL]|B[ABDHLNRSTX]?|C[ABFHMORTVW]|D[ADEGHLNTY]|E[HNX]?|F[KY]|G[LUY]?|H[ADGPRSUX]|I[GMPV]|JE|K[ATWY]|L[ADELNSU]?|M[EKL]?|N[EGNPRW]?|O[LX]|P[AEHLOR]|R[GHM]|S[AEGKLMNOPRSTY]?|T[ADFNQRSW]|UB|W[ADFNRSV]|YO|ZE)[1-9]?[0-9]|((E|N|NW|SE|SW|W)1|EC[1-4]|WC[12])[A-HJKMNPR-Y]|(SW|W)([2-9]|[1-9][0-9])|EC[1-9][0-9]) [0-9][ABD-HJLNP-UW-Z]{2})$/'; 

    /** 
    * 
    * @return bool True if valid 
    * @throws \InvalidArgumentException 
    */ 
    public function isValid() 
    { 
     $valid = false; 
     $data = $this -> getData(); 

     switch (gettype ($data)) 
     { 
      case 'NULL'  : 
       $valid = true; 
      break; 
      case 'string' : 
       $valid = preg_match (static::PATTERN, $data) > 0; 
      break; 
      default   : 
       throw new \InvalidArgumentException (__CLASS__ . ': This property cannot be applied to data of type ' . gettype ($data)); 
      break; 
     } 

     return ($valid); 
    } 
} 

Le regex défini dans PostcodeUk :: MOTIF a été dérivé de la donnée sur dans Wikipedia's article on UK postcodes. Cependant, l'expression regex donnée détecte les chaînes de codes postaux valides contenues dans de plus gros blocs de texte. Je veux qu'il corresponde exactement à un code postal valide, à l'exclusion des caractères précédents et suivants. Donc (SW1A 0AA) devrait être passé comme valide, mais (foobarSW1A 0AA) ne devrait pas passer.

J'ai ajouté les ancres à la regex (^ au début et $ à la fin) pour essayer de le forcer à n'accepter qu'une chaîne composée uniquement d'un code postal valide. Cependant, la classe passe toujours les codes postaux avec des chaînes de remplissage et/ou des chaînes non post-code l'enveloppant.

Qu'est-ce que je fais mal? Je pensais que l'ajout des ancres serait suffisant pour obtenir le comportement que je voulais.

Répondre

3

Ajouter les points d'ancrage comme:

^(?:regex)$ 

^foo|bar$ n'est pas la même chose que ^(?:foo|bar)$. Vous devez également utiliser \z au lieu de $. $ permet un saut de ligne facultatif à la fin de la chaîne, alors que \z est une correspondance stricte de fin de chaîne.

+0

+1 pour trouver un problème évident. – xfix

+0

Désolé, juste besoin d'un peu de clarification. Voulez-vous dire '/^(? :(GIR 0AA) | (bla bla bla etc etc)) $'? (OK, l'édition rend un peu plus clair, merci) – GordonM

+0

@GordonM, oui, mais utilisez '\ z'. – Qtax