2

I want to create a custom validation for my fields. The Form has been extended from cakephp Form class (Modelless Forms).

Note: Bear in mind this is Modelless Forms so there is no table or database.

The problem is when I create the validation it give me this error.

Method isValidCardNumber does not exist

Here is my code:

<?php
namespace App\Form;

use Cake\Core\Configure;
use Cake\Form\Form;
use Cake\Form\Schema;
use Cake\Network\Exception\SocketException;
use Cake\Validation\Validator;
use SagePay\SagePayDirectPayment;

/**
 * Payment Form
 */
class PaymentForm extends Form
{

    /**
     * Define the schema
     *
     * @param  \Cake\Form\Schema $schema The schema to customize.
     * @return \Cake\Form\Schema The schema to use.
     */
    protected function _buildSchema(Schema $schema)
    {
        return $schema
            ->addField('name', 'string')
            ->addField('card_number', 'string')
            ...
            ...;
    }

    /**
     * Define the validator
     * 
     * @param  \Cake\Validation\Validator $validator The validator to customize.
     * @return \Cake\Validation\Validator The validator to use.
     */
    protected function _buildValidator(Validator $validator)
    {
        return $validator   
            ->notEmpty('name', 'Please enter the name on card.')    
            ->notEmpty('card_number', 'string')
            ->add('card_number', 'isValidCardNumber', [
                'rule' =>  ['isValidCardNumber'],
                'message' => 'Card number should be 16 long number.'
            ])
            ...
            ...;

    }

    protected function isValidCardNumber($data, array $context)
    {
        debug($data);
        die;
    }
}
Fury
  • 4,643
  • 5
  • 50
  • 80

2 Answers2

1

You need to set it up as a provider.

Add your object as provider.

$validator = new Validator();

// Use an object instance.
$validator->provider('custom', $myObject);

// Use a class name. Methods must be static.
$validator->provider('custom', 'App\Model\Validation');

Then use it.

use Cake\ORM\Table;
use Cake\Validation\Validator;

class UsersTable extends Table
{

    public function validationDefault(Validator $validator)
    {
        $validator
            ->add('role', 'validRole', [
                'rule' => 'isValidRole', // <--- method
                'message' => __('You need to provide a valid role'),
                'provider' => 'table', // <--- provider
            ]);
        return $validator;
    }

    public function isValidRole($value, array $context)
    {
        return in_array($value, ['admin', 'editor', 'author'], true);
    }

}

The code is copy pasted from the official documentation, alter it as needed for your use case.

floriank
  • 25,546
  • 9
  • 42
  • 66
  • Thank you. But I said this class is extended from Modelless Forms and there is no table and no database for it. – Fury Aug 08 '16 at 09:43
  • Spent more than just a second on a documentation page and actually read the page, not just look at examples. It is explained there as well how to setup other providers. default and table are built in, other need to be defined. – floriank Aug 08 '16 at 09:45
  • @Fury `$validator->provider('custom', $myObject);` `$myObject` is `$this` - the form object if that's the class you want the validator to use as a provider, the example code copied from the docs isn't table-class specific. – AD7six Aug 08 '16 at 10:11
1

T answer my question I found a CC()validation method in Cake Validation http://api.cakephp.org/3.0/class-Cake.Validation.Validation.html which is for payment cards.

But I decided to keep the answer for others developers so they learn how the Modelless Forms custom validation works.


I needed to create my own custom payment class.

<?php
namespace App\Form;

use App\Validation\PaymentCardValidation;  // <= Need to add the custom payment class
/**
 * Payment Form
 */
class PaymentForm extends Form
{

    /**
     * Define the validator
     * 
     * @param  \Cake\Validation\Validator $validator The validator to customize.
     * @return \Cake\Validation\Validator The validator to use.
     */
    protected function _buildValidator(Validator $validator)
    {       
        return $validator   
            // assign the custom PaymentCardValidation to the provider   
            ->provider('custom', 'App\Validation\PaymentCardValidation')

            ->notEmpty('name', 'Please enter the name on card.')    
            ->notEmpty('card_number', 'string') 
            ->add('card_number', 'cardNumber', [
                'rule' =>  'cardNumber',
                'message' => 'Card number should be 16 long number.',
                'provider' => 'custom', // <= Use the provider
            ])
...
...

In my PaymentCardValidation class

<?php
namespace App\Validation;

use Cake\Validation\Validation;

/**
 * PaymentCard Validation 
 * 
 * Provide's rules for payment cards
 */
class PaymentCardValidation extends Validation
{

    /**
     * Check if card number.
     * 
     * @param  string $check The value to check.
     * @return bool
     */
    public static function cardNumber($check)
    {
        debug($check);
        die;
    }
}
Fury
  • 4,643
  • 5
  • 50
  • 80