Створення та маніпулювання рядками

Дата оновлення перекладу 2025-09-22

Створення та маніпулювання рядками

Symfony надає об'єктно-орієнтований API для роботи з рядками Unicode (як байтами, кодовими точками та кластерами графем). Цей API доступний через компонент String, який ви повинні спочатку встановити у вашому додатку:

1
$ composer require symfony/string

Note

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

Що таке String?

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

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

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

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

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

Кожна літера в слові «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[]

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

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

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() створює рядки Unicode
use function Symfony\Component\String\u;

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

// функція s() створює байтовий рядок або рядок Unicode,
// залежно від заданого змісту
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

// видаляє всі пробіли (' \n\r\t\x0C') на початку та в кінці рядка та заміняє
// два або більше знаків пробілу поспіль на один знак пробілу (' ')
u("  \n\n   hello \t   \n\r   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
24
25
26
27
28
29
30
31
32
33
34
35
36
// змінює всі графеми/кодові точки на нижній регістр
u('FOO Bar Brİan')->lower();  // 'foo bar bri̇an'
// змінює всі графеми/кодові точки на нижній регістр відповідно до мапувань регістру, специфічних для локалі
u('FOO Bar Brİan')->localeLower('en');  // 'foo bar bri̇an'
u('FOO Bar Brİan')->localeLower('lt');  // 'foo bar bri̇̇an'

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

// змінює всі графеми/кодові точки на верхній регістр
u('foo BAR bάz')->upper(); // 'FOO BAR BΆZ'
// змінює всі графеми/кодові точки на верхній регістр відповідно до мапувань регістру, специфічних для локалі
u('foo BAR bάz')->localeUpper('en'); // 'FOO BAR BΆZ'
u('foo BAR bάz')->localeUpper('el'); // 'FOO BAR BAZ'

// змінює всі графеми/кодові точки на "регістр заголовку"
u('foo ijssel')->title();     // 'Foo ijssel'
u('foo ijssel')->title(true); // 'Foo Ijssel'
// змінює всі графеми/кодові точки на "регістр заголовку" відповідно до мапувань регістру, специфічних для локалі
u('foo ijssel')->localeTitle('en'); // 'Foo ijssel'
u('foo ijssel')->localeTitle('nl'); // 'Foo IJssel'

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

7.1

Методи localeLower(), localeUpper() та localeTitle() були представлені в Symfony 7.1.

7.2

Метод kebab() був представлений в Symfony 7.2.

7.3

Метод pascal() був представлений в Symfony 7.3.

Методи всіх класів рядків за замовчуванням є чутливими до регістру. Ви можете виконувати нечутливі до регістру операції з допомогою методу 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'
// when passing an array of prefix/suffix, only the first one found is trimmed
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
43
44
45
46
47
// перевіряє, чи рядок починається/закінчується заданим рядком
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', null]

// Ви можете передати прапорці для preg_match() як другий аргумент. Якщо передано PREG_PATTERN_ORDER
// або PREG_SET_ORDER, буде використано preg_match_all().
u('206-555-0100 and 800-555-1212')->match('/\d{3}-\d{3}-\d{4}/', \PREG_PATTERN_ORDER);
// result = [['206-555-0100', '800-555-1212']]

// перевіряє, чи містить рядок будь-який з інших заданих рядків
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 (string $match): string {
    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
25
26
27
28
29
// використовує рядок як «клей» для об'єднання усіх заданих рядків
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 dolor sit amet')->truncate(8, cut: TruncateMode::Char);       // 'Lorem ip'
// повертає до останнього повного слова, яке відповідає заданій довжині, не перевершуючи його
u('Lorem ipsum dolor sit amet')->truncate(8, cut: TruncateMode::WordBefore); // 'Lorem'
// повертає до останнього повного слова, яке відповідає заданий довжині, перевершуючи його за необхідності
u('Lorem ipsum dolor sit amet')->truncate(8, cut: TruncateMode::WordAfter);   // 'Lorem ipsum'

7.2

Параметр TruncateMode для функції обрізання був представлений в Symfony 7.2.

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 = "латинська мала літера A з кільцем зверху") або послідовністю з двох кодових точок (U+0061 =
"латинська мала літера A з кільцем зверху"). Метод 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);

Ліниво завантажувані рядки

Іноді створення рядка методами, описаними у попередніх розділах, не є оптимальним. Наприклад, розглянемо значення хешу, яке вимагає певних обчислень для отримання, і яке, можливо, не буде використано.

У таких випадках краще використовувати клас LazyString, який дозволяє зберігати рядок, значення якого генерується лише тоді, коли це потрібно:

1
2
3
4
5
6
7
8
9
use Symfony\Component\String\LazyString;

$lazyString = LazyString::fromCallable(function (): string {
    // Обчислити значення рядка...
    $value = ...;

    // Потім повернути фінальне значення
    return $value;
});

Зворотний виклик буде виконано лише тоді, коли значення лінивого рядка буде запитано під час виконання програми. Ви також можете створювати ліниві рядки з об'єкта Stringable:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Hash implements \Stringable
{
    public function __toString(): string
    {
        return $this->computeHash();
    }

    private function computeHash(): string
    {
        // Обчислити значення хешу з потенційно важкою обробкою
        $hash = ...;

        return $hash;
    }
}

// Потім створити лінивий рядок з цього хешу, який запустить
// обчислення хешу лише, якщо це буде потрібно
$lazyHash = LazyString::fromStringable(new Hash());

Робота з емодзі

Цей зміст було переміщено до документації компонента Emoji.

Слаггер

У деяких контекстах, таких як 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 $string, string $locale): string {
    return str_replace('❤️', 'love', $string);
});

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

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

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

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

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

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

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

class MyService
{
    public function __construct(
        private SluggerInterface $slugger,
    ) {
    }

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

Емодзі слагу

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

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, Gitlab або 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']

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

Symfony також надає інфлектори для інших мов:

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

$inflector = new FrenchInflector();
$result = $inflector->singularize('souris'); // ['souris']
$result = $inflector->pluralize('hôpital');  // ['hôpitaux']

use Symfony\Component\String\Inflector\SpanishInflector;

$inflector = new SpanishInflector();
$result = $inflector->singularize('aviones'); // ['avión']
$result = $inflector->pluralize('miércoles'); // ['miércoles']

7.2

Клас SpanishInflector було представлено в Symfony 7.2.

Note

Symfony також надає InflectorInterface, якщо вам потрібно реалізувати власний інфлектор.