The idea is that you can enforce a max scale rather than just magically round the number to the exact scale. This is pretty useful if you do not always use the form to retrieve the data, you can validate the entity in case of automated imports or as in my use case due to an Excel import.
Last active
October 30, 2015 09:14
-
-
Save peterrehm/e4186c41d33191a77b1c to your computer and use it in GitHub Desktop.
Numeric Validation Constraint
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Enginge { | |
/** | |
* @ORM\Column(type="float") | |
* @Assert\NotBlank() | |
* @Assert\Numeric(maxScale = 2) | |
*/ | |
private $power; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use Symfony\Component\Validator\Constraint; | |
/** | |
* @Annotation | |
*/ | |
class Numeric extends Constraint | |
{ | |
public $maxScale = null; | |
public $message = 'The number has more than {{ maxScale }} decimal places.'; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class NumericValidator extends ConstraintValidator | |
{ | |
/** | |
* {@inheritdoc} | |
*/ | |
public function validate($value, Constraint $constraint) | |
{ | |
if (!$constraint instanceof Numeric) { | |
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Numeric'); | |
} | |
$maxScale = $constraint->maxScale; | |
if (null === $maxScale) { | |
return; | |
} | |
if (is_int($value)) { | |
return; | |
} | |
// no additional type checks | |
if (!is_numeric($value)) { | |
return; | |
} | |
if (abs($value - round($value, $maxScale)) >= 0.0000000000001 ) { | |
$this->context->buildViolation($constraint->message) | |
->setParameter('{{ maxScale }}', $constraint->maxScale) | |
->addViolation(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class NumericValidatorTest extends \PHPUnit_Framework_TestCase | |
{ | |
/** | |
* @dataProvider getNumericData | |
* | |
* @param string $string | |
* @param integer $maxScale | |
* @param boolean $valid | |
*/ | |
public function testMaxScale($string, $maxScale, $valid) | |
{ | |
$context = $this->getMock( | |
'Symfony\Component\Validator\ExecutionContext', | |
[ 'buildViolation' ], | |
[], | |
'', | |
false | |
); | |
$violationBuilder = $this->getMock( | |
'Symfony\Component\Validator\Violation\ConstraintViolationBuilder', | |
[ 'addViolation' ], | |
[], | |
'', | |
false | |
); | |
$context->expects($valid ? $this->never() : $this->once()) | |
->method('buildViolation') | |
->with('The number has more than {{ maxScale }} decimal places.') | |
->willReturn($violationBuilder); | |
$violationBuilder->expects($valid ? $this->never() : $this->once()) | |
->method('addViolation'); | |
$validator = new NumericValidator(); | |
$constraint = new Numeric(); | |
$constraint->maxScale = $maxScale; | |
/** @var ExecutionContextInterface $context */ | |
$validator->initialize($context); | |
$validator->validate($string, $constraint); | |
} | |
public function getNumericData() | |
{ | |
return [ | |
[ 6.0795, 3, false ], | |
[ 1.0001, 4, true ], | |
[ 1.0001, 2, false ], | |
[ 1.00, 2, true ], | |
[ 1.00, 3, true ], | |
[ 0.00000000000012, 4, false ], | |
[ 1000000.000000001, 4, false ], | |
[ 1.0001, 4, true ], | |
[ 1, 4, true ], | |
]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment