-1

I am attempting to validate a field that should hold US dollar amounts using the Validator method money(). I get the error "Call to undefined method Cake\Validation\Validator::money()".

I'm able to access the methods minLenthBytes() & naturalNumber() without the same error. I did see some issues on github regarding money() from 2016 but it looks they are closed. The cookbook indicates that money() should be there (https://api.cakephp.org/3.8/class-Cake.Validation.Validation.html#_money). I did find it in \vendor\cakephp\cakephp\src\Validation\Validation.php.

Here's my code

$validator
  ->numeric('ship_amt') //no error
  ->minLengthBytes('ship_amt', 25) //no error, testing only
  ->money('ship_amt', 'Please enter a valid monetary amount.') //error -> call to undefined method. Same error with or without message.
  ->naturalNumber('ship_amt') //no error, testing only
  ->greaterThanOrEqual('ship_amt', 0) //no error, testing only
  ->notEmptyString('ship_amt'); // no error, testing only

Here's the top portion of the debug log (I can provide more if needed):

[Error] Call to undefined method Cake\Validation\Validator::money() 
#0 XXX\vendor\cakephp\cakephp\src\Validation\ValidatorAwareTrait.php(178): App\Model\Table\ProjectsTable->validationDefault(Object(Cake\Validation\Validator))
#1 XXX\vendor\cakephp\cakephp\src\Validation\ValidatorAwareTrait.php(151): Cake\ORM\Table->createValidator('default')
#2 XXX\vendor\cakephp\cakephp\src\View\Form\EntityContext.php(593): Cake\ORM\Table->getValidator('default')
#3 XXX\vendor\cakephp\cakephp\src\View\Form\EntityContext.php(504): Cake\View\Form\EntityContext->_getValidator(Array)
#4 XXX\vendor\cakephp\cakephp\src\View\Helper\FormHelper.php(1463): Cake\View\Form\EntityContext->getRequiredMessage('company_id')
#5 XXX\vendor\cakephp\cakephp\src\View\Helper\FormHelper.php(1354): Cake\View\Helper\FormHelper->_magicOptions('company_id', Array, false)
#6 XXX\vendor\cakephp\cakephp\src\View\Helper\FormHelper.php(1171): 

Specs: CakePHP 3.8 on Windows Server 2012, PHP 7.3.1

I'm quite new to v3.x after being away for a few years. If there are any noob mistakes, my apologies. I'm feeling like a serious noob right now.

Thanks in advance for any assistance. It will be greatly appreciated.

Salines
  • 5,674
  • 3
  • 25
  • 50
jsf
  • 5
  • 3

2 Answers2

1

It looks like the proxy for the Money validator was merged in but removed again shortly thereafter back in 2016, per the Git history comments:

Remove this proxy until we have a better money() validation method. The current one is not very locale aware and isn't great at handling a variety of currencies. We can re-implement the money() proxy when we have a better validation method to use.

Likely you just have to call the rule manually via add(), ex:

$validator->add('ship_amt', 'money', [
    'rule' => ['money', 'left'],
    'message' => 'Please enter a valid monetary amount.'
]);
Andy Hoffner
  • 3,267
  • 2
  • 21
  • 22
  • This is exactly what I needed. Thank you for the clear answer. However, why would a reader of the cookbook think that a method that isn't defined when called as instructed work when called manually? I'm familiar with cake from early v2.x but I am finding the documentation for v3.x very difficult to work with. Given your quote from Git, why is the method still there? It doesn't appear in the deprecated list on the Cake website. I find it kind of sad that most of the best explanations/examples of even the simplest items are found everywhere but the official documentation. – jsf Aug 21 '19 at 01:50
  • Yeah the default `Validator` provider only has shorthand methods for a subset of all the validators listed in the default `Validation` Provider - the Cake Cookbook section on validation does rely on links to the API docs for a full list of what's in there, could be worth brining up with their team they might be interested & just need help from the community to list them in full. Either way I'd guess they're limiting exposure to `money()` specifically since it's not gonna work for many users anyways & might be better off in Locations providers. – Andy Hoffner Aug 22 '19 at 19:07
0

From CakePHP Book:

CakePHP provides a basic suite of validation methods in the Validation class. The Validation class contains a variety of static methods that provide validators for several common validation situations.

The API documentation for the Validation class provides a good list of the validation rules that are available, and their basic usage.

Some of the validation methods accept additional parameters to define boundary conditions or valid options. You can provide these boundary conditions and options as follows:

$validator = new Validator();
$validator
    ->add('title', 'minLength', [
        'rule' => ['minLength', 10]
    ])
    ->add('rating', 'validValue', [
        'rule' => ['range', 1, 5]
    ]);

Using money validation:

$validator
    ->add('ship_amt', 'validValue', [
        'rule' => ['money', 'right']
    ]);

from api:

/**
 * Checks that a value is a monetary amount.
 *
 * @param string $check Value to check
 * @param string $symbolPosition Where symbol is located (left/right)
 * @return bool Success
 */
public static function money($check, $symbolPosition = 'left')
{
    $money = '(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{1,2})?';
    if ($symbolPosition === 'right') {
        $regex = '/^' . $money . '(?<!\x{00a2})\p{Sc}?$/u';
    } else {
        $regex = '/^(?!\x{00a2})\p{Sc}?' . $money . '$/u';
    }

    return static::_check($check, $regex);
}
Salines
  • 5,674
  • 3
  • 25
  • 50