@Alex-Broudy

PHP — Города в предложном падеже — как отменить склонение для некоторых городов?

Доброго времени суток!

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

Москва -> Москве (подразумевается - в Москве)
Санкт-Петербург -> Санкт-Петербурге и т.д.

Сам обработчик:
function to_prepositional($str) {	
	
	$replace = array();
	$replace['2'][] = array('ия','ии');
	$replace['2'][] = array('ия','ии');
	$replace['2'][] = array('ий','ом');
	$replace['2'][] = array('ое','ом');
	$replace['2'][] = array('ая','ой');
	$replace['2'][] = array('ль','ле');
	$replace['1'][] = array('а','е');
	$replace['1'][] = array('о','е');
	$replace['1'][] = array('и','ах');
	$replace['1'][] = array('ы','ах');
	$replace['1'][] = array('ь','и');
	
	foreach ($replace as $length => $replacement) {
		$str_length = mb_strlen($str, 'UTF-8');
		$find = mb_substr($str, $str_length - $length, $str_length, 'UTF-8');
		foreach($replacement as $try) {
			if ( $find == $try[0] ) {
				$str = mb_substr($str, 0, $str_length - $length, 'UTF-8');
				$str .= $try['1'];
				return $str;
			}
		}
	}
	if ($find == 'е') {
		return $str;
	} else {
		return $str.'е';
	}
	
}


Но, есть города, которые не склоняются, например: Улан-Удэ или Балаково.

Подскажите новичку, какие изменения необходимо сделать, чтобы не осуществлялась обработка значений для городов заканчивающихся на: -и, -о, -е(ё), -ово, -ево, -ино, -ыно, -э.
то есть, если такие города попадаются, то их склонение игнорируется.

Так же интересует, как можно склонять города еще и в родительном падеже, чтобы было так:

Москва -> Москвы (подразумевается - для Москвы)
Санкт-Петербург -> Санкт-Петербурга и т.д.

можно конечно аналогично $replace['1'][] = array('а','е'); указывать значения array('а','ы'); и т.д., но это будет уже другой обработчик.

Цель всей этой идеи такова:

есть страницы сайта в которых обязательно присутствует название города в заголовке, и на этих страницах размещены тексты, в которых присутствуют две переменные:

{city-name-pred} - переменная в которую подставляется город в предложном падеже
{city-name-rod} - переменная в которую подставляется город в родительном падеже

1. Получаем название города из заголовка
2. Проверяем на наличие переменных в тексте
3. Если в тексте страницы присутствует одна из двух или обе переменные сразу - в любом случае подставляем в эти переменные полученное название города в нужном падеже.

Если кому-то интересно будет разобраться в этой задаче или подсказать в каком направлении двигаться дальше - буду очень рад этой помощи.
  • Вопрос задан
  • 2643 просмотра
Решения вопроса 1
kawabanga
@kawabanga
Много же вы времени потратили на описание задачи.

function to_prepositional($str) {


    if (in_array( substr($str, -1), ['и','о','е','ё','э'])) return $str;
    if (in_array( substr($str, -3), ['ово','ево','ино','ыно'])) return $str;

    $custom_cities = [
        'Москва'=>'Москвы'
    ];
    if (isset($custom_cities[$str])) return $custom_cities[$str];

    $replace = array();
    $replace['2'][] = array('ия','ии');
    $replace['2'][] = array('ия','ии');
    $replace['2'][] = array('ий','ом');
    $replace['2'][] = array('ое','ом');
    $replace['2'][] = array('ая','ой');
    $replace['2'][] = array('ль','ле');
    $replace['1'][] = array('а','е');
    $replace['1'][] = array('о','е');
    $replace['1'][] = array('и','ах');
    $replace['1'][] = array('ы','ах');
    $replace['1'][] = array('ь','и');

    foreach ($replace as $length => $replacement) {
        $str_length = mb_strlen($str, 'UTF-8');
        $find = mb_substr($str, $str_length - $length, $str_length, 'UTF-8');
        foreach($replacement as $try) {
            if ( $find == $try[0] ) {
                $str = mb_substr($str, 0, $str_length - $length, 'UTF-8');
                $str .= $try['1'];
                return $str;
            }
        }
    }
    if ($find == 'е') {
        return $str;
    } else {
        return $str.'е';
    }

}
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Adamos
@Adamos
Все это рукоблудие оправдано только в случае небольшого числа городов (а их, возможно, проще будет вручную просклонять, чем выдумывать алгоритмы). Плюс потом вы воткнетесь в то, что ваша страница выдает "Я в Владимире" (реальный косяк сразу после обновления сайта Мосигры, например).
Есть же серьезная база - phpMorphy. От него и плясать.
Ответ написан
Не буду вдаваться в решение задач проверки необходимости склонения, а просто подскажу варианты для нормального склонения:
- morpher.ru (есть веб-сервис, для оффлайн - платно)
- morphos.io (полностью оффлайн, без базы, только список правил и условий)

Не надо делать велосипед склонения, он уже давно изобретён и оттестирован.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы