Использование phpMorphy

Словари

phpMorphy использует для работы словарь. Поддерживаются словари проекта AOT (http://aot.ru) и myspell (в myspell словарях отсутствует грамматическая информация, потому часть функций будет недоступна). Словари представлены в двух видах: в исходном и бинарном. Исходный словарь представлен в виде xml файла и содержит

  • Основы слов
  • Правила изменения
  • Грамматическая информация

Более подробно структура словаря описана в http://www.aot.ru/docs/sokirko/Dialog2004.htm, в phpMorphy словарь в исходной форме представлен аналогично. Имеется возможность преобразовать myspell словарь в исходную форму словаря для phpMorphy.

Для работы библиотеки требуется скомпилировать бинарный словарь. При компиляции используется словарь в исходном виде. Бинарный словарь обладает следующими особенностями:

  • бинарно совместим между различными платформами
  • все данные представлены в заданной кодировке, в верхнем (по умолчанию) или нижнем регистре.

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

Физически словарь представлен в виде нескольких файлов:

  • Key ⇒ value хранилище всех словоформ. Хранилище - использует модель минимального детерминированного конечного автомата (DAWG), позволяет искать слово за линейное от длины слова время O(N), N – длина слова. Разработано по мотивам How to Squeeze a Lexicon by Marcin Ciura Sebastian , Sebastian Deorowicz. Располагается в файле common_aut.ru
  • Хранилище грамматической информации, таблицы окончаний, граммем (файл morph_data.bin)
  • Хранилище окончаний для предсказания (файл predict_aut.bin) используется структура похожая на описанную в п1.
  • Вспомогательные файлы (кэши для php версии, опции и т.п.)

Именование файлов словаря сделано следующим образом: ИМЯ_ФАЙЛА.ЯЗЫК.bin, где ЯЗЫК – условный код языка, в виде ISO3166 код страны и ISO639 код языка т.е. ru_ru, en_en и т.п. Данный метод позволяет размещать в одном каталоге словари для нескольких языков. К примеру, файлы для русского словаря:

common_aut.ru_ru.bin
gramtab.ru_ru.bin
gramtab_txt.ru_ru.bin
morph_data.ru_ru.bin
morph_data_ancodes_cache.ru_ru.bin
morph_data_ancodes_map.ru_ru.bin
morph_data_header_cache.ru_ru.bin
predict_aut.ru_ru.bin
options.ru_ru.ini

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

dicts\
    utf-8\
        словари в utf-8 кодировке
    windows\
        словари в windows кодировке: windows-1251 (русский), windows-1250 (английский) и т.п.
    iso-8859\
        словари в семействе iso-8859 кодировок

Стоит заметить, что словарь не загружается в память полностью. Загрузка происходит по мере необходимости, так например, если используется только лемматизация - будет загружен только один файл - common_aut.ru_ru.bin.

Установка

Для работы Вам потребуется

  • Исходный код библиотеки.
  • Один или несколько словарей в бинарном виде.
  1. Скачайте последнюю версию библиотеки.
  2. Распакуйте архив (к примеру, в каталог c:\php\libs\phpmorphy). Рекомендуется разместить код бибилотеки в директории недоступной web серверу. Для Apache к примеру, выше DocumentRoot.
  3. Скачайте необходимые словари. Распакуйте файл со словарями (используем c:\php\libs\phpmorphy\dicts). В c:\php\libs\phpmorphy\dicts должны находится файлы словаря т.е. common_aut.*.bin, predict_aut.*.bin и т.п.

Инициализация

// Подключите файл common.php. phpmorphy-0.3.2 - для версии 0.3.2,
// если используется иная версия исправьте код.
require_once( 'c:/php/libs/phpmorphy/phpmorphy-0.3.2/src/common.php');
 
// Укажите путь к каталогу со словарями
$dir = 'c:/php/libs/phpmorphy/dicts';
 
// Укажите, для какого языка будем использовать словарь.
// Язык указывается как ISO3166 код страны и ISO639 код языка, 
// разделенные символом подчеркивания (ru_RU, uk_UA, en_EN, de_DE и т.п.)
 
$lang = 'ru_RU';
 
// Укажите опции
// Список поддерживаемых опций см. ниже
$opts = array(
    'storage' => PHPMORPHY_STORAGE_FILE,
);
 
// создаем экземпляр класса phpMorphy
// обратите внимание: все функции phpMorphy являются throwable т.е. 
// могут возбуждать исключения типа phpMorphy_Exception (конструктор тоже)
try {
    $morphy = new phpMorphy($dir, $lang, $opts);
} catch(phpMorphy_Exception $e) {
    die('Error occured while creating phpMorphy instance: ' . $e->getMessage());
}
 
// далее под $morphy мы подразумеваем экземпляр класса phpMorphy

Опции

Опции используемые при инициализации.

storage

Указывает способ обращения к файлам словаря. Для PHPMORPHY_STORAGE_SHM требуется наличие расширения shmop.

Значение по умолчанию: PHPMORPHY_STORAGE_FILE

Допустимые значения:

  • PHPMORPHY_STORAGE_FILE - использует файловые операции. Потребляется небольшое количество памяти. Самый медленный способ, однако, работает в любом окружении
  • PHPMORPHY_STORAGE_MEM - загружает словари в память. Плюсы этого способа в том, что обеспечивается самый быстрый способ доступа и работа в любом окружении. Однако имеется один существенный минус – словарь загружается для каждого экземпляра класса phpMorphy. Что приводит к очень медленной инициализации phpMorphy и большому потреблению памяти (т.к. для каждого запроса в память загружается порядка 10Mb, соответственно при 10 одновременных запросах потребуется около 100Mb памяти. Потому данный способ может быть полезен только для CLI скриптов. Обратите внимание на директиву memory_limit в PHP, слишком низкое значение может вызвать ошибку «Fatal error: Allowed memory size of xxx bytes exhausted (tried to allocate xxx bytes)».
  • PHPMORPHY_STORAGE_SHM - скорость сравнима с PHPMORPHY_STORAGE_MEM, однако словари загружаются в разделяемую память. Это предпочтительный способ, однако необходимо наличие shmop расширения, см. вывод php –m | grep shmop. phpMorphy загружает все словари в один сегмент разделяемой памяти (см опцию shm), поэтому необходимо установить размер сегмента таким образом, чтобы все словари с которыми предполагается работать умещались в данный сегмент (иначе возможны ошибки при иницализации: «Can`t find free space for XXX block»)

predict_by_suffix

Использовать предсказание путем отсечения префикса. Для распознавания слов, образованных от известных путём прибавления префиксов (популярный – мегапопулярный и т.п.)

Значение по умолчанию: TRUE

Допустимые значения: TRUE/FALSE

predict_by_db

Использовать предсказание по окончанию

Значение по умолчанию: TRUE

Допустимые значения: TRUE/FALSE

graminfo_as_text

использовать текстовое представление грамматической информации, иначе используется значение констант из phpmorphy/src/gramtab_consts.php

Значение по умолчанию: TRUE

Допустимые значения: TRUE/FALSE

use_ancodes_cache

Позволяет ускорить процесс получения грамматической информации (увеличивает потребление памяти во время исполнения и замедляет процесс инициализации)

Значение по умолчанию: FALSE

Допустимые значения: TRUE/FALSE

resolve_ancodes

Устанавливает способ преобразования анкодов.

Значение по умолчанию: phpMorphy::RESOLVE_ANCODES_AS_TEXT

Допустимые значения:

  • phpMorphy::RESOLVE_ANCODES_AS_INT - Используются числовые идентификаторы анкодов.
  • phpMorphy::RESOLVE_ANCODES_AS_DIALING - Анкоды преобразуются к виду используемому в словарях AOT. (двухбуквенное обозначение) |
  • phpMorphy::RESOLVE_ANCODES_AS_TEXT - Развертывать анкод в текстовое представление. Формат - ЧАСТЬ_РЕЧИ граммема1, граммема2, … |

shm

Массив настроек разделяемой памяти(используется только для PHPMORPHY_STORAGE_SHM).

shm => array(
         // размер сегмента разделяемой памяти в байтах.
         // Предпочтительное значение: суммарный объем требуемых словарей + 10%.
	'segment_size' => int, 
        'semaphore_key' => int, // ключ для сегмента
	'segment_id' => int, // ключ для семафора
	'with_mtime' => bool, // автоматически перегружать изменившиеся словари
	'no_lock' => bool, // не использовать блокировку 
);

Размер сегмента можно указать глобально. Для этого необходимо ДО созданиния экземпляра phpMorphy объявить константу PHPMORPHY_SHM_SEGMENT_SIZE. т.е.

require_once('.../common.php');
 
...
 
define('PHPMORPHY_SHM_SEGMENT_SIZE', 32 * 1024 * 1024); 
 
...
 
$morphy = new phpMorphy(...);
...

по умолчанию размер сегмента равен 24Mb

Методы

Сервисные

string getEncoding()

Возвращает кодировку загруженного словаря.

echo $morphy->getEncoding();
// windows-1251 или utf-8 и т.п., в зависимость от словаря.

string getLocale()

Возвращает код языка. В формате ISO3166 код страны, символ '_', ISO639 код языка.

echo $morphy->getLocale();
// ru_RU или en_EN или uk_UA, в зависимости от словаря

phpMorphy_Shm_Cache getShmCache()

Возвращает экземпляр phpMorphy_Shm_Cache класса. Иногда может потребоваться освободить сегмент разделяемой памяти (например при обновлении словаря, или если требуется изменить размер сегмента при возникновении ошибки: 'Can`t find free space for XXX block' ). Следующий код позволяет это сделать

$morphy->getShmCache()->free()

В связи с особенностями разделяемой памяти, освобождение происходит не сразу, а после того как будут закрыты все открытые дескрипторы для данного сегмента.

Посмотреть список загруженных файлов можно при помощи

var_dump($morphy->getShmCache()->getFilesList());

Удалить загруженный файл(не путать с удалением сегмента)

// $filePath путь к файлу, можно посмотреть при помощи getFilesList()
$morphy->getShmCache()->delete($filePath);
// $morphy->getShmCache()->clear(); // удалить все файлы

phpMorphy_Morphier_Interface getCommonMorphier()

Возвращает экземпляр класса реализующий phpMorphy_Morphier_Interface интерфейс. Используется только поиск по словарю.

phpMorphy_Morphier_Interface getPredictBySuffixMorphier()

Возвращает экземпляр класса реализующий phpMorphy_Morphier_Interface интерфейс. Используется только предсказание путем отсечения префикса.

phpMorphy_Morphier_Interface getPredictByDatabaseMorphier()

Возвращает экземпляр класса реализующий phpMorphy_Morphier_Interface интерфейс. Используется только предсказание по окончанию.

phpMorphy_Morphier_Interface getBulkMorphier()

Возвращает экземпляр phpMorphy_Morphier_Bulk класса. Используется пакетный режим обработки слов, только поиск по словарю.

Основные

bool phpMorphy:: isLastPredicted()

Функция возвращает TRUE если при анализе последнего слова выяснилось, что слово отсутствует в словаре и было предсказано. FALSE в ином случае. Функция не работает для bulk режима.

// слова ГЛОКАЯ нет в словаре, слово ТЕСТ есть в словаре
print_r ($morphy->lemmatize('ГЛОКАЯ', phpMorphy::NORMAL)); // ГЛОКАЯ
print_r($morphy->isLastPredicted()); // TRUE
// слово было предсказано
 
print_r ($morphy->lemmatize('ГЛОКАЯ', phpMorphy::IGNORE_PREDICT)); // FALSE 
print_r($morphy->isLastPredicted()); // FALSE
// если предыдущий вызов (lemmatize к примеру) вернул FALSE isLastPredicted() возвращает FALSE
 
$morphy->lemmatize('ТЕСТ', phpMorphy::NORMAL);
print_r($morphy->isLastPredicted()); // FALSE
// слово ТЕСТ было найдено в словаре
 
$morphy->lemmatize('ТЕСТ', phpMorphy::ONLY_PREDICT);
print_r($morphy->isLastPredicted()); // TRUE
// был использован режим ONLY_PREDICT соответственно ТЕСТ было предсказано

mixed phpMorphy::getLastPredictionType()

Функция возвращает константу определяющую, каким способом было предсказано последнее слово. Функция не работает для bulk режима. phpMorphy::PREDICT_BY_NONE – предсказание не использовано. Возможны следующие случаи: 1) Слово было найдено в словаре, предсказание не использовалось. 2) Слово отсутствует в словаре, предсказать не удалось (к примеру, метод $morphy→lemmatize($word) возвратил FALSE) phpMorphy::PREDICT_BY_SUFFIX – слово было предсказано по окончанию. phpMorphy::PREDICT_BY_DB – слово было предсказано по базе окончаний.

$morphy->lemmatize('ТЕСТ', phpMorphy::NORMAL);
print_r($morphy-> getLastPredictionType() == phpMorphy::PREDICT_BY_NONE); // TRUE
// слово ТЕСТ есть в словаре, предсказание не использовалось.
 
$morphy->lemmatize('ГЛОКАЯ', phpMorphy:: IGNORE_PREDICT);
print_r($morphy-> getLastPredictionType() == phpMorphy::PREDICT_BY_NONE); // TRUE
// слово ГЛОКАЯ отсутствует в  словаре, предсказать не удалось (lemmatize вернул FALSE).
 
$morphy->lemmatize('ТЕСТДРАЙВ', phpMorphy::ONLY_PREDICT);
print_r($morphy-> getLastPredictionType() == phpMorphy::PREDICT_BY_SUFFIX); // TRUE
 
$morphy->lemmatize('ПОДФИГАЧИТЬ', phpMorphy::ONLY_PREDICT);
print_r($morphy-> getLastPredictionType() == phpMorphy::PREDICT_BY_DB); // TRUE
 

Следующие методы имеют схожую сигнатуру.

mixed phpMorphy::xxx($word, $type = self::NORMAL)

где xxx – findWord, lemmatize, getBaseForm, getPseudoRoot, getPartOfSpeech, getAllFormsWithGramInfo и т.д. $word – строка или массив.

  1. Строка – слово для анализа. Если слово не было найдено в словаре или предсказано, функция возвращает FALSE.
  2. Массив – массив слов для анализа. Это так называемый bulk режим, благодаря некоторым оптимизациям внутри кода, позволяет увеличить скорость обработки слов на ~50%. В данном режиме функция возвращает массив, в качестве ключа выступает исходное слово, соответствующее значение – результат.
$words = array(
	'СОБАКА',
	'КОШКА',
);
 
$result = array();
foreach($words as $word) {
	$result[$word] = $morphy->lemmatize($word);
}
 
// $result можно получить на 50% быстрее с помощью $result = $morphy->lemmatize($words) в bulk режиме

Следует заметить, что phpMorphy::getLastPredictionType() и phpMorphy:: isLastPredicted() не работают в bulk режиме. $type – указывает порядок обработки для конкретного слова (списка слов в bulk режиме). Может принимать значения:

  1. phpMorphy::NORMAL – значение по умолчанию, в этом режиме обработка слова производится в следующем порядке:
    1. идет поиск в словаре
    2. если в словаре слово не найдено, то пытаемся предсказать в соответствии с настройками предсказания при инициализации (predict_by_suffix, predict_by_db опции).
    3. если предсказать не удалось, возвращаем FALSE
  2. phpMorphy::IGNORE_PREDICT – отключает предсказание т.е. поиск слова идет только по словарю. Если слова в словаре нет, возвращает FALSE
  3. phpMorphy::ONLY_PREDICT – отключает поиск по словарю, используется только предсказание, в соответствии с настройками предсказания при инициализации. Если предсказать не удалось (к примеру, predict_by_suffix и predict_by_db установлены в false) возвращаем FALSE.

Далее будут описаны только уникальные свойства для каждого метода, на основе одиночного режима (для bulk результат помещается в массив).

mixed phpMorphy::findWord($word, $type = self::NORMAL)

Производит анализ слова, возвращает коллекцию типа phpMorphy_WordDescriptor_Collection. Используется для детального анализа слов,

$word = 'ДУША';
if(false === ($paradigms = $morphy->findWord($word))) {
    die('Can`t find word');
}
 
// получить только существительные можно при помощи
foreach($paradigms->getByPartOfSpeech('С') as $paradigm) {
    echo 'Существительное ', $paradigm->getBaseForm(), PHP_EOL;
}
 
// обрабатываем омонимы
foreach($paradigms as $paradigm) {
    echo 'Лемма: ', $paradigm->getBaseForm(), PHP_EOL;
    echo 'Все формы: ', implode(',', $paradigm->getAllForms()), PHP_EOL;
 
    // информация о искомом слове т.к. в парадигме словоформы могут повторятся $found_word - массив
    $found_word_ary = $paradigm->getFoundWordForm();
 
    foreach($found_word_ary as $found_form) {
        echo $found_form->getWord(), ' - ', $found_form->getPartOfSpeech(), ' ', implode(',', $found_form->getGrammems()) . PHP_EOL;
    }
 
    if($paradigm->hasGrammems('НО')) {
        echo "$word - неодушевлённое\n";
    }
 
    echo 'форм в именительном падеже = ', count($paradigm->getWordFormsByGrammems('ИМ')), PHP_EOL;
 
    // аналогично используется hasPartOfSpeech, getWordFormsByPartOfSpeech
 
    echo PHP_EOL, 'Все формы с грамматической информацией', PHP_EOL;
    foreach($paradigm as $form) {
        echo $form->getWord(), ' - ';
 
        if($form->hasGrammems('ИМ')) { // есть граммема ИМ?
            echo 'именительный';
        } else if($form->hasGrammems(array('ЕД', 'РД'))) { // у формы должны присутствовать граммемы ЕД и РД
            echo 'родительный, единственное число';
        } else {
            echo $form->getPartOfSpeech(), ' ', implode(',', $form->getGrammems());
        }
 
        echo PHP_EOL;
    }
 
    echo '---------', PHP_EOL;
}
 

mixed phpMorphy::lemmatize($word, $type = self::NORMAL)

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

var_dump($morphy->lemmatize('КОЛБАСЫ')); // array('КОЛБАСА')
var_dump($morphy->lemmatize('ТЕСТ')); // array('ТЕСТ', 'ТЕСТО')
// ТЕСТ отождествляется с формами слов
// ТЕСТ – единственное число, именительный, винительный падежи
// ТЕСТО – множественное число, родительный падеж
var_dump($morphy->lemmatize('ГЛОКАЯ', phpMorphy::IGNORE_PREDICT)); // FALSE
 
var_dump($morphy->lemmatize(array('КОЛБАСЫ', 'ТЕСТ', 'ГЛОКАЯ'), phpMorphy::IGNORE_PREDICT));
// array(
//	'КОЛБАСЫ' => array('КОЛБАСА'),
//	'ТЕСТ'    => array('ТЕСТ', 'ТЕСТО'),
//	'ГЛОКАЯ'  => false
// )

mixed phpMorphy::getBaseForm($word, $type = self::NORMAL)

Это синоним для метода lemmatize

mixed phpMorphy::getAllForms($word, $type = self::NORMAL)

Возвращает список всех форм (в виде массива) для слова. Если $word отождествляется с формами разных слов, словоформы для каждого слова сливаются в один массив.

$result = $morphy->getAllForms('ТЕСТ'));
// В $result помещаются все формы для слов ТЕСТ и ТЕСТО

mixed phpMorphy::getPseudoRoot($word, $type = self::NORMAL)

Возвращает общую часть для всех словоформ заданного слова. Общая часть может быть пустой (к примеру, для слова ДЕТИ). Этот метод не возвращает корень слова в привычном его понимании (только longest common substring для всех словоформ). Всегда возвращает строку (не массив!).

var_dump($morphy->getPseudoRoot('ТЕСТ')); // string('ТЕСТ')
var_dump($morphy->getPseudoRoot('ДЕТЕЙ')); // string('')

mixed phpMorphy::getPartOfSpeech($word, $type = self::NORMAL)

Возвращает часть речи для заданного слова. Т.к. словоформа может образовываться от нескольких слов, метод возвращает массив. Возвращаемое значение зависит от опции инициализации graminfo_as_text. Если graminfo_as_text = true часть речи представляется в текстовом виде, иначе в виде значения константы. (подробнее см. выше)

var_dump($morphy->getPartOfSpeech('ТЕСТ'));  // array('С')
// ТЕСТ образовывается от ТЕСТ и ТЕСТО, однако оба слова являются существительными
 
var_dump($morphy->getPartOfSpeech('ДУША'));  // array('С', 'ДЕЕПРИЧАСТИЕ')
// ДУША образовывается от ДУШ, ДУША и ДУШИТЬ

mixed phpMorphy::getAllFormsWithGramInfo($word, $asText = true, $type = self::NORMAL)

Возвращает массив в формате

array(
	// омоним №1
	array(
		'forms' => array(
		),
		'all' => array(
			массив содержит часть речи и граммемы для каждой формы из 'forms'. Граммемы разделены запятой. Часть речи отделена от граммем пробелом.
			например: ПРИЧАСТИЕ ДСТ,ЕД,ИМ,МР,НО,НП,ОД,ПРШ,СВ
		),
		'common' => строка содержащая общие для всех форм граммемы
)
)

Данный метод рекомендуется использовать только для отладки. Для анализа используйте метод findWord(). Если $asText = true грамматическая информация возвращается в виде строки, как описано выше. Иначе в виде массива

array(
    'pos' => часть речи,
    'grammems' => array(массив граммем)
)
var_dump($morphy->getAllFormsWithGramInfo('ТЕСТ', true);
/*
Результат:
array(2) {
  [0]=>
  array(3) {
    ["forms"]=>
    array(12) {
      [0]=>
      string(4) "ТЕСТ"
      [1]=>
      string(4) "ТЕСТ"
      [2]=>
      string(5) "ТЕСТА"
      [3]=>
      string(5) "ТЕСТУ"
      [4]=>
      string(6) "ТЕСТОМ"
      [5]=>
      string(5) "ТЕСТЕ"
      [6]=>
      string(5) "ТЕСТЫ"
      [7]=>
      string(5) "ТЕСТЫ"
      [8]=>
      string(6) "ТЕСТОВ"
      [9]=>
      string(6) "ТЕСТАМ"
      [10]=>
      string(7) "ТЕСТАМИ"
      [11]=>
      string(6) "ТЕСТАХ"
    }
    ["all"]=>
    array(12) {
      [0]=>
      string(13) "С ЕД,ИМ,МР,НО"
      [1]=>
      string(13) "С ВН,ЕД,МР,НО"
      [2]=>
      string(13) "С ЕД,МР,НО,РД"
      [3]=>
      string(13) "С ДТ,ЕД,МР,НО"
      [4]=>
      string(13) "С ЕД,МР,НО,ТВ"
      [5]=>
      string(13) "С ЕД,МР,НО,ПР"
      [6]=>
      string(13) "С ИМ,МН,МР,НО"
      [7]=>
      string(13) "С ВН,МН,МР,НО"
      [8]=>
      string(13) "С МН,МР,НО,РД"
      [9]=>
      string(13) "С ДТ,МН,МР,НО"
      [10]=>
      string(13) "С МН,МР,НО,ТВ"
      [11]=>
      string(13) "С МН,МР,НО,ПР"
    }
    ["common"]=>
    string(0) ""
  }
  [1]=>
  array(3) {
    ["forms"]=>
    array(12) {
      [0]=>
      string(5) "ТЕСТО"
      [1]=>
      string(5) "ТЕСТО"
      [2]=>
      string(5) "ТЕСТА"
      [3]=>
      string(5) "ТЕСТА"
      [4]=>
      string(5) "ТЕСТА"
      [5]=>
      string(5) "ТЕСТУ"
      [6]=>
      string(6) "ТЕСТОМ"
      [7]=>
      string(5) "ТЕСТЕ"
      [8]=>
      string(4) "ТЕСТ"
      [9]=>
      string(6) "ТЕСТАМ"
      [10]=>
      string(7) "ТЕСТАМИ"
      [11]=>
      string(6) "ТЕСТАХ"
    }
    ["all"]=>
    array(12) {
      [0]=>
      string(13) "С ЕД,ИМ,НО,СР"
      [1]=>
      string(13) "С ВН,ЕД,НО,СР"
      [2]=>
      string(13) "С ЕД,НО,РД,СР"
      [3]=>
      string(13) "С ИМ,МН,НО,СР"
      [4]=>
      string(13) "С ВН,МН,НО,СР"
      [5]=>
      string(13) "С ДТ,ЕД,НО,СР"
      [6]=>
      string(13) "С ЕД,НО,СР,ТВ"
      [7]=>
      string(13) "С ЕД,НО,ПР,СР"
      [8]=>
      string(13) "С МН,НО,РД,СР"
      [9]=>
      string(13) "С ДТ,МН,НО,СР"
      [10]=>
      string(13) "С МН,НО,СР,ТВ"
      [11]=>
      string(13) "С МН,НО,ПР,СР"
    }
    ["common"]=>
    string(0) ""
  }
}
*/

mixed phpMorphy::getAllFormsWithAncodes($word, $type = self::NORMAL)

Вывод похож на getAllFormsWithGramInfo(), но грамматическая информация возвращается в виде анкодов (согласно опции resolve_ancodes). Если resolve_ancodes = phpMorphy::RESOLVE_ANCODES_AS_TEXT вывод аналогичен $morphy→getAllFormsWithGramInfo($word, true).

$opts = array(
    'resolve_ancode' => phpMorphy::RESOLVE_ANCODES_AS_TEXT,);
 
var_dump($morphy-> getAllFormsWithAncodes('Я'));
 
/*
Результат:
array(1) {
  [0]=>
  array(3) {
    ["forms"]=>
    array(7) {
      [0]=>
      string(1) "Я"
      [1]=>
      string(4) "МЕНЯ"
      [2]=>
      string(4) "МЕНЯ"
      [3]=>
      string(3) "МНЕ"
      [4]=>
      string(3) "МНЕ"
      [5]=>
      string(4) "МНОЙ"
      [6]=>
      string(4) "МНОЮ"
    }
    ["common"]=>
    NULL
    ["all"]=>
    array(7) {
      [0]=>
      string(11) "МС 1Л,ЕД,ИМ"
      [1]=>
      string(11) "МС 1Л,ЕД,РД"
      [2]=>
      string(11) "МС 1Л,ЕД,ВН"
      [3]=>
      string(11) "МС 1Л,ЕД,ДТ"
      [4]=>
      string(11) "МС 1Л,ЕД,ПР"
      [5]=>
      string(11) "МС 1Л,ЕД,ТВ"
      [6]=>
      string(11) "МС 1Л,ЕД,ТВ"
    }
  }
}
*/

mixed phpMorphy::getAncode($word, $type = self::NORMAL)

Возвращает анкоды для слова.

var_dump($morphy->getAncode('ТЕСТ'));
 
/*
Результат:
array(2) {
  [0]=>
  array(2) {
    ["common"]=>
    string(3) " НО"
    ["all"]=>
    array(2) {
      [0]=>
      string(10) "С МР,ЕД,ИМ"
      [1]=>
      string(10) "С МР,ЕД,ВН"
    }
  }
  [1]=>
  array(2) {
    ["common"]=>
    string(3) " НО"
    ["all"]=>
    array(1) {
      [0]=>
      string(10) "С СР,МН,РД"
    }
  }
}
*/

mixed phpMorphy::getGramInfo($word, $type = self::NORMAL)

Возвращает грамматическую информацию для слова

var_dump($morphy-> getGramInfo('ТЕСТ'));
 
/*
Результат:
array(2) {
  [0]=>
  array(2) {
    [0]=>
    array(3) {
      ["pos"]=>
      string(1) "С"
      ["grammems"]=>
      array(4) {
        [0]=>
        string(2) "ВН"
        [1]=>
        string(2) "ЕД"
        [2]=>
        string(2) "МР"
        [3]=>
        string(2) "НО"
      }
      ["form_no"]=>
      int(0)
    }
    [1]=>
    array(3) {
      ["pos"]=>
      string(1) "С"
      ["grammems"]=>
      array(4) {
        [0]=>
        string(2) "ЕД"
        [1]=>
        string(2) "ИМ"
        [2]=>
        string(2) "МР"
        [3]=>
        string(2) "НО"
      }
      ["form_no"]=>
      int(0)
    }
  }
  [1]=>
  array(1) {
    [0]=>
    array(3) {
      ["pos"]=>
      string(1) "С"
      ["grammems"]=>
      array(4) {
        [0]=>
        string(2) "МН"
        [1]=>
        string(2) "НО"
        [2]=>
        string(2) "РД"
        [3]=>
        string(2) "СР"
      }
      ["form_no"]=>
      int(5)
    }
  }
}
*/

mixed phpMorphy::getGramInfoMergeForms($word, $type = self::NORMAL)

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

var_dump($morphy-> getGramInfoMergeForms ('ТЕСТ'));
 
/*
Результат:
array(2) {
  [0]=>
  array(5) {
    ["pos"]=>
    string(1) "С"
    ["grammems"]=>
    array(5) {
      [0]=>
      string(2) "ВН"
      [1]=>
      string(2) "ЕД"
      [2]=>
      string(2) "ИМ"
      [3]=>
      string(2) "МР"
      [4]=>
      string(2) "НО"
    }
    ["forms_count"]=>
    int(2)
    ["form_no_low"]=>
    int(0)
    ["form_no_high"]=>
    int(2)
  }
  [1]=>
  array(5) {
    ["pos"]=>
    string(1) "С"
    ["grammems"]=>
    array(4) {
      [0]=>
      string(2) "МН"
      [1]=>
      string(2) "НО"
      [2]=>
      string(2) "РД"
      [3]=>
      string(2) "СР"
    }
    ["forms_count"]=>
    int(1)
    ["form_no_low"]=>
    int(5)
    ["form_no_high"]=>
    int(6)
  }
}
*/

Обратите внимание, граммемы ИМ и ВН для парадигмы слова ТЕСТ (не ТЕСТО) объединены в один массив, в отличие от getGramInfo().

mixed phpMorphy::castFormByGramInfo($word, $partOfSpeech, $grammems, $returnOnlyWord = false, $callback = null, $type = self::NORMAL)

Приводит слово в заданную форму. $partOfSpeech – необходим только для прилагательных и глаголов т.к. только для этих частей речи внутри парадигмы встречаются различные части речи. Если $partOfSpeech == null, часть речи не используется.

$word = 'ШКАФ';
 
// поставим слово ШКАФ в множественное число, предложный падеж
var_dump($morphy->castFormByGramInfo($word, null, array('МН', 'ПР'), false));
/*
Результат:
array(1) {
  [0]=>
  array(4) {
    ["form"]=>
    string(6) "ШКАФАХ"
    ["form_no"]=>
    int(12)
    ["pos"]=>
    string(1) "С"
    ["grammems"]=>
    array(4) {
      [0]=>
      string(2) "МР"
      [1]=>
      string(2) "МН"
      [2]=>
      string(2) "ПР"
      [3]=>
      string(2) "НО"
    }
  }
}
*/
 
// возвращает только слово, без грамматической информации
var_dump($morphy->castFormByGramInfo($word, null, array('МН', 'ПР'), true));
/*
Результат:
array(1) {
  [0]=>
  string(6) "ШКАФАХ"
}
*/
 
// применим пользовательский фильтр
// фильтр – предикат (функция возвращающая true/false) со следующей сигнатурой:
// function XXX($form, $partOfSpeech, $grammems, $formNo)
// если функция возвращает TRUE, то исходное слово приводится в данную форму
// $callback – обычная функция обратного вызова, может принимать значения допустимые для call_user_func(…) т.е. is_callable($callback) === true.
 
function cast_predicate($form, $partOfSpeech, $grammems, $formNo) {
    return in_array('ИМ', $grammems); 
}
 
// приведём ШКАФ в именительный падеж
var_dump($morphy->castFormByGramInfo($word, null, null, true, 'cast_predicate'));
/*
Результат:
array(2) {
  [0]=>
  string(4) "ШКАФ"
  [1]=>
  string(5) "ШКАФЫ"
}
*/
 
// выберем краткое прилагательное единственного числа, женского рода.
// если не указать часть речи, будут выбраны все прилагательные единственного числа, женского рода
var_dump($morphy->castFormByGramInfo('КРАСНЫЙ', 'КР_ПРИЛ', array('ЕД', 'ЖР'), true));
/*
Результат:
array(1) {
  [0]=>
  string(6) "КРАСНА"
}
*/
 

mixed phpMorphy::castFormByPattern($word, $patternWord, phpMorphy_GrammemsProvider_Interface $grammemsProvider = null, $returnOnlyWord = false, $callback = null, $type = self::NORMAL)

Приводит слово $word в форму в которой стоит слово $patternWord

var_dump($morphy->castFormByPattern('ДИВАН', 'СТОЛАМИ', null, true)); 
/*
Результат:
array(1) {
  [0]=>
  string(8) "ДИВАНАМИ"
}
*/
 

Сложность возникает, если некоторые граммемы у слов не совпадают. Т.к. данная функция ищет в парадигме слова $word форму у которой граммемы совпадают с граммемами $patternWord, то в таких случаях на выходе получим пустой результат. Например, ДИВАН и КРОВАТЬ имеют разный род (мужской и женский соответственно).

var_dump($morphy->castFormByPattern('ДИВАН', 'КРОВАТЯМИ', null, true)); 
/*
Результат:
array(0) {
}
*/

Нам требуется указать, что род сравнивать не нужно. Можно это сделать следующим способом

$provider = $morphy->getGrammemsProvider();
$provider->excludeGroups('С', 'род');
/*
указываем, что для существительных род сравнивать не будем.
 
Первым параметром указывается часть речи, для которой требуется внести изменения
Вторым - группу граммем, которую необходимо исключить, может принимать следующие значения:
1)	род
2)	одушевленность 
3)	число 
4)	падеж 
5)	залог 
6)	время 
7)	повелительная форма 
8)	лицо
9)	сравнительная форма 
10)	превосходная степень
11)	вид
12)	переходность
13)	безличный глагол
 
следует помнить, что все данные должны быть в кодировке словаря
*/
var_dump($morphy->castFormByPattern('ДИВАН', 'КРОВАТЯМИ', $provider, true)); 
var_dump($morphy->castFormByPattern('КРЕСЛО', 'СТУЛЬЯМИ', $provider, true)); 
/*
Результат:
array(1) {
  [0]=>
  string(8) "ДИВАНАМИ"
}
*/ 
 
/*
Чтобы не передавать $provider каждый раз, можно сделать изменения глобально
*/
$morphy->getDefaultGrammemsProvider()->excludeGroups('С', 'род');
var_dump($morphy->castFormByPattern('ДИВАН', 'КРОВАТЯМИ', null, true)); 
 

mixed phpMorphy::castFormByAncode($word, $ancode, $commonAncode = null, $returnOnlyWord = false, $callback = null, $type = self::NORMAL)

Аналогично castFormByGramInfo, но грамматическая информация указывается в виде анкода (согласно опции resolve_ancodes).

 
manual.txt · Последние изменения: 2010/01/14 12:08 От heromantor
 
За исключением случаев, когда указано иное, содержимое этой вики предоставляется на условиях следующей лицензии:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Get phpMorphy at SourceForge.net. Fast, secure and Free Open Source software downloads Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki