Компонент String

Дата оновлення перекладу 2022-12-12

Компонент String

Компонент String надає API, орієнтований на один обʼєкт, для роботи з трьома "модульними системами" рядків: байтами, кодовими точками та графемами.

Установка

1
$ composer require symfony/string

Note

Якщо ви встановлюєте цей компонент поза додатком Symfony, вам потрібно підключити файл vendor/autoload.phpу вашому коді для включення механізму автозавантаження класів, наданих Composer. Детальніше можна прочитати у цій статті.

Що таке String?

Ви можете пропустити цей розділ, якщо ви вже знаєте, що таке "кодова точка" або "графема" в контексті обробки рядків. Якщо ні, то прочитайте цей розділ, щоб вивчити термінлогію, використовувану даним компонентом.

Мови, на кшталт англійської, вимагають дуже обмеженого набору знаків та символів для відображення будь-якого змісту. Кожний рядок - це набір знаків (літер або символів), які можуть бути зашифровані навіть з найобмеженішими стандартами (наприклад, ASCII).

Однак, інші мови вимагають тисячі знаків для відображення свого змісту. Їм необхідні складні стандарти шифрування на кштшалт Юнікоду та концепції типу "знак" більше не мають сенсу. Замість цього, вам потрібно буде стикатися з такими термінами:

  • Кодові точки: це елементарна одиниця інформації. String - це серія кодових точок. Кожна кодова точка - це число, значення якого надається стандартом Юнікод. Наприклад, англійська літера A - це кодова точка U+0041, а японська кана - це кодова точка U+306E.
  • Графеми: це послідовність однієї або більше кодових точок, які відображаються у вигляді єдиної графічної одиниці. Наприклад, іспанська літера ñ - це графема, яка містить дві кодові точки: U+006E = n ("маленька літера N латиницею") + U+0303 = ◌̃ ("комбінуюча тильда").
  • Байти: реальна інформація, що зберігається у змісті рядків. Кожна кодова точка може вимагати один або більше байтів зберігання в залежності від використовуваного стандарту (UTF-8, UTF-16, і т.д.).

Наступне зображення відображає байти, кодові точки та графеми для одного й того ж слова, написаного англійською (hello), та хінді (नमस्ते):

Використання

Створіть новий обʼєкти типу ByteString, CodePointString або UnicodeString, передайте зміст рядку як його аргументи, а потім використайте обʼєктно-орієнтований API для роботи з цими рядками:

1
2
3
4
5
6
7
8
9
10
11
12
use Symfony\Component\String\UnicodeString;

$text = (new UnicodeString('This is a déjà-vu situation.'))
    ->trimEnd('.')
    ->replace('déjà-vu', 'jamais-vu')
    ->append('!');
// $text = 'This is a jamais-vu situation!'

$content = new UnicodeString('नमस्ते दुनिया');
if ($content->ignoreCase()->startsWith('नमस्ते')) {
    // ...
}

Довідник методів

Методи створення обʼєктів рядку

Спочатку ви можете створювати обʼєкти, готові для зберігання рядків як байтів, кодових точок та графем з наступними класами:

1
2
3
4
5
6
7
8
use Symfony\Component\String\ByteString;
use Symfony\Component\String\CodePointString;
use Symfony\Component\String\UnicodeString;

$foo = new ByteString('hello');
$bar = new CodePointString('hello');
// UnicodeString - це найвикористовуваніший клас
$baz = new UnicodeString('hello');

Використайте статичний метод wrap(), щоб інстанціювати більше одного обʼєкта рядку:

1
2
3
4
5
6
7
$contents = ByteString::wrap(['hello', 'world']);        // $contents = ByteString[]
$contents = UnicodeString::wrap(['I', '❤️', 'Symfony']); // $contents = UnicodeString[]

// використайте метод розпаковки, щоб створити інверсовану конверсію
$contents = UnicodeString::unwrap([
    new UnicodeString('hello'), new UnicodeString('world'),
]); // $contents = ['hello', 'world']

Якщо ви працюєте з багатьма обʼєктами Рядку, розгляньте використання скорочень функцій, щоб зробити ваш код ємнішим:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// функція b() створює байтові рядки
use function Symfony\Component\String\b;

// обидва рядки однакові
$foo = new ByteString('hello');
$foo = b('hello');

// функція u() створює рядки Юнікоду
use function Symfony\Component\String\u;

// обидва рядки однакові
$foo = new UnicodeString('hello');
$foo = u('hello');

// функція s() створює байтовий рядок або рядок Юнікоду,
// залежно від наданого змісту
use function Symfony\Component\String\s;

// створює обʼєкт ByteString
$foo = s("\xfe\xff");
// створює обʼєкт UnicodeString
$foo = s('अनुच्छेद');

Також існують спеціальні конструктори:

1
2
3
4
5
6
7
8
9
10
// ByteString може створити довільний рядок заданої довжини
$foo = ByteString::fromRandom(12);
// за замовчуванням, довільні рядки використовують символи A-Za-z0-9; ви можете обмежити
// використовувані символи за допомогою другого необовʼязкового аргументу
$foo = ByteString::fromRandom(6, 'AEIOU0123456789');
$foo = ByteString::fromRandom(10, 'qwertyuiop');

// CodePointString і UnicodeString можуть створити рядок з кодових точок
$foo = UnicodeString::fromCodePoints(0x928, 0x92E, 0x938, 0x94D, 0x924, 0x947);
// еквівалентно: $foo = new UnicodeString('नमस्ते');

Методи перетворення обʼєктів рядку

Кожний обʼєкт рядку може бути перетворений на два інших типи обʼєкту:

1
2
3
4
5
6
7
8
$foo = ByteString::fromRandom(12)->toCodePointString();
$foo = (new CodePointString('hello'))->toUnicodeString();
$foo = UnicodeString::fromCodePoints(0x68, 0x65, 0x6C, 0x6C, 0x6F)->toByteString();

// необовʼязковий аргумент $toEncoding визначає шифрування цільового рядку
$foo = (new CodePointString('hello'))->toByteString('Windows-1252');
// необовʼязковий аргумент $fromEncoding визначає шифрування початкового рядку
$foo = (new ByteString('さよなら'))->toCodePointString('ISO-2022-JP');

Якщо перетворення неможливе через будь-яку причину, ви отримаєте InvalidArgumentException.

Також існує метод отримання байтів, що зберігаються в якомусь місці:

1
2
3
4
5
6
7
// ('नमस्ते' bytes = [224, 164, 168, 224, 164, 174, 224, 164, 184,
//                  224, 165, 141, 224, 164, 164, 224, 165, 135])
b('नमस्ते')->bytesAt(0);   // [224]
u('नमस्ते')->bytesAt(0);   // [224, 164, 168]

b('नमस्ते')->bytesAt(1);   // [164]
u('नमस्ते')->bytesAt(1);   // [224, 164, 174]

Методи, повʼязані з довжиною та вільними просторами

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// повертає кількість графем, кодових точок або байтів заданого рядку
$word = 'नमस्ते';
(new ByteString($word))->length();      // 18 (байтів)
(new CodePointString($word))->length(); // 6 (кодових точок)
(new UnicodeString($word))->length();   // 4 (графем)

// деякі символи вимагають вдвічі більше простору, ніж інші, для відображення при використанні
// моноширинного шрифту (наприклад, в консолі). Цей метод повертає загальну довжину, необхідну
// відображення всього слова
$word = 'नमस्ते';
(new ByteString($word))->width();      // 18
(new CodePointString($word))->width(); // 4
(new UnicodeString($word))->width();   // 4
// якщо текст містить декілька рядків, він повертає максимальну довжину всіх рядків
$text = "<<<END
This is a
multiline text
END";
u($text)->width(); // 14

// повертає TRUE лише якщо рядок пустий (навіть без вільних просторів)
u('hello world')->isEmpty();  // false
u('     ')->isEmpty();        // false
u('')->isEmpty();             // true

// видаляє всі вільні простори з початку до кінця рядку та замінює два або
// більше послідовних пробіли всерредині змісту на один
u("  \n\n   hello        world \n    \n")->collapseWhitespace(); // 'hello world'

Методи зміни регістру

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// змінює всі графеми/кодові точки на нижній регістр
u('FOO Bar')->lower();  // 'foo bar'

// при роботі з різними мовами, нижнього/верхнього регістру недостатньо
// тоді регістри три (нижній, верхній, заголовний), деякі символи не мають регістру,
// регістр чутливий до контексту, локалі та ін.
// цей метод повертає рядок, який ви можете використати в нечутливих до регістру порівняннях
u('FOO Bar')->folded();             // 'foo bar'
u('Die O\'Brian Straße')->folded(); // "die o'brian strasse"

// змінює всі графеми/кодові точки на верхній регістр
u('foo BAR')->upper(); // 'FOO BAR'

// змінює всі графеми/кодові точки на "заголовний регістр"
u('foo bar')->title();     // 'Foo bar'
u('foo bar')->title(true); // 'Foo Bar'

// змінює всі графеми/кодові точки на camelCase
u('Foo: Bar-baz.')->camel(); // 'fooBarBaz'
// змінює всі графеми/кодові точки на snake_case
u('Foo: Bar-baz.')->snake(); // 'foo_bar_baz'
// інших регістрів можна досягнути, змінюючи методи. Наприклад, PascalCase:
u('Foo: Bar-baz.')->camel()->title(); // 'FooBarBaz'

Методи всіх класів рядків чутливі до регістру за замовчуванням. Ви можете виконати нечутливі до регістру операції за допомогою методу ignoreCase():

1
2
u('abc')->indexOf('B');               // null
u('abc')->ignoreCase()->indexOf('B'); // 1

Методи додавання до початку та кінця

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// додає заданий зміст (один або більше рядків) на початку/кінці рядку
u('world')->prepend('hello');      // 'helloworld'
u('world')->prepend('hello', ' '); // 'hello world'

u('hello')->append('world');      // 'helloworld'
u('hello')->append(' ', 'world'); // 'hello world'

// додає заданий зміст на початку рядку (або видаляє його), щоб гарантувати, що
// зміст починається саме з цього
u('Name')->ensureStart('get');       // 'getName'
u('getName')->ensureStart('get');    // 'getName'
u('getgetName')->ensureStart('get'); // 'getName'
// цей метод схожий, але працює з кінцем змісту, а не з початком
u('User')->ensureEnd('Controller');           // 'UserController'
u('UserController')->ensureEnd('Controller'); // 'UserController'
u('UserControllerController')->ensureEnd('Controller'); // 'UserController'

// повертає весь зміст, знайдений до/після першої появи заданого рядку
u('hello world')->before('world');   // 'hello '
u('hello world')->before('o');       // 'hell'
u('hello world')->before('o', true); // 'hello'

u('hello world')->after('hello');   // ' world'
u('hello world')->after('o');       // ' world'
u('hello world')->after('o', true); // 'o world'

// повертає весь зміст, знайдений до/післе останньої появи заданого рядку
u('hello world')->beforeLast('o');       // 'hello w'
u('hello world')->beforeLast('o', true); // 'hello wo'

u('hello world')->afterLast('o');       // 'rld'
u('hello world')->afterLast('o', true); // 'orld'

Методи заповнення та усікання

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// робить рядок тієї ж довжини, що і перший аргумент, додаючи заданий
// рядок на початку, в кінці або по обидві сторони рядку
u(' Lorem Ipsum ')->padBoth(20, '-'); // '--- Lorem Ipsum ----'
u(' Lorem Ipsum')->padStart(20, '-'); // '-------- Lorem Ipsum'
u('Lorem Ipsum ')->padEnd(20, '-');   // 'Lorem Ipsum --------'

// повторює заданий рядок ту кількість разів, яка передана в аргументі
u('_.')->repeat(10); // '_._._._._._._._._._.'

// видаляє задані символи (за замовчуванням, вільні простори) з рядку
u('   Lorem Ipsum   ')->trim(); // 'Lorem Ipsum'
u('Lorem Ipsum   ')->trim('m'); // 'Lorem Ipsum   '
u('Lorem Ipsum')->trim('m');    // 'Lorem Ipsu'

u('   Lorem Ipsum   ')->trimStart(); // 'Lorem Ipsum   '
u('   Lorem Ipsum   ')->trimEnd();   // '   Lorem Ipsum'

// видаляє заданий зміст з початку/кінця рядку
u('file-image-0001.png')->trimPrefix('file-');           // 'image-0001.png'
u('file-image-0001.png')->trimPrefix('image-');          // 'file-image-0001.png'
u('file-image-0001.png')->trimPrefix('file-image-');     // '0001.png'
u('template.html.twig')->trimSuffix('.html');            // 'template.html.twig'
u('template.html.twig')->trimSuffix('.twig');            // 'template.html'
u('template.html.twig')->trimSuffix('.html.twig');       // 'template'
// при передаче массива префисков/суфиксов, усекается только первый найденный
u('file-image-0001.png')->trimPrefix(['file-', 'image-']); // 'image-0001.png'
u('template.html.twig')->trimSuffix(['.twig', '.html']);   // 'template.html'

Методи пошуку та заміни

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// перевіряє, чи починається/закінчується рядок з заданого рядку
u('https://symfony.com')->startsWith('https'); // true
u('report-1234.pdf')->endsWith('.pdf');        // true

// перевіряє, чи точно зміст рядку відповідає заданому змісту
u('foo')->equalsTo('foo'); // true

// перевіряє, чи відповідає зміст рядку заданому регулярному виразу
u('avatar-73647.png')->match('/avatar-(\d+)\.png/');
// result = ['avatar-73647.png', '73647']

// перевіряє, чи містить рядок будь-який з заданих рядків
u('aeiou')->containsAny('a');                 // true
u('aeiou')->containsAny(['ab', 'efg']);       // false
u('aeiou')->containsAny(['eio', 'foo', 'z']); // true

// знаходить місцезнаходження першого виявлення заданого рядку
// (другий аргумент - місцезнаходження, звідки починається пошук, негативні
// значення мають те ж значення, що і в PHP-функціях)
u('abcdeabcde')->indexOf('c');     // 2
u('abcdeabcde')->indexOf('c', 2);  // 2
u('abcdeabcde')->indexOf('c', -4); // 7
u('abcdeabcde')->indexOf('eab');   // 4
u('abcdeabcde')->indexOf('k');     // null

// знаходить місцезнаходження останнього виявлення заданого рядку
// (другий аргумент - місцезнаходження, звідки починається пошук, негативні
// значення мають те ж значення, що і в PHP-функціях)
u('abcdeabcde')->indexOfLast('c');     // 7
u('abcdeabcde')->indexOfLast('c', 2);  // 7
u('abcdeabcde')->indexOfLast('c', -4); // 2
u('abcdeabcde')->indexOfLast('eab');   // 4
u('abcdeabcde')->indexOfLast('k');     // null

// замінює всі виявлення заданого рядку
u('http://symfony.com')->replace('http://', 'https://'); // 'https://symfony.com'
// замінює всі виявлення заданого регулярного виразу
u('(+1) 206-555-0100')->replaceMatches('/[^A-Za-z0-9]++/', ''); // '12065550100'
// ви можете передати викликане в якості другого аргументу, щоб виконати проосунути заміни
u('123')->replaceMatches('/\d/', function ($match) {
    return '['.$match[0].']';
}); // result = '[1][2][3]'

Методи обʼєднання, розділення, усікання та реверсу

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// використовує рядок в якості "клею" для обʼєднання всіх заданих рядків
u(', ')->join(['foo', 'bar']); // 'foo, bar'

// розбиває рядок на частини, використовуючи заданих розділювач
u('template_name.html.twig')->split('.');    // ['template_name', 'html', 'twig']
// ви можете встановити максимальну кількість частин в якості другого аргументу
u('template_name.html.twig')->split('.', 2); // ['template_name', 'html.twig']

// повертає підрядок, який починається з першого аргументу і має довжину другого
// необовʼязкового аргументу (негативні значення мають те ж значення, що і в PHP-функціях)
u('Symfony is great')->slice(0, 7);  // 'Symfony'
u('Symfony is great')->slice(0, -6); // 'Symfony is'
u('Symfony is great')->slice(11);    // 'great'
u('Symfony is great')->slice(-5);    // 'great'

// зменшує рядок до довжини, заданої в якості аргументу (якщо він довший)
u('Lorem Ipsum')->truncate(3);             // 'Lor'
u('Lorem Ipsum')->truncate(80);            // 'Lorem Ipsum'
// другий аргумент - це символ(и), додані, коли рядок усікається
// (загальна довжина включає в себе довжину цього(цих) символа(ів))
u('Lorem Ipsum')->truncate(8, '…');        // 'Lorem I…'
// якщо третій аргумент - false, останнє слово до усікання залишається, навіть
// якщо це створює рядок, більше за описану довжину
u('Lorem Ipsum')->truncate(8, '…', false); // 'Lorem Ipsum'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// розбиває рядок на рядки заданої довжини
u('Lorem Ipsum')->wordwrap(4);             // 'Lorem\nIpsum'
// за замовчуванням розбиває за вільними просторами; передайте TRUE, щоб розбивати незалежно від цього
u('Lorem Ipsum')->wordwrap(4, "\n", true); // 'Lore\nm\nIpsu\nm'

// замінює частину рядку на заданий зміст:
// другий аргумент - місцезнаходження, з якого починається заміна;
// третій аргумент - кількість графем/кодових точок, видалених з рядку
u('0123456789')->splice('xxx');       // 'xxx'
u('0123456789')->splice('xxx', 0, 2); // 'xxx23456789'
u('0123456789')->splice('xxx', 0, 6); // 'xxx6789'
u('0123456789')->splice('xxx', 6);    // '012345xxx'

// розбиває рядок на частини довжиною, заданою аргументом
u('0123456789')->chunk(3);  // ['012', '345', '678', '9']

// реверсує порядок змісту рядку
u('foo bar')->reverse(); // 'rab oof'
u('さよなら')->reverse(); // 'らなよさ'

Методи, додані ByteString

Ці методи доступні лише для обʼєктів ByteString:

1
2
3
// повертає TRUE, якщо зміст рядку є валідним змістом UTF-8
b('Lorem Ipsum')->isUtf8(); // true
b("\xc3\x28")->isUtf8();    // false

Методи, додані CodePointString і UnicodeString

Ці методи доступні лише для обʼєктів CodePointString иі UnicodeString:

1
2
3
4
5
6
7
8
9
10
11
// транслітерує будь-який рядок у латинський алфавіт, визначений шифруванням ASCII
// (не використовуйте цей метод для створення слагера, так як даний компонент вже надає
// слагер, як пояснюється далі у статті)
u('नमस्ते')->ascii();    // 'namaste'
u('さよなら')->ascii(); // 'sayonara'
u('спасибо')->ascii(); // 'spasibo'

// повертає масив з кодовою точкою або точками, що зберігаються у заданому місцезнаходженні
// (кодові точки 'नमस्ते' графеми = [2344, 2350, 2360, 2340]
u('नमस्ते')->codePointsAt(0); // [2344]
u('नमस्ते')->codePointsAt(2); // [2360]

Еквівалентність Юнікоду - це специфікація стандарту Юнікод, за якою різні послідовності кодових точок надають один і той самий знак. Наприклад, шведська літера å може бути однією кодовою точкою (U+00E5 = "маленька латинська літера А з кільцем над нею") або послідовністю двох кодових точок (U+0061 = "маленька латинська літера A" + U+030A = "комбінація з кільцем зверху"). Метод normalize() дозволяє обрати режим нормалізації:

1
2
3
4
5
6
// ці зашифровують літеру як одну кодову точку: U+00E5
u('å')->normalize(UnicodeString::NFC);
u('å')->normalize(UnicodeString::NFKC);
// ці зашифровують літеру як дві кодові точки: U+0061 + U+030A
u('å')->normalize(UnicodeString::NFD);
u('å')->normalize(UnicodeString::NFKD);

Слагер

В деяких контекстах, на кшталт URL та назв файлів/каталогів, небезпечно використовувати будь-який символ Юнікоду. Слагер перетворює заданий рядок на інший рядок, який містить лише безпечні символи ASCII:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
use Symfony\Component\String\Slugger\AsciiSlugger;

$slugger = new AsciiSlugger();
$slug = $slugger->slug('Wôrķšƥáçè ~~sèťtïñğš~~');
// $slug = 'Workspace-settings'

// ви також можете передати масив з додатковими замінами символів
$slugger = new AsciiSlugger('en', ['en' => ['%' => 'percent', '€' => 'euro']]);
$slug = $slugger->slug('10% or 5€');
// $slug = '10-percent-or-5-euro'

// якщо для вашої локалі не існує відображення символу (наприклад, 'en_GB'), то буде використано
// відображення символу батьківської локалі (тобто, 'en')
$slugger = new AsciiSlugger('en_GB', ['en' => ['%' => 'percent', '€' => 'euro']]);
$slug = $slugger->slug('10% or 5€');
// $slug = '10-percent-or-5-euro'

// для динамічніших замін, передайте замикання PHP замість масиву
$slugger = new AsciiSlugger('en', function ($string, $locale) {
    return str_replace('❤️', 'love', $string);
});

Розділювач між словами - за замовчуванням дефіс (-), але ви можете визначити інший розділювач як другий аргумент:

1
2
$slug = $slugger->slug('Wôrķšƥáçè ~~sèťtïñğš~~', '/');
// $slug = 'Workspace/settings'

Слагер транслітерує початковий рядок у латиницю до того, як застосовувати будь-які інші перетворення. Локаль початкового рядку визначається автоматично, але ви можете чітко визначити її:

1
2
3
4
5
// повідомляє слагеру транслітерувати з корейської мови
$slugger = new AsciiSlugger('ko');

// ви можете перевизначити локаль в якості третього необовʼязкового параметра slug()
$slug = $slugger->slug('...', '-', 'fa');

У додатку Symfony, вам не потрібно створювати слагер самостійно. Завдяки автомонтуванню сервісів, ви можете впровадити слагер з підказкою в аргументі сервіс-конструктора за допомогою SluggerInterface. Локаль впровадженого слагера буде тією ж, що і локаль запиту:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use Symfony\Component\String\Slugger\SluggerInterface;

class MyService
{
    private $slugger;

    public function __construct(SluggerInterface $slugger)
    {
        $this->slugger = $slugger;
    }

    public function someMethod()
    {
        $slug = $this->slugger->slug('...');
    }
}

Слаг емоджі

6.2

Функція транслітерації емоджі була представлена в Symfony 6.2.

Ви можете перетворити будь-які емоджі на їх текстове представлення:

1
2
3
4
5
6
7
8
9
10
use Symfony\Component\String\Slugger\AsciiSlugger;

$slugger = new AsciiSlugger();
$slugger = $slugger->withEmoji();

$slug = $slugger->slug('a 😺, 🐈‍⬛, and a 🦁 go to 🏞️', '-', 'en');
// $slug = 'a-grinning-cat-black-cat-and-a-lion-go-to-national-park';

$slug = $slugger->slug('un 😺, 🐈‍⬛, et un 🦁 vont au 🏞️', '-', 'fr');
// $slug = 'un-chat-qui-sourit-chat-noir-et-un-tete-de-lion-vont-au-parc-national';

Якщо ви хочете використати конкретну локаль для емоджі, або використати скорочені коди з GitHub або Slack, використайте перший аргумент методу withEmoji():

1
2
3
4
5
6
7
use Symfony\Component\String\Slugger\AsciiSlugger;

$slugger = new AsciiSlugger();
$slugger = $slugger->withEmoji('github'); // or "en", or "fr", etc.

$slug = $slugger->slug('a 😺, 🐈‍⬛, and a 🦁');
// $slug = 'a-smiley-cat-black-cat-and-a-lion';

Інфлектор

В деяких випадках, на кшталт генерування та інтроспеції коду, вам потрібно перетворювати слова у/з множини/однини. Наприклад, щоб дізнатися властивість, асоційовану з методом adder, ви повинні виконати перетворення з множини (метод addStories()) в однину (властивість $story).

Більшість людських мов мають прості правила множин, але в той же час вони визначають багато виключень. Наприклад, загальне правило в англійській мові - додавати s в кінці слова (book -> books), але існує багато виключень навіть для розповсюджених слів (woman -> women, life -> lives, news -> news, radius -> radii, і т.д.)

Цей компонент надає клас EnglishInflector, щоб впевнено перетворювати англійські слова у/з однини/множини:

1
2
3
4
5
6
7
8
9
10
11
use Symfony\Component\String\Inflector\EnglishInflector;

$inflector = new EnglishInflector();

$result = $inflector->singularize('teeth');   // ['tooth']
$result = $inflector->singularize('radii');   // ['radius']
$result = $inflector->singularize('leaves');  // ['leaf', 'leave', 'leaff']

$result = $inflector->pluralize('bacterium'); // ['bacteria']
$result = $inflector->pluralize('news');      // ['news']
$result = $inflector->pluralize('person');    // ['persons', 'people']

Значення, повернене обома методами, завжди є масивом, так як іноді неможливо визначити унікальну форму однини/множини заданого слова.