Pull to refresh

Comments 26

Cпасибо, пригодиться. Хотя у меня тоже есть в рукаве такие штуки :P
хы какраз на днях примерно такое же писал)))
Не вижу смысла гнаться за милисекундами, но имхо
$format = str_replace(array("M", "F"), array($rus[$month], $rus2[$month]), $format);
логичнее, чем
$format = preg_replace(array("'M'", "'F'"), array($rus[$month], $rus2[$month]), $format);
Согласен. Думаю, там много мест, где можно оптимизировать код. В этом месте просто раньше был регэксп, который я потом заменил, а функцию просто не переписал, потому что, видимо, недоглядел.
UFO just landed and posted this here
UFO just landed and posted this here
извините, а давно ли можно в пыхе писать
return $words[];
это вообще говоря fatal error
наверно return $words[0]; имелось ввиду?
Да, конечно. Спасибо, что заметили. Хайлайтер или нло похитило нолик. (:
Видимо, все-таки НЛО, поскольку при редактировании поста в этом месте стоит <font color="#0000BB">0</font>, а после прогонки через парсер вся конструкция полностью исчезает.
Я бы еще добавил «нет комментариев».
Ну, это скорее нужно делать за пределами этой функции, т.к. она именно для склонения существительных, а не только для комментов. Обычную логическую конструкцию на проверку переменной $count перед вызовом функции сделать логичнее с точки зрения универсальности, имхо.
а я бы сделал все-таки внутри функции, скажем первым элементом массива «нет комментариев» (что-либо для нулевого значения), ну а дальше как положено
echo human_date(strtotime('+1 day'));
почему послезавтра?:)
Потому что косяк, да. Чуть позже вникну и поправлю. Спасибо.
вот бы еще таких статей сюда, только мне кажется надо в отдельный блог — «php, готовые решения»
лишь бы не забивать этот блог всеми функциями подряд
Для функции declension() я бы использовал более продвинутый вариант:

function declension($digit,$expr,$onlyword=false)
{
    if(!is_array($expr)) $expr = array_filter(explode(' ', $expr));
    if(empty($expr[2])) $expr[2]=$expr[1];
    $i=preg_replace('/[^0-9]+/s','',$digit)%100; //intval не всегда корректно работает
    if($onlyword) $digit='';
    if($i>=5 && $i<=20) $res=$digit.' '.$expr[2];
    else
    {
        $i%=10;
        if($i==1) $res=$digit.' '.$expr[0];
        elseif($i>=2 && $i<=4) $res=$digit.' '.$expr[1];
        else $res=$digit.' '.$expr[2];
    }
    return trim($res);
}


Позволяет писать, к примеру, так:

echo 'Написано '.declension('<b>33</b>','комментарий комментария комментариев');

(выведет «написано 33 комментария»).

А вообще, Ваша функция (как и название) очень похожа на то, что представлено на форуме дклаб: forum.dklab.ru/viewtopic.php?t=6760
По-моему, класс для таких мелочей — это перебор. Но за ссылку спасибо, покопаюсь.
Название — это слово «склонение» на английском. Ничего удивительного. (: А функция похожа только в том месте, где собственно склоняется. Это, в общем, довольно распространенный алгоритм.

Насчет приведенной функции согласен, обычно это удобнее. Если в склоняемых формах нет пробела. Правда регексп для выделения числа из форматированной строки — совершенно лишнее, имхо.
В русском языке есть небольшая нелогичность в согласовании существительных с числом:
1 комментарий,
2 комментария,
5 комментариев,
23 комментария,
71 комментарий…
Но!
11 комментариев,
12 комментариев,
13 комментариев,
14 комментариев.
Поэтому нужно проверять не только число единиц, но и число десятков.
У меня похожая функция выглядела так:

/* Вывод оповещения о непрочитанных сообщениях выбранного пользователя */
function getUserNewMessageNotice(&$DB, $userId)
{
$MESSAGE_COUNT = getUserNewMessageCount($DB, $userId);

if (accountIsBanned($DB, $_SESSION['userId'], $_SESSION['userStatus'])
|| accountIsDeleted($DB, $_SESSION['userId'], $_SESSION['userStatus'])
|| $MESSAGE_COUNT == 0)
{ // Если новых сообщений нет или пользователь заблокирован или удалён, напоминание не выводится
return NULL;
}

$NOTICE = 'В Вашем поч­то­вом ящи­ке ';

switch ($MESSAGE_COUNT)
{
// Согласование существительного <сообщение> в нужном числе с количеством новых сообщений
// Одно сообщение, два сообщение, три сообщение, четыре сообщение, двадцать одно сообщение, тридцать два сообщение,
// НО! Одиннадцать писЕМ, двенадцать сообщений, тринадцать сообщений и четырнадцать сообщений.
// Для всех чисел, оканчивающихся на 1, 2, 3 и 4 окончание будет <-ий>, кроме 11, 12, 13 и 14.
// Для всех остальных - <ие>. Такой вот он забавный, русский язык.

case ((1 != floor(($MESSAGE_COUNT % 100) / 10)) && ($MESSAGE_COUNT % 10 == 1)):
$NOTICE .= 'на­хо­дит­ся '.$MESSAGE_COUNT.' но­вое со­об­ще­ние.';
break;

case ((1 != floor(($MESSAGE_COUNT % 100) / 10)) && (($MESSAGE_COUNT % 10 == 2) || ($MESSAGE_COUNT % 10 == 3) || ($MESSAGE_COUNT % 10 == 4))):
$NOTICE .= 'на­хо­дят­ся '.$MESSAGE_COUNT.' но­вых со­об­ще­ния.';
break;

default:
$NOTICE .= 'находятся '.$MESSAGE_COUNT.' но­вых со­об­ще­ний.';
break;
}
return $NOTICE;
}

Код корявый и намертво вгрызается в свои модули со вспомогательными функциями, но общий смысл, я думаю, понятен. В случае, если непрочитанных сообщений нет, это напоминание просто не выводится.
<?php
$numbers = array(1, 2, 5, 23, 71, 11, 12, 13, 14);
$words = array('комментарий', 'комментария', 'комментариев');
foreach($numbers as $number) printf('%d %s
', $number, declension($number, $words));
?>

Выводит:
1 комментарий
2 комментария
5 комментариев
23 комментария
71 комментарий
11 комментариев
12 комментариев
13 комментариев
14 комментариев


Почитайте внимательнее приведенную мной функцию. Эта особенность там учитываются, если число больше 20. Только строчек в ней значительно меньше.
Да, вы совершенно правы, у меня с самого начала в голове был совсем другой алгоритм согласования, поэтому и вашем увидел совсем не то, что нужно )
Sign up to leave a comment.

Articles