如何在 Cakephp4 的关联字段 JSON 中显示验证错误?
How to display validation errors in JSON of associated fields in Cakephp4?
我正在寻找一种在 ajax 中发送表单后在 jQuery 中显示验证错误的方法,而 return 在 JSON 中出现验证错误。
我的代码适用于简单的表单,但对于更复杂的表单,尤其是包含关联数据输入的表单,会出现困难。
例如:
这是一个包含用于编写字幕的输入文件和相关数据的表单:
// Articles/edit.php
$this->Form->create($article);
echo $this->Form->control('title');
echo $this->Form->control('photos.0.legend');
echo $this->Form->control('photos.1.legend');
$this->Form->end();
我 post ajax 中的表单到我的 ArticlesController
的编辑方法看起来像这样:
// ArticlesController.php
public function edit($id)
{
$article = $this->Articles->findById($id)->firstOrFail();
if ($this->request->is(['post', 'put'])) {
$article = $this->Articles->patchEntity($article, $this->request->getData());
if ($this->Articles->save($article)) {
$redirection = ['action' => 'index'];
if ($this->request->is('ajax')) {
die(json_encode(['error' => false, 'redirection' => Router::url($redirection)]));
}
return $this->redirect($redirection);
}
else {
if ($this->request->is('ajax')) {
die(json_encode(['error' => true, 'validationErrors' => $article->getErrors()]));
}
}
}
$this->set(compact('article'));
}
这是 JSON 中的 return 验证错误:
{
"error": true,
"validationErrors": {
"title": {
"_empty": "The title please."
},
"photos": { // validation errors are nested
"1": {
"legend": {
"_empty": "The legend please."
}
}
}
}
}
以下是我尝试显示验证错误的方式:
// Articles/edit.php
$('form')
.fileupload({ // It sends the form in ajax
dataType: 'json',
// [...]
done: function (e, data) {
var responseJSON = data.jqXHR.responseJSON;
if (!responseJSON.error) { // There's no error => redirect
window.location = responseJSON.redirection;
}
else { // The form contains validation errors
$.each(responseJSON.validationErrors, function (field, errors) {
displayFieldErrors(field, errors);
});
}
},
// [...]
});
// Display validation errors in a field
function displayFieldErrors(field, errors)
{
var fieldId = field.replace(/_/, '-');
var input = $("#" + fieldId);
var errorMessage = '';
$.each(errors, function (key, message) {
errorMessage = errorMessage + message + '<br>';
});
input.parents('.input').addClass('error');
input.after('<div class="error-message">' + errorMessage + '</div>');
}
问题是关联数据字段的验证错误是嵌套的(例如photos
),那么如何获取输入的id?
谁能帮我找到 jQuery 函数 displayFieldErrors()
的正确实现?
我已经通过从 JSON 视图(服务器端)返回格式化的验证错误解决了这个问题:
// in Articles/json/edit.php
$errors = [];
// Recursive function to build `$errors[]` associating each field in error to one or many error message(s)
$fieldsInError = function ($err, $buildingField = '') use (&$errors, &$fieldsInError) {
foreach ($err as $key => $value) {
if (is_array($value)) {
$fieldsInError($value, empty($buildingField) ? $key : $buildingField . '.' . $key); // recursive
}
else { // string
if (isset($errors[$buildingField])) {
if (is_array($errors[$buildingField])) {
$errors[$buildingField][] = $value;
}
else {
$errors[$buildingField] = [$errors[$buildingField], $value];
}
}
else {
$errors += [$buildingField => $value];
}
}
}
};
$fieldsInError($article->getErrors());
echo json_encode(['error' => true, 'validationErrors' => $errors]));
JSON 现在看起来像这样:
{
"error": true,
"validationErrors": {
"title": "The title please.",
"photos.1.legend": "The legend please."
}
}
我正在寻找一种在 ajax 中发送表单后在 jQuery 中显示验证错误的方法,而 return 在 JSON 中出现验证错误。
我的代码适用于简单的表单,但对于更复杂的表单,尤其是包含关联数据输入的表单,会出现困难。
例如:
这是一个包含用于编写字幕的输入文件和相关数据的表单:
// Articles/edit.php
$this->Form->create($article);
echo $this->Form->control('title');
echo $this->Form->control('photos.0.legend');
echo $this->Form->control('photos.1.legend');
$this->Form->end();
我 post ajax 中的表单到我的 ArticlesController
的编辑方法看起来像这样:
// ArticlesController.php
public function edit($id)
{
$article = $this->Articles->findById($id)->firstOrFail();
if ($this->request->is(['post', 'put'])) {
$article = $this->Articles->patchEntity($article, $this->request->getData());
if ($this->Articles->save($article)) {
$redirection = ['action' => 'index'];
if ($this->request->is('ajax')) {
die(json_encode(['error' => false, 'redirection' => Router::url($redirection)]));
}
return $this->redirect($redirection);
}
else {
if ($this->request->is('ajax')) {
die(json_encode(['error' => true, 'validationErrors' => $article->getErrors()]));
}
}
}
$this->set(compact('article'));
}
这是 JSON 中的 return 验证错误:
{
"error": true,
"validationErrors": {
"title": {
"_empty": "The title please."
},
"photos": { // validation errors are nested
"1": {
"legend": {
"_empty": "The legend please."
}
}
}
}
}
以下是我尝试显示验证错误的方式:
// Articles/edit.php
$('form')
.fileupload({ // It sends the form in ajax
dataType: 'json',
// [...]
done: function (e, data) {
var responseJSON = data.jqXHR.responseJSON;
if (!responseJSON.error) { // There's no error => redirect
window.location = responseJSON.redirection;
}
else { // The form contains validation errors
$.each(responseJSON.validationErrors, function (field, errors) {
displayFieldErrors(field, errors);
});
}
},
// [...]
});
// Display validation errors in a field
function displayFieldErrors(field, errors)
{
var fieldId = field.replace(/_/, '-');
var input = $("#" + fieldId);
var errorMessage = '';
$.each(errors, function (key, message) {
errorMessage = errorMessage + message + '<br>';
});
input.parents('.input').addClass('error');
input.after('<div class="error-message">' + errorMessage + '</div>');
}
问题是关联数据字段的验证错误是嵌套的(例如photos
),那么如何获取输入的id?
谁能帮我找到 jQuery 函数 displayFieldErrors()
的正确实现?
我已经通过从 JSON 视图(服务器端)返回格式化的验证错误解决了这个问题:
// in Articles/json/edit.php
$errors = [];
// Recursive function to build `$errors[]` associating each field in error to one or many error message(s)
$fieldsInError = function ($err, $buildingField = '') use (&$errors, &$fieldsInError) {
foreach ($err as $key => $value) {
if (is_array($value)) {
$fieldsInError($value, empty($buildingField) ? $key : $buildingField . '.' . $key); // recursive
}
else { // string
if (isset($errors[$buildingField])) {
if (is_array($errors[$buildingField])) {
$errors[$buildingField][] = $value;
}
else {
$errors[$buildingField] = [$errors[$buildingField], $value];
}
}
else {
$errors += [$buildingField => $value];
}
}
}
};
$fieldsInError($article->getErrors());
echo json_encode(['error' => true, 'validationErrors' => $errors]));
JSON 现在看起来像这样:
{
"error": true,
"validationErrors": {
"title": "The title please.",
"photos.1.legend": "The legend please."
}
}