Skip to content

Instantly share code, notes, and snippets.

@webdevilopers
Last active July 22, 2020 10:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save webdevilopers/31c8e39d786f2e02ecb2321f9c2486ac to your computer and use it in GitHub Desktop.
Save webdevilopers/31c8e39d786f2e02ecb2321f9c2486ac to your computer and use it in GitHub Desktop.
Symfony Validator Constraints Regex behaves differently to PHP preg_match condition
<?php
namespace Acme\PersonnelManagement\Application\Service\Person;
use Acme\Common\Domain\Model\FirstName;
use Symfony\Component\Validator\Constraints as Assert;
final class ChangeName
{
/**
* @var FirstName
* @Assert\NotNull
* @Assert\NotBlank
* @Assert\Type(type="string")
* @Assert\Regex(pattern="/^[\p{L}\\-\\. \']+$/u")
*/
private $firstName;
}
<?php
namespace Acme\Common\Domain\Model\PersonalName;
final class NamePolicy
{
public static function isSatisfiedBy(string $name): bool
{
if (empty($name)) {
return false;
}
// Allowed are unicode letters only and `.`, `-`, `'`, no numbers.
if (0 === preg_match("/^[\p{L}\\-\\. \']+$/u", $name)) {
return false;
}
// Continuous uppercase letters are not allowed.
if (1 === preg_match("/[\p{Lu}]{2,}/u", $name)) {
return false;
}
return true;
}
}
<?php
namespace Tests\Acme\Common\Domain\PersonalName;
use PHPUnit\Framework\TestCase;
use Acme\Common\Domain\Model\PersonalName\NamePolicy;
final class NamePolicyTest extends TestCase
{
/** @test */
public function hyphenSeparatedDoubleNamesAreAllowed(): void
{
$policy = NamePolicy::isSatisfiedBy('Hans-Werner');
$this->assertTrue($policy);
}
}
@webdevilopers
Copy link
Author

webdevilopers commented Jul 22, 2020

Came from:

The regex pattern for the NamePolicy l. 14 matches the asserted pattern in ChangeName command l. 14.

It works as expected in both cases for:

  • "Hans Werner"
  • "Hans B. Werner"
  • "Hans B. Werner'X"

But not for "Hans-Werner"! The command the symfony constraint throws an error:

^ Symfony\Component\Validator\ConstraintViolationList {#383 ▼
  -violations: array:1 [▼
    0 => Symfony\Component\Validator\ConstraintViolation {#426 ▼
      -message: "Dieser Wert ist nicht gültig."
      -messageTemplate: "This value is not valid."
      -parameters: array:1 [▼
        "{{ value }}" => ""Hans-Werner""
      ]
      -plural: null
      -root: Acme\PersonnelManagement\Application\Service\Person\ChangeName {#311 ▶}
      -propertyPath: "firstName"
      -invalidValue: "Hans-Werner"
      -constraint: Symfony\Component\Validator\Constraints\Regex {#415 ▼
        +message: "This value is not valid."
        +pattern: "/^[\p{L}\\-\\. \']+$/u"
        +htmlPattern: null
        +match: true
        +normalizer: null
        +payload: null
        +"groups": array:2 [▶]
      }
      -code: "de1e3db3-5ed4-4941-aae4-59f3667cc3a3"
      -cause: null
    }
  ]
}

In how far does the Symfony Validator Constraint handle the pattern differently from preg_match?

@webdevilopers
Copy link
Author

webdevilopers commented Jul 22, 2020

It looks like you have to remove the "double escape" as mentioned in:

BEFORE:

    /**
     * @var FirstName
     * @Assert\NotNull
     * @Assert\NotBlank
     * @Assert\Type(type="string")
     * @Assert\Regex(pattern="/^[\p{L}\\-\\. \']+$/u")
     */

AFTER:

    /**
     * @var FirstName
     * @Assert\NotNull
     * @Assert\NotBlank
     * @Assert\Type(type="string")
     * @Assert\Regex(pattern="/^[\p{L}\-\. \']+$/u")
     */

Thank you @lashae & @javiereguiluz !

@webdevilopers
Copy link
Author

In addition it looks like the "double escape" in my original pattern is not required at all.

        if (1 !== preg_match("/^[\p{L}\-\. \']+$/u", $name, $matches)) {
            return false;
        }

Works fine.

@webdevilopers
Copy link
Author

Improved by @freshp:

        // Allowed are unicode letters only and `.`, `-`, `'`, no numbers.
        if (1 !== preg_match("/^[\p{L}\-\.\s\']+$/u", $name)) {
            return false;
        }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment