{"action":"created","issue":{"url":"https://api.github.com/repos/cakephp/cakephp/issues/5856","labels_url":"https://api.github.com/repos/cakephp/cakephp/issues/5856/labels{/name}","comments_url":"https://api.github.com/repos/cakephp/cakephp/issues/5856/comments","events_url":"https://api.github.com/repos/cakephp/cakephp/issues/5856/events","html_url":"https://github.com/cakephp/cakephp/issues/5856","id":56887263,"number":5856,"title":"3.0 Messages of notEmpty and allowEmpty validation rules not set in Validator","user":{"login":"fub-frank","id":4126447,"avatar_url":"https://avatars.githubusercontent.com/u/4126447?v=3","gravatar_id":"","url":"https://api.github.com/users/fub-frank","html_url":"https://github.com/fub-frank","followers_url":"https://api.github.com/users/fub-frank/followers","following_url":"https://api.github.com/users/fub-frank/following{/other_user}","gists_url":"https://api.github.com/users/fub-frank/gists{/gist_id}","starred_url":"https://api.github.com/users/fub-frank/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fub-frank/subscriptions","organizations_url":"https://api.github.com/users/fub-frank/orgs","repos_url":"https://api.github.com/users/fub-frank/repos","events_url":"https://api.github.com/users/fub-frank/events{/privacy}","received_events_url":"https://api.github.com/users/fub-frank/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/cakephp/cakephp/labels/On%20hold","name":"On hold","color":"eb6420"},{"url":"https://api.github.com/repos/cakephp/cakephp/labels/validation","name":"validation","color":"FFFFFF"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/cakephp/cakephp/milestones/7","labels_url":"https://api.github.com/repos/cakephp/cakephp/milestones/7/labels","id":453043,"number":7,"title":"3.0.0","description":"New major release that breaks compatibility with 2.x\r\n\r\n- PHP5.4.19+\r\n- New ORM & behaviors.\r\n- Improved Routing\r\n- PSR-0 and composer support.\r\n- Simpler configuration and bootstrapping.\r\n- Improved configuration handling.\r\n- Improved bake.\r\n\r\nSee [the roadmap](http://github.com/cakephp/cakephp/wiki/3.0-roadmap) for more details.","creator":{"login":"lh-import","id":5175817,"avatar_url":"https://avatars.githubusercontent.com/u/5175817?v=3","gravatar_id":"","url":"https://api.github.com/users/lh-import","html_url":"https://github.com/lh-import","followers_url":"https://api.github.com/users/lh-import/followers","following_url":"https://api.github.com/users/lh-import/following{/other_user}","gists_url":"https://api.github.com/users/lh-import/gists{/gist_id}","starred_url":"https://api.github.com/users/lh-import/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lh-import/subscriptions","organizations_url":"https://api.github.com/users/lh-import/orgs","repos_url":"https://api.github.com/users/lh-import/repos","events_url":"https://api.github.com/users/lh-import/events{/privacy}","received_events_url":"https://api.github.com/users/lh-import/received_events","type":"User","site_admin":false},"open_issues":23,"closed_issues":2276,"state":"open","created_at":"2013-10-11T20:56:23Z","updated_at":"2015-02-07T15:19:52Z","due_on":null,"closed_at":null},"comments":5,"created_at":"2015-02-07T00:24:29Z","updated_at":"2015-02-07T21:01:22Z","closed_at":null,"body":"If the `notEmpty` or `allowEmpty` validation rules are added by using the `add` method of the Validator instead of the `notEmpty` or `allowEmpty` methods the custom error message is not set and gets lost.\r\n\r\n```php\r\n// in a Table Model:\r\npublic function validationDefault(Validator $validator)\r\n{\r\n    $validator = parent::validationDefault($validator);\r\n    $validator->add('some_field_name', [\r\n            'notEmpty' => [\r\n                'rule' => 'notEmpty',\r\n                'message' => 'a custom error message'\r\n            ]\r\n        ]);\r\n\r\n    return $validator;\r\n}\r\n```\r\n\r\nThe custom error message is lost.\r\nIf the `notEmpty` or `allowEmpty` methods are used, the custom error message will be saved into the array `$_allowEmptyMessages[$field]` of the `Cake\\Validation\\Validator` class.\r\n```php\r\n// Cake\\Validation\\Validator\r\npublic function notEmpty($field, $message = null, $when = false)\r\n{\r\n    if ($when === 'create' || $when === 'update') {\r\n        $when = $when === 'create' ? 'update' : 'create';\r\n    } elseif (is_callable($when)) {\r\n        $when = function ($context) use ($when) {\r\n            return !$when($context);\r\n        };\r\n    }\r\n\r\n    $this->field($field)->isEmptyAllowed($when);\r\n    if ($message) {\r\n        $this->_allowEmptyMessages[$field] = $message;\r\n    }\r\n    return $this;\r\n}\r\n```\r\n\r\nBut this is not the case, if using the `add` method\r\n```php\r\n// Cake\\Validation\\Validator\r\npublic function add($field, $name, $rule = [])\r\n{\r\n    $field = $this->field($field);\r\n\r\n    if (!is_array($name)) {\r\n        $rules = [$name => $rule];\r\n    } else {\r\n        $rules = $name;\r\n    }\r\n\r\n    foreach ($rules as $name => $rule) {\r\n        $field->add($name, $rule);\r\n    }\r\n\r\n    return $this;\r\n}\r\n```\r\n\r\nWhen the errors are returned the custom error message is not set in `$_allowEmptyMessages[$field]` and the default error message `This field cannot be left empty` will be returned\r\n```php\r\n// Cake\\Validation\\Validator\r\n\r\npublic function errors(array $data, $newRecord = true)\r\n{\r\n    // ...\r\n    $emptyMessage = 'This field cannot be left empty';\r\n    // ...\r\n    if (!$canBeEmpty && $isEmpty) {\r\n        $errors[$name][] = isset($this->_allowEmptyMessages[$name])\r\n            ? $this->_allowEmptyMessages[$name]\r\n            : $emptyMessage;\r\n        continue;\r\n    }\r\n}\r\n```\r\n\r\nHere is a quick fix for the `add` Method, that adds the message to the `$_allowEmptyMessages[$field]` array. But maybe there is a better solution to this or i missed something:\r\n```php\r\n// Cake\\Validation\\Validator\r\npublic function add($field, $name, $rule = [])\r\n{\r\n    $fieldName = $field;\r\n    $field = $this->field($field);\r\n\r\n    if (!is_array($name)) {\r\n        $rules = [$name => $rule];\r\n    } else {\r\n        $rules = $name;\r\n    }\r\n\r\n    foreach ($rules as $name => $rule) {\r\n        if (($name == 'notEmpty' || $name == 'allowEmpty') && isset($rule['message'])) {\r\n            $this->_allowEmptyMessages[$fieldName] = $rule['message'];\r\n        }\r\n        $field->add($name, $rule);\r\n    }\r\n\r\n    return $this;\r\n}\r\n```"},"comment":{"url":"https://api.github.com/repos/cakephp/cakephp/issues/comments/73382922","html_url":"https://github.com/cakephp/cakephp/issues/5856#issuecomment-73382922","issue_url":"https://api.github.com/repos/cakephp/cakephp/issues/5856","id":73382922,"user":{"login":"markstory","id":24086,"avatar_url":"https://avatars.githubusercontent.com/u/24086?v=3","gravatar_id":"","url":"https://api.github.com/users/markstory","html_url":"https://github.com/markstory","followers_url":"https://api.github.com/users/markstory/followers","following_url":"https://api.github.com/users/markstory/following{/other_user}","gists_url":"https://api.github.com/users/markstory/gists{/gist_id}","starred_url":"https://api.github.com/users/markstory/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/markstory/subscriptions","organizations_url":"https://api.github.com/users/markstory/orgs","repos_url":"https://api.github.com/users/markstory/repos","events_url":"https://api.github.com/users/markstory/events{/privacy}","received_events_url":"https://api.github.com/users/markstory/received_events","type":"User","site_admin":false},"created_at":"2015-02-07T21:01:22Z","updated_at":"2015-02-07T21:01:22Z","body":"@fub-frank 'allowEmpty' is not valid as rule for `add()`.  The 'notEmpty' validator only exists for backwards compatibility and still needs to be combined with `notEmpty()` to actually work."}}