I am currently developing a Website in which user may buy gift cards. I am using a three step form using the CraueFormFlow bundle and everything is concerning the steps. I a
This is how I've done this in my validation constraints, to check credit card validity with expiration month and year properties.
In this class, I check the value of expirationYear property and compare it with value of expirationMonth property got from contextObject.
/**
* Method to validate
*
* @param string $value Property value
* @param \Symfony\Component\Validator\Constraint $constraint All properties
*
* @return boolean
*/
public function validate($value, Constraint $constraint)
{
$date = getdate();
$year = (string) $date['year'];
$month = (string) $date['mon'];
$yearLastDigits = substr($year, 2);
$monthLastDigits = $month;
$otherFieldValue = $this->context->getRoot()->get('expirationMonth')->getData();
if (!empty($otherFieldValue) && ($value <= $yearLastDigits) &&
($otherFieldValue <= $monthLastDigits)) {
$this->context->addViolation(
$constraint->message,
array('%string%' => $value)
);
return false;
}
return true;
}
Of course, you have to authorize class and properties constraints in your getTargets method, form the main constraint file.
/**
* Get class constraints and properties
*
* @return array
*/
public function getTargets()
{
return array(self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT);
}
Further explanations and complete tutorial here: http://creativcoders.wordpress.com/2014/07/19/symfony2-two-fields-comparison-with-custom-validation-constraints/
You have many solutions for this.
The easiest one is to add a Callback constraint to your model class.
Another way to do it would be to create your custom constraint and its associated validator. You have a cookbook explaining how to create a custom validation constrain. This is the best approach to do it.
As your constraint does not apply to a property but to a class, you must specify it overriding the the ->getTargets()
method of your constraint class:
class MyConstraint extends Constraint
{
// ...
public function getTargets()
{
return Constraint::CLASS_CONSTRAINT;
}
}
So the value passed as $value
argument of the ->isValid()
method will contain values of the whole class and not only of a single property.
I'd suggest using Expression constraint. This constraint can be applied on form field or (preferably) in entity:
/**
* @var int
* @Assert\Type(type="integer")
*/
private $amountGiftCards25;
/**
* @var int
* @Assert\Type(type="integer")
* @Assert\Expression(expression="this.getAmountGiftCards25() > 0 or value > 0", message="Please choose amount of gift cards.")
*/
private $amountGiftCards50;
When you don't have a data class attached to your form you can implement dependent constraints in forms like this:
$startRangeCallback = function ($object, ExecutionContextInterface $context) use ($form)
{
$data = $form->getData();
$rangeEnd = $data['range_end'];
if($object && $rangeEnd){
if ($object->getTimestamp() > $rangeEnd->getTimestamp()) {
$context->addViolation('Start date should be before end date!', array(), null);
}
}
};
$form->add('range_start', 'bootstrap_datepicker', array(
'format' => 'dd-MM-yyyy',
'required' => false,
'attr' => array('class' => "col-xs-2"),
'calendar_weeks' => true,
'clear_btn' => true,
'constraints' => array(
new Callback(array($startRangeCallback)),
)
)
);
$form->add('range_end', 'bootstrap_datepicker', array(
'format' => 'dd-MM-yyyy',
'required' => false,
'attr' => array('class' => "col-xs-2"),
'calendar_weeks' => true,
'clear_btn' => true,
)
);
Use Regular expression inorder to prevent Zero
In your Entity class write down the below override function , and specify your property which you need to validate.
The below example is for validating a pincode ,here in pincode field I admit only numbers 0-9 combinations upto 10 digits .
" ^\d+$ " this is the regular expression I used to prevent other characters.
For overriding this function you must include the below classes
use Symfony\Component\Validator\Mapping\ClassMetadata;// for overriding function loadValidatorMetadata()
use Symfony\Component\Validator\Constraints\NotBlank;// for notblank constrain
use Symfony\Component\Validator\Constraints\Email;//for email constrain
use Symfony\Component\Validator\Constraints\MinLength;// for minimum length
use Symfony\Component\Validator\Constraints\MaxLength; // for maximum length
use Symfony\Component\Validator\Constraints\Choice; // for choice fields
use Symfony\Component\Validator\Constraints\Regex; // for regular expression
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addPropertyConstraint('pincode', new NotBlank(array('message' => 'Does not blank')));
$metadata->addPropertyConstraint('pincode', new Regex(array('pattern'=>'/^\d+$/','message' => 'must be number')));
$metadata->addPropertyConstraint('pincode', new MaxLength(array('limit'=>'6','message' => 'must maximum 6 digits')));
$metadata->addPropertyConstraint('pincode', new MinLength(array('limit'=>'6','message' => 'must minimum 6 digits')));
}
Not forget these all must
included in your Entity class
that you have to validate. So in your case use a proper regular expression which does not permit '0'.
Happy coding