Склоняем фамилию на PHP

Некоторое время назад, в очередном проекте, задался целью обращение к пользователям ставить в соответствующий падеж. Например, во фразе «Вам пришло письмо от Васи Пупкина», фамилия и имя стоят в Родительном падеже. Это получается красиво, а главное очень удобно. В то же время пользователю безумно приятно видеть, что программа правильно обращается к нему по имени. Задавшись целью, я не стал сломя голову писать все с нуля, а решил сначала поискать наработки других программистов на этом поприще. Поиски увенчались переменным успехом.

Результаты поисков
Сразу же нашлись несколько скриптов для склонения английских фамилий. Их я немедленно отбросил, поскольку мне нужно было склонение русских фамилий. За ними нашел библиотеки для 1С, Delphi и FoxPro. Но, в конце концов, и мне сопутствовала удача. Нашел одну относительно неплохую библиотеку на php. Скачать ее можно здесь.

Последней интересной находкой по этой теме, были отличыные сервисы Морфер.ру и Яндекс.Склонятор, но об этом ниже.

Найденная библиотека
Найденная библиотека в комментариях не поведала мне о своем наименовании. Архив называется names, но я предлагаю именовать его RussianNameProcessor, по имени основного класса. Сама библиотека срабатывает верно приблизительно в 90-95% случаев, что само по себе достаточно много.

В архиве есть файл для тестирования testNames.php, который объясняет, как работать с библиотекой.

testNames.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
include ("./names.php");
$a = new RussianNameProcessor(
'Козлов Евгений Павлович');      // годится обычная форма
echo "".$a->fullName($a->gcaseRod);
$a = new RussianNameProcessor(
'Евгений Павлович Козлов');      // в таком виде тоже
echo "<br/>".$a->fullName($a->gcaseRod);
$a = new RussianNameProcessor('Козлов', 
'Евгений');        // можно явно указать составляющие
echo "<br/>".$a->fullName($a->gcaseRod);
$a = new RussianNameProcessor('Кунтидия', 
'Убиреко', '', 'f'); // можно явно указать пол ('m' или 'f')
echo "<br/>".$a->fullName($a->gcaseRod);
$a = new RussianNameProcessor('Козлова Евгения Павловна');
echo "<br/>".$a->fullName($a->gcaseRod);
?>

Соответственно видим следующий текст.

В родительном падеже стоят прекрасно

Итак, подключив файл names.php, с помощью include, создаем объект класса RussianNameProcessor. Этот класс является основным и через него идет вся работа. Конструктор объявлен следующим образом:

function RussianNameProcessor (string $lastName, 
string $firstName = NULL, string $middleName = NULL, 
string $sex = NULL)

Как видите, в конструктор обязательно нужно передать первый параметр – фамилию. Можно также первым параметром передать строку с фамилией, именем и отчеством, как показано в примере выше.

Следующие параметры можно передать в конструктор:

  • string $lastName – фамилия. Может быть указана строка с фамилией, именем и отчеством;
  • string $firstName – имя. По умолчанию равно NULL;
  • string $middleName – отчество. По умолчанию равно NULL;
  • string $sex – пол. Может принимать значение «m» что значит мужской пол или «f» что значит женский пол. По умолчанию равно NULL.

Для работы со склонением фамилий в принципе достаточно одной функции.

string fullName( string $gcase)

Метод в качестве параметра получает название падежа, а возвращает фамилию, имя и отчество в указанном падеже. Падежи записаны в специальных публичных свойствах в классе RussianNameProcessor

  • $RussianNameProcessor->gcaseIm или $RussianNameProcessor->gcaseNom – именительный падеж;
  • $RussianNameProcessor->gcaseRod или $RussianNameProcessor->gcaseGen – родительный падеж;
  • $RussianNameProcessor->gcaseDat – дательный падеж;
  • $RussianNameProcessor->gcaseVin или $RussianNameProcessor->gcaseAcc – винительный падеж;
  • $RussianNameProcessor->gcaseTvor или $RussianNameProcessor->gcaseIns – творительный падеж;
  • $RussianNameProcessor->gcasePred или $RussianNameProcessor->gcasePos – предложный падеж.

Есть также несколько функций для склонения отдельных составляющих:

  • string lastName(string $gcase) – метод склоняет отдельно фамилию;
  • string firstName(string $gcase) – метод склоняет отдельно имя;
  • string middleName(string $gcase) – метод склоняет отдельно отчество.

В эти методы падеж передается точно также как и в метод fullName, т.е. с помощью указанных выше свойств класса RussianNameProcessor.

Хочу отдельно заметить, что эта библиотека настроена так, что хорошо склоняет русские фамилии, записанные в кодировке windows-1251.

Для того чтобы склонять фамилии, записанные в UTF-8, нужно сделать некоторые преобразования.

Во-первых, нужно перекодировать файл names.php в кодировку UTF-8. Сделать это можно в любом нормальном редакторе, рекомендую Notepad++, который можно скачать где угодно, да хотя бы здесь.

Во-вторых, нужно в php настроить перегрузку строковых функций, функциями из расширения mb_string (не забудьте его сначала активировать). Для этого в php.ini напишите mbstring.func_overload = 7.

Теперь можно склонять фамилии, записанные в UTF-8. Для примера можно немного переделать файл testNames.php, перекодировав его в UTF-8.

testNamesUTF.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
header('Content-type:text/html;charset=UTF-8');
//внутреннюю кодировку поставим в утф
mb_internal_encoding("UTF-8");
include ("./names.php");
$a = new RussianNameProcessor(
'Козлов Евгений Павлович');      // годится обычная форма
echo "".$a->fullName($a->gcaseRod);
$a = new RussianNameProcessor(
'Евгений Павлович Козлов');      // в таком виде тоже
echo "<br/>".$a->fullName($a->gcaseRod);
$a = new RussianNameProcessor('Козлов', 
'Евгений');        // можно явно указать составляющие
echo "<br/>".$a->fullName($a->gcaseRod);
$a = new RussianNameProcessor('Кунтидия', 
'Убиреко', '', 'f'); // можно явно указать пол ('m' или 'f')
echo "<br/>".$a->fullName($a->gcaseRod);
$a = new RussianNameProcessor('Козлова Евгения Павловна');
echo "<br/>".$a->fullName($a->gcaseRod);
?>

При этом видим ту же картину

В UTF-8 все слова были поставлены верно

Эта библиотека вполне неплохо справляется с поставленной задачей склонения фамилий на русском языке. Поэтому, я считаю, что ее можно использовать в различных проектах.

Морфер.ру
Теперь перейдем к сервисам.

Кого по каким-либо причинам не устаивает вышеописанная библиотека, может использовать специальные сервисы для склонения фамилий и слов. Начнем описание с сервиса morpher.ru.

Этот сервис был разработан и поддерживается программистом Сергеем Слеповым. Разработанная технология отличная и умеет многое:

  • склонять слова на русском;
  • склонять слова на украинском;
  • писать сумму прописью;
  • склонять слова в единственном и множественном числе;
  • и многое другое.

Сервис представляет собой следующую структуру: обратившись к определенному URL, передав через get или post слово, которое нужно просклонять, получим XML-файл с результатом.

Для примера, я написал небольшой класс для работы с этим сервисом по протоколу HTTP (ещё этот сервис поддерживает SOAP). Скачать этот класс можно отсюда.

Вот небольшой пример работы с этим классом

testMorpher.php

1
2
3
4
5
6
7
8
9
10
11
<?php
//подключаем класс
include_once 'morpher.php';
//отправляем заголовки
header('Content-type:text/plain;charset=UTF-8');
//создаем объект класса
$m = new Morpher(mb_convert_encoding(
'Вася Пупкин','UTF-8','windows-1251'));
//получаем склонение
var_dump($m->getInflect());
?>

В конструктор класса передается слово, которое нужно просклонять, в кодировке UTF-8.

Для того чтобы получить склонение, нужно вызвать метод getInflect(). Этот метод вернет массив со словами в соответствующих падежах либо false, если произошла ошибка.

Сервис позволяет делать не более 100 одинаковых запросов в сутки и не более 1000 запросов в сутки всего. Правда существуют платные варианты, в которых нет данных ограничений.

Яндекс.Склонятор
У Яндекса есть специальная площадка для того, чтобы сотрудники компании могли размещать свои проекты в сети. Эта площадка называется Яндекс.Нано. Среди всех проектов, расположенных на Яндекс.Нано, есть один, который предназначен для склонения фамилий. Он имеет название Яндекс.Склонятор.

Этот сервис чуть-чуть похуже, чем предыдущий. Верность склонения составляет приблизительно 90% (например, мою фамилию неверно поставил в винительный падеж).

Работает этот сервис приблизительно по такой же схеме, что и предыдущий. Единственное отличие Яндекс.Склонятора в том, что он может возвращать данные не только в xml-формате, но еще и в формате json.

Вот небольшой класс, который я написал, чтобы продемонстрировать работу с сервисом.

testYandex.php

1
2
3
4
5
6
7
8
9
10
11
<?php
//отсылаем заголовки
header('Content-type:text/plain;charset=UTF-8');
//подключаем класс
include_once 'yandex_inflect.php';
//создаем объект
$y = new YandexInflect(mb_convert_encoding(
'Вася Пупкин','UTF-8','windows-1251'),'json');
//получаем склонение
var_dump($y->getInflect());
?>

В конструктор класса передаем слово, которое нужно просклонять в UTF-8, а также наименование формата, в котором будем запрашивать данные у Яндекса: xml или json. По умолчанию установлено в xml.
Метод getInflect() вернет массив со словами в падежах.
Про ограничения этого сервиса ничего не сказано, но я уверен, что такой сервис без ограничений в количестве запросов не обойдется.

Популярность: 12%


Интересное из других блогов:

2leep.com

И не забывайте комментировать статью.

Добавляйся в группу во вконтакте, чтобы самым первым узнавать все новости сайта

Отзывов: 19 на «Склоняем фамилию на PHP»

  1. Автор: sl4mmer, 30 апреля 2011 в 15:23

    использует Opera 11.10 Opera 11.10 на GNU/Linux x64 GNU/Linux x64

    Cgfcb,j pf материал – сэкономил время, думал уж придется самому писать

  2. Автор: sl4mmer, 30 апреля 2011 в 15:24

    использует Opera 11.10 Opera 11.10 на GNU/Linux x64 GNU/Linux x64

    *спасибо за

  3. Автор: Олег, 12 сентября 2011 в 17:22

    использует Google Chrome 14.0.835.159 Google Chrome 14.0.835.159 на Windows 7 Windows 7

    Спасибо автору за статью. Давно такую искал :)

RSS-лента комментариев. Адрес для трекбека

Ваш отзыв

Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">

Нажимая на кнопку "Добавить" вы принимаете правила комментирования