Простейшая функция склонения слов после числительных

На WordPress-сайтах, как правило, информация о количестве комментариев выглядит текстом вида комментариев: 21. Более красиво это выглядело бы так: 21 комментарий.

WordPress, естественно, не учитывает особенности русского языка, когда окончание слова после числа меняется в зависимости от этого числа.

Я предлагаю вашему вниманию простейшую PHP-функцию, которая решает данную задачу. Покажу 2 варианта этой функции.

Вариант 1

Когда нужен текст вида 21 комментарий.

В файле functions.php темы вставляем функцию:

function plural_form($number, $after) {
	$cases = array (2, 0, 1, 1, 1, 2);
	echo $number.' '.$after[ ($number%100>4 && $number%100<20)? 2: $cases[min($number%10, 5)] ];
}

А в то место, где нужно выводить текст о количестве комментов, вставляем такой код:

<?php
plural_form(
	get_comments_number(),
	/* варианты написания для количества 1, 2 и 5 */
	array('комментарий','комментария','комментариев')
);
?>

Вариант 2

Когда нужен текст вида опубликован 21 комментарий. Т.е. в данном случае склоняется слово и перед числом, и после числа.

В файле functions.php темы вставляем функцию:

function plural_form($number,$before,$after) {
	$cases = array(2,0,1,1,1,2);
	echo $before[($number%100>4 && $number%100<20)? 2: $cases[min($number%10, 5)]].' '.$number.' '.$after[($number%100>4 && $number%100<20)? 2: $cases[min($number%10, 5)]];
}

А в то место, где нужно выводить текст о количестве комментов, вставляем такой код:

<?php
plural_form(
	get_comments_number(),
	/* варианты написания для количества 1, 2 и 5 */
	array('опубликован','опубликовано','опубликовано'),
	array('комментарий','комментария','комментариев')
);
?>

Если нужно, чтобы текст был ссылкой, тогда делаем так:

<a href="<?php the_permalink() ?>#comments">[тут вставляем вышеуказанный PHP-код, который выводит количество комментов]</a>

Вот, собственно, и все.

Комментарии (11)
  1. 1
    Евгений
    @

    Спасибо за функцию.
    Но возник вопрос, как быть если при отсутствии комментариев выводилось не «0 комментариев», а «Нет комментариев»?

  2. 4
    Павел
    @

    Здравствуйте! Подскажите пожалуйста, как склонить выражение:
    — если одна рубрика, то «Опубликовано в рубрике»;
    — если рубрик несколько, то «Опубликовано в рубриках».

    Буду признателен за помощь.

  3. 7
    Александр

    Что то вы тут велосипеды придумываете.
    Начну с этого:

    switch($number) {
     case 1:
     echo "Опубликовано в рубрике";
     break; 
     default:
     echo "Опубликовано в рубриках";
    }
    

    Тут достаточно простого условия:

    echo ($number ? 'Опубликовано в рубриках' :'Опубликовано в рубрике');

    Незачем строить конструкции из свитчей без надобности.
    Теперь перейдем к самой функции склонения.
    Вот тут: (Извиняюсь конечно)

    function plural_form($number,$before,$after) {
     $cases = array(2,0,1,1,1,2);
     echo $before[($number%100>4 &amp;&amp; $number%100<20)? 2: $cases[min($number%10, 5)]].' '.$number.' '.$after[($number%100>4 &amp;&amp; $number%100<20)? 2: $cases[min($number%10, 5)]];
    }

    Но это бред сивой кобылы.
    Достаточно просто переписать нормально функцию например вот так:
    Это функция моя просто название поставил ваше.

    function plural_form($n, $w, $t = false){
     $c = array(2, 0, 1, 1, 1, 2);
     return (!$t ? $n.' ' : '').$t[ ($n % 100 > 4 &amp;&amp; $n % 100 < 20) ? 2 : $c[min($n % 10, 5)] ];
    }
    

    А теперь вывод:

    echo plural_form($count,array('опубликован','опубликовано','опубликовано'),1).' '.plural_form($count, array('комментарий','комментария','комментариев'));
    

    Тем самым немного изменив функцию мы убиваем сразу несколько зайцев.
    1. Нам больше не надо изменять функцию. Так как она подойдет для всего.
    2. Мы расширили функционал сайта. И немного уменьшили нагрузку.(Хотя для Wp давно забило о наблюдении за нагрузкой)

    • 8
      Евгений

      Добрый день. А как все это можно преобразовать в вордпресовский шорткод?

      У меня есть шорткод, который выводит количество записей в категории:

      /* Шорткод кол-ва записей */
      function kol_zap($atts) {
      extract(shortcode_atts(array(
      "id" => ''
      ), $atts));
      $post_count = get_category($id)->category_count;
      $cat_name = get_category($id)->name;
      $cat_slug = get_category($id)->slug;
      return ''.$post_count.'';
      }
      add_shortcode('kolvo', 'kol_zap');
      

      Хотелось, чтобы этот шорткод выводил после числа — слово запись(‘и’, ‘ей’).

      Заранее спасибо.

  4. 9
    Виталий Анохин

    Доработал вашу функцию =)
    Теперь есть все проверки, проще задать текст в переменной и можно его отключать.

    <?php
    
    function plural_form($number,$before,$after,$ifzero) {
     if ($number == 0) {echo $ifzero;} else {
     $cases = array(2,0,1,1,1,2);
     if ($before <> 0) {echo $before[($number%100>4 &amp;&amp; $number%100<20)? 2: $cases[min($number%10, 5)]].' ';}
     echo $number;
     if ($after <> 0) {echo ' '.$after[($number%100>4 &amp;&amp; $number%100<20)? 2: $cases[min($number%10, 5)]];}
     }
    }
    
    $anynumber = 55; // число которое надо описать
    $anytextformbefore = array('продан','продано','продано');
    //если указать значение 0 вместо массива, то текст не выводится
    $anytextformafter = array('билет','билета','билетов');
    $anytextformifzero = "билетов нет";
    
    plural_form($anynumber, $anytextformbefore, $anytextformafter, $anytextformifzero);
    
    ?>
    
  5. 10
    Виталий Анохин

    А если надо записать текст в переменную, что будет правильно, то код будет такой

    <?php
    	function plural_form($number,$before,$after,$ifzero) {
    		if ($number == 0) {return $ifzero;} else {
    			$retval = "";
    			$cases = array(2,0,1,1,1,2);
    			if ($before <> 0) {$retval .= $before[($number%100>4 &amp;&amp; $number%100<20)? 2: $cases[min($number%10, 5)]].' ';}
    			$retval .= $number;
    			if ($after <> 0) {$retval .= ' '.$after[($number%100>4 &amp;&amp; $number%100<20)? 2: $cases[min($number%10, 5)]];}
    			return $retval;
    		}
    	}
    
    	$anynumber = 55; // число которое надо описать
    	$anytextformbefore = array('продан','продано','продано');
    	//если указать значение 0 вместо массива, то текст не выводится
    	$anytextformafter = array('билет','билета','билетов');
    	$anytextformifzero = "билетов нет";
    	// результат в переменной
    	$strtext = plural_form($anynumber, $anytextformbefore, $anytextformafter, $anytextformifzero);
    	echo $strtext;
    ?>
    
  6. 11
    Иван

    Здавствуйте! Использовал вашу функцию, был доволен, но столкнулся с такой проблемой. При поиске нашлось 15 материалов и выдало такую ошибку:
    По Вашему запросу
    Notice (8): Undefined offset: 2 [APP\View\Helper\SearchingHelper.php, line 10] 15 ответов :

    вызываю так

    echo plural_form(count($search_res), ['найден', 'найдено'], ['ответ', 'ответа', 'ответов'])
    

    а код функции как в этой статье — Вариант 2
    Подскажите как решить эту проблемку.

Ваш комментарий