Проверка массива опций
Мы используем стандартную функцию WordPress register_setting()
для проверки опций темы. Например, такой вызов:
register_setting( 'options-group', 'option1', 'intval' );
Проверит, является ли $option1
целым числом.
Что я могу использовать для передачи массива опций, чтобы проверить каждый элемент массива?
Например:
$options = array(
'options1' => 4, // целое число
'options2' => '127.0.0.1', // IP-адрес
'options3' => 'test@test.com' // email-адрес
);

Вам необходимо создать собственную функцию валидации данных. Ozh ранее написал отличное руководство на эту тему, но вот суть...
Предположим, ваш массив настроек называется $my_options
и содержит три поля: 'text'
, 'age'
и 'isauthorized'
.
Вы по-прежнему регистрируете его тем же способом:
register_setting( 'my_setting', 'my_options', 'my_validation_function' );
Но видите, как мы использовали пользовательский callback для третьего параметра? Теперь нам просто нужно определить эту пользовательскую функцию:
function my_validation_function( $input ) {
// Валидация возраста как целого числа
$input['age'] = intval( $input['age'] );
// Удаление HTML-тегов из текста для безопасности
$input['text'] = wp_filter_nohtml_kses( $input['text'] );
// Убеждаемся, что isauthorized может быть только true или false (0 или 1)
$input['isauthorized'] = ( $input['isauthorized'] == 1 ? 1 : 0 );
return $input;
}
Альтернативный вариант
Если вы хотите сделать ваши функции валидации более гибкими, вы можете использовать встроенные фильтры WordPress, чтобы избежать повторения кода. Вы по-прежнему регистрируете валидацию тем же способом:
register_setting( 'my_setting', 'my_options', 'my_validation_function' );
Но вместо проверки каждого элемента массива внутри функции валидации вы перебираете массив и делегируете проверку фильтрам:
function my_validation_function( $input ) {
foreach( $input as $key => $value ) {
$input[$key] = apply_filters( 'my_validation_' . $key, $value );
}
return $input
}
Теперь вы можете подключить любую необходимую логику валидации:
add_filter( 'my_validation_age', 'validate_numeric' );
function validate_numeric( $numeric ) {
return intval( $numeric );
}
add_filter( 'my_validation_text', 'validate_text' );
function validate_text( $text ) {
return wp_filter_nohtml_kses( $text );
}
add_filter( 'my_validation_isauthorized', 'validate_bool' );
function validate_bool( $bool ) {
return $bool == 1 ? 1 : 0;
}
Если вы не добавите фильтр для одной из ваших опций, значение этой опции останется неизменным. Фильтры также являются предпочтительным способом для функций, которые возвращают контент, и вы можете добавить столько фильтров, сколько нужно... или прикрепить их к любым полям.
Допустим, у вас есть два числовых поля в массиве — age
и numberChildren
. Вместо создания дополнительной функции валидации для обработки поля numberChildren
, вы просто добавляете его в фильтр:
add_filter( 'my_validation_numberChildren', 'validate_numeric' );

Мне нравится этот альтернативный подход, но как вы сохраняете чекбоксы? Они отправляются через POST только если отмечены, поэтому цикл foreach
, перебирающий все результаты, не сохранит неотмеченный чекбокс.

Ребята, разве это валидация? Если введённые данные неверны, ничего не должно сохраняться, пользователю должно быть показано неверное поле и полезное сообщение об ошибке. add_settings_error()
— это то, что нужно!

Это не валидация, а санитизация. Однако в WordPress немало плохо спроектированных или некорректно названных функций. Эта функция совмещает в себе и санитизацию, и валидацию. Чтобы не обновлять опцию из-за неверных значений, просто верните старое значение. Также разумно добавить полезное сообщение об ошибке с помощью add_settings_error().

Кажется, решение "разные функции для каждой опции в массиве" не совсем такое, как я представлял, но думаю, это должно сработать:
register_setting( 'my_setting', 'my_options', 'my_validation_function' );
function my_validation_function( $input ) {
foreach ($input as $option=>$value){
do_action('my_validation_'.$option, $option, $value);
}
return $input;
}
И затем я могу использовать собственные функции для валидации каждой опции, например:
add_action('my_validation_age', 'my_validation_function_for_age', 10, 2);
function my_validation_function_for_age($option, $value) {
$input[$option] = intval( $value );
}
add_action('my_validation_text', 'my_validation_function_for_text', 10, 2);
function my_validation_function_for_text($option, $value) {
$input[$option] = wp_filter_nohtml_kses( $value );
}
add_action('my_validation_isauthorized', 'my_validation_function_for_isauthorized', 10, 2);
function my_validation_function_for_isauthorized($option, $value) {
$input[$option] = ( $value == 1 ? 1 : 0 );
}
Пишу здесь для будущих посетителей. Принимаю решение EAMann.
