Функции и методы с переменным количеством аргументов в WordPress 5.3

На этот пост меня вдохновил комментарий Игоря, дело в том, что после обновления WordPress на 5.3, начали появляться PHP warnings, например у тех, кто модифицировал классы при помощи волкеров.

Как исправить PHP предупреждения.

Прежде всего вам нужно иметь ввиду, что если у вас не отображаются PHP предупреждения, то это не значит, что их нет 😁, вы ведь понимаете, что я говорю про эту строчку в файле wp-config.php вашего сайта?

define( 'WP_DEBUG', false ); // false – предупреждения отключены, true - включены

То есть если вдруг у вас не получится разобраться в том, что я буду описывать дальше в этом уроке, вы можете всего лишь поменять значения true на false и на какое-то время забить на это.

А теперь предположим, что вы когда-то модифицировали волкер меню при помощи моего кода:

class True_Walker_Nav_Menu extends Walker_Nav_Menu {
 
	function start_lvl(&$output, $depth) {
		// тут какие-то ваши модификации
	}
 
	...
 
}

И вдруг, внезапно после обновления на WordPress 5.3 вы стали получать следующее уведомление:

Warning: Declaration of True_Walker_Nav_Menu::start_lvl(&$output, $depth) should be compatible with Walker_Nav_Menu::start_lvl(&$output, $depth = 0, $args = NULL) in /Applications/MAMP/htdocs/mishablog/wp-content/themes/misha/functions.php on line X

Что делать в этой ситуации? Ммм.. Есть идеи? Последовать рекомендациям конечно и поменять строчку на какую написано! 😁

function start_lvl(&$output, $depth = 0, $args = NULL) {

Что такое функции с переменным количеством аргументов?

Постараюсь очень кратко, чтобы вам было понятно, о чем дальше речь. Если нужно больше информации, можете погуглить про spread operator в какой-нибудь документации PHP.

К примеру давайте взглянем на эту функцию:

function true_umnozhenie( ...$numbers ) {
 
    $result = 1;
 
    foreach ( $numbers as $number ) {
        $total = $total * $number;
    }
 
    return $result;
}

Эта функция может получать любое количество аргументов, перемножать их и возврать результат, например: echo true_umnozhenie( 15, 20, 75 );. Как видите, благодаря оператору ..., функция поработала с $numbers как с массивом, хотя мы просто передали в неё числа через запятую.

Что такое распаковка аргументов?

Второй пример!

Допустим, у нас есть уже определённая функция, которая перемножает только три числа:

function true_umnozhenie_3( $a, $b, $c ) {
	return $a * $b * $c;
}

Раньше, до PHP 5.6, для того, чтобы передать в неё массив из трёх чисел, нам нужно было передавать все элементы по отдельности:

$numbers = array( 5, 10, 75 );
echo true_umnozhenie_3( $numbers[0], $numbers[1], $numbers[2] );

Теперь это делается оператором ...

$numbers = array( 5, 10, 75 );
echo true_umnozhenie_3( ...$numbers );

Надеюсь, что это пролило немного света на функции с переменным количеством аргументов и на распаковку аргументов.

Реальный пример в коде ядра WordPress

Возможно на первый взгляд оператор ... может показаться из серии – ну окей, вроде бы как стало поприятнее, но не то что бы очень 🤔 Но для того, чтобы понять всю глобальность ситуации, давайте рассмотрим изменения во всем нам известной функции current_user_can().

Так функция выглядела в версии WordPress 5.2 и ниже:

function current_user_can( $capability ) {
    $current_user = wp_get_current_user();
 
    if ( empty( $current_user ) ) {
        return false;
    }
 
    $args = array_slice( func_get_args(), 1 );
    $args = array_merge( array( $capability ), $args );
 
    return call_user_func_array( array( $current_user, 'has_cap' ), $args );
}
  • Как вы видите на строчке 1, функция имеет только один параметр $capability, в который мы передаём название возможности, которую хотим проверить, однако для проверки некоторых возможностей мы можем передавать дополнительные параметры, например ID поста, чтобы проверить, есть ли у пользователя возможность редактировать определённый пост, и так как эти параметры не указаны в определении функции на строчке 1, то мы получаем их другим путём – через PHP функцию func_get_args().
  • На 8 строчке мы отрезаем параметр $capability при помощи array_slice().
  • Однако на 9 строке он возвращает параметр $capability обратно 👽 Не спрашивайте! Сомневаюсь, что вы найдёте человека, который объяснит вам почему это так было сделано. В любом случае, эти две строчки кода теперь уже в прошлом.

А так она выглядит в версии WordPress 5.3:

function current_user_can( $capability, ...$args ) {
    $current_user = wp_get_current_user();
 
    if ( empty( $current_user ) ) {
        return false;
    }
 
    return $current_user->has_cap( $capability, ...$args );
}

Итак, вывод.

Функция current_user_can() по своему определению может принимать разное количество параметров в зависимости от проверяемой возможности. До WordPress 5.3 это было сделано через func_get_args(), теперь же при помощи оператора ...

Другая, всеми нами знакомая функция, которая получила оператор переменного количества аргументов – add_query_arg()!

Список затронутых классов и их методов

  • Walker
    методы: walk() и page_walk(),
  • WP_User
    метод has_cap(),
  • wpdb
    метод prepare(),
  • _WP_Dependency
    метод __construct()
  • Automatic_Upgrader_Skin
    метод feedback()
  • Bulk_Upgrader_Skin
    метод feedback(),
  • WP_Ajax_Upgrader_Skin
    методы error() и feedback(),
  • WP_Upgrader_Skin
    метод feedback().

Стоп, а где же start_lvl(), про который мы говорили в самом начале этого урока? Нет, я не хочу вас надурить, в этом списке лишь те методы, которые приобрели оператор переменного количества аргументов ....

По теме:

Миша

Недавно я осознал, что моя миссия – способствовать распространению WordPress. Ведь WordPress – это лучший движок для разработки сайтов – как для тех, кто готов использовать заложенную структуру этой CMS, так и для тех, кто предпочитает headless решения.

Сам же я впервые познакомился с WordPress в 2009 году. Организатор WordCamp. Преподаватель в школах Epic Skills и LoftSchool.

Если вам нужна помощь с вашим сайтом или может даже разработка с нуля на WordPress / WooCommerce — пишите. Я и моя команда сделаем вам всё на лучшем уровне.

Оставить комментарий

Если вы хотите добавить код, не забудьте обернуть его в <pre lang="php"></pre>, если же код – меньше одной строчки, то можно и в <code></code>.