Апр 01 2013

Склонение числительных в PHP

Категория: PHPgugglegum @ 17:36

Я просто положу это здесь, т.к. эта функция практически без изменений у меня качует из проекта в проект.


/**
 * Склонение числительных (для русского языка)
 *
 * Принимает число и выбирает соответствующее склонение числительного. Всего 3 варианта, которые
 * соответствуют числам 1, 2 и 5.
 *
 * @param int $number
 * @param string $one
 * @param string $two
 * @param string $five
 * @return string
 */
$plural = function($number, $one, $two, $five) {
	if (($number - $number % 10) % 100 != 10) {
		if ($number % 10 == 1) {
			$result = $one;
		} elseif ($number % 10 >= 2 && $number % 10 <= 4) {
			$result = $two;
		} else {
			$result = $five;
		}
	} else {
		$result = $five;
	}
	return $result;
};

Эта функция часто пригождается, когда нужно вывести правильное окончание у слов, связанных с количественным числительным. Например, нам нужно вывести кол-во слов. Мы пишем в шаблоне:

echo "Найдено " . $n . " слов";

Но $n может быть равно 1, тогда правильнее писать “слово“. А если слов, например, 23, то правильно писать “слова“. Данная функция реализует универсальный подход к решению данной задачи. Вы пишите:

echo "Найдено " . $n . " " . $plural($n, "слово", "слова", "слов");

Здесь функция $plural() принимает первым параметром число, по которому мы выбираем окончание, а тремя следующими параметрами принимает словоформы некоторого слова, которое нам нужно поставить с правильным окончанием, соответствующие числительным “один”, “два” и “пять” соответственно. Для всех остальных числительных (0, 7, 11, 22, 159) правильной будет одна из этих трёх форм и выбор нужной формы одинаков для всех существительных.

3 отзыва на “Склонение числительных в PHP”

  1. Сергей says:

    Доброго дня :)

    Не сразу заметил - а в чём преимущество:
    $plural = function($number, $one, $two, $five) {}

    по сравнению:
    function plural($number, $one, $two, $five) {}

    P.S. Хорошо что продолжил вести сайт, года два у меня в RSS был, теперь приятно интересные вещи по php почитать.

  2. gugglegum says:

    Сергей, хороший вопрос. Отвечу. Преимущество $plural = function() в том, что так создаётся функция в локальном пространстве имён. Тогда как function plural() делает эту функцию глобальной и притом вечной. В первом случае, если функция создана внутри какой-то другой функции, то созданная функция умрёт вместе с локальными переменными при выходе из функции, либо её можно убить через unset(). Тогда как во втором случае функция будет жить вечно (до конца работы скрипта).

    Обычно функции такого рода используются в специальных PHP-шаблонах, в которых HTML-код разбавлен PHP-вставками с форматированием, условиями и циклами. Технически, конечно, ничто не мешает объявлять функции внутри шаблонов обычным способом. Но если вы вызовете этот же шаблон ещё раз, то получите ошибку “Fatal error: Cannot redeclare plural() (previously declared in [..])”. Это делает ваш шаблон одноразовым (в рамках жизни PHP-скрипта). К тому же, вы или другой программист можете в другом шаблоне создать другую функцию с таким же именем. И если при построении страницы отработают оба шаблона, в которых объявлены функции с одинаковыми именами, вы снова получите фатал. Поэтому объявление обычных функций внутри шаблонов — это дурной тон, т.к. это приводит к конфликтам, а использование анонимных функций (замыканий) позволяет изящно обойти эту проблему, создав функцию, которая существует только внутри конкретного PHP-шаблона и не более.

    Более правильно, конечно, использовать хэлперы (view helpers), которые представляют собой некий реестр из подобных функций, доступных в любом шаблоне через PHP-магию. Но, бывают ситуации, когда вам нужно доработать уже существующий проект, созданный кем-то другим, в котором нет хэлперов или вам не хочется разбираться с их реализацией, или вы просто хотите внести как можно меньше изменений в чужой проект, чтобы не дай бог где-то что-то не сломалось из-за этого и в этом не обвинили вас.

  3. Сергей says:

    Понял, спасибо!
    Это видимо с фреймворками справедливо в первую очередь.
    Я в основном с Drupal работаю, и все полезные для себя функции в один модуль собираю, который сразу на новые проекты клонирую. А для уникальности имён функций использую префиксы по первым буквам названия модуля - сразу видны хуки и пользовательские функции. Да они глобальные, их отовсюду можно вызвать.
    Кстати, Drupal 8 использует Symfony ;)

Напишите что Вы об этом думаете


*


*


rel=nofollow включен, спам не поднимет Page Rank Вашего сайта



Anti-Spam Image
Введите этот код, чтобы подтвердить, что вы человек
*

* — Обязательно для заполнения

Перейти на главную страницу