Travailler avec les chaînes de caractères
Nette\Utils\Strings est une classe statique avec des fonctions utiles pour travailler avec les chaînes de caractères, principalement en encodage UTF-8.
Installation :
composer require nette/utils
Tous les exemples supposent qu'un alias a été créé :
use Nette\Utils\Strings;
Changement de casse
Ces fonctions nécessitent l'extension PHP mbstring
.
lower (string $s): string
Convertit une chaîne UTF-8 en minuscules.
Strings::lower('Dobrý den'); // 'dobrý den'
upper (string $s): string
Convertit une chaîne UTF-8 en majuscules.
Strings::upper('Dobrý den'); // 'DOBRÝ DEN'
firstUpper (string $s): string
Convertit la première lettre d'une chaîne UTF-8 en majuscule, ne change pas les autres.
Strings::firstUpper('dobrý den'); // 'Dobrý den'
firstLower (string $s): string
Convertit la première lettre d'une chaîne UTF-8 en minuscule, ne change pas les autres.
Strings::firstLower('Dobrý den'); // 'dobrý den'
capitalize (string $s): string
Convertit la première lettre de chaque mot dans une chaîne UTF-8 en majuscule, les autres en minuscules.
Strings::capitalize('Dobrý den'); // 'Dobrý Den'
Modification de chaîne
normalize (string $s): string
Supprime les caractères de contrôle, normalise les fins de ligne en \n
, supprime les lignes vides de début et
de fin, supprime les espaces de fin sur les lignes, normalise l'UTF-8 en forme normale NFC.
unixNewLines (string $s): string
Convertit les fins de ligne en \n
utilisé dans les systèmes Unix. Les fins de ligne sont : \n
,
\r
, \r\n
, U+2028 séparateur de ligne, U+2029 séparateur de paragraphe.
$unixLikeLines = Strings::unixNewLines($string);
platformNewLines (string $s): string
Convertit les fins de ligne en caractères spécifiques à la plateforme actuelle, c'est-à-dire \r\n
sous Windows
et \n
ailleurs. Les fins de ligne sont : \n
, \r
, \r\n
, U+2028 séparateur de
ligne, U+2029 séparateur de paragraphe.
$platformLines = Strings::platformNewLines($string);
webalize (string $s, ?string $charlist=null, bool $lower=true): string
Modifie une chaîne UTF-8 à la forme utilisée dans les URL, c'est-à-dire supprime les diacritiques et remplace tous les caractères, sauf les lettres de l'alphabet anglais et les chiffres, par un trait d'union.
Strings::webalize('náš produkt'); // 'nas-produkt'
Si d'autres caractères doivent être conservés, ils peuvent être indiqués dans le deuxième paramètre de la fonction.
Strings::webalize('10. obrázek_id', '._'); // '10.-obrazek_id'
Avec le troisième paramètre, on peut supprimer la conversion en minuscules.
Strings::webalize('Dobrý den', null, false); // 'Dobry-den'
Nécessite l'extension PHP intl
.
trim (string $s, ?string $charlist=null): string
Supprime les espaces (ou autres caractères spécifiés par le deuxième paramètre) du début et de la fin d'une chaîne UTF-8.
Strings::trim(' Hello '); // 'Hello'
truncate (string $s, int $maxLen,
string $append=`'…'
`): string
Tronque une chaîne UTF-8 à la longueur maximale spécifiée, en essayant de préserver les mots entiers. Si la chaîne est raccourcie, ajoute des points de suspension à la fin (peut être changé avec le troisième paramètre).
$text = 'Řekněte, jak se máte?';
Strings::truncate($text, 5); // 'Řekn…'
Strings::truncate($text, 20); // 'Řekněte, jak se…'
Strings::truncate($text, 30); // 'Řekněte, jak se máte?'
Strings::truncate($text, 20, '~'); // 'Řekněte, jak se~'
indent (string $s, int $level=1, string
$indentationChar=`"\t"
`): string
Indente un texte multiligne depuis la gauche. Le nombre d'indentations est déterminé par le deuxième paramètre, avec quoi indenter par le troisième paramètre (la valeur par défaut est une tabulation).
Strings::indent('Nette'); // "\tNette"
Strings::indent('Nette', 2, '+'); // '++Nette'
padLeft (string $s, int $length, string
$pad=`' '
`): string
Remplit une chaîne UTF-8 à la longueur spécifiée en répétant la chaîne $pad
depuis la gauche.
Strings::padLeft('Nette', 6); // ' Nette'
Strings::padLeft('Nette', 8, '+*'); // '+*+Nette'
padRight (string $s, int $length,
string $pad=`' '
`): string
Remplit une chaîne UTF-8 à la longueur spécifiée en répétant la chaîne $pad
depuis la droite.
Strings::padRight('Nette', 6); // 'Nette '
Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
substring (string $s, int $start, ?int $length=null): string
Retourne une partie de la chaîne UTF-8 $s
spécifiée par la position de départ $start
et la
longueur $length
. Si $start
est négatif, la chaîne retournée commencera par le caractère
-$start
depuis la fin.
Strings::substring('Nette Framework', 0, 5); // 'Nette'
Strings::substring('Nette Framework', 6); // 'Framework'
Strings::substring('Nette Framework', -4); // 'work'
reverse (string $s): string
Inverse une chaîne UTF-8.
Strings::reverse('Nette'); // 'etteN'
length (string $s): int
Retourne le nombre de caractères (pas d'octets) dans la chaîne UTF-8.
C'est le nombre de points de code Unicode, qui peuvent différer du nombre de graphèmes.
Strings::length('Nette'); // 5
Strings::length('červená'); // 7
startsWith (string $haystack, string $needle): bool
Détermine si la chaîne $haystack
commence par la chaîne $needle
.
$haystack = 'Začíná';
$needle = 'Za';
Strings::startsWith($haystack, $needle); // true
Utilisez la fonction native str_starts_with()
.
endsWith (string $haystack, string $needle): bool
Détermine si la chaîne $haystack
se termine par la chaîne $needle
.
$haystack = 'Končí';
$needle = 'čí';
Strings::endsWith($haystack, $needle); // true
Utilisez la fonction native str_ends_with()
.
contains (string $haystack, string $needle): bool
Détermine si la chaîne $haystack
contient $needle
.
$haystack = 'Posluchárna';
$needle = 'sluch';
Strings::contains($haystack, $needle); // true
Utilisez la fonction native str_contains()
.
compare (string $left, string $right, ?int $length=null): bool
Comparaison de deux chaînes UTF-8 ou de leurs parties sans tenir compte de la casse. Si $length
contient null,
les chaînes entières sont comparées, s'il est négatif, le nombre correspondant de caractères est comparé depuis la fin des
chaînes, sinon le nombre correspondant de caractères est comparé depuis le début.
Strings::compare('Nette', 'nette'); // true
Strings::compare('Nette', 'next', 2); // true - correspondance des 2 premiers caractères
Strings::compare('Nette', 'Latte', -2); // true - correspondance des 2 derniers caractères
findPrefix (…$strings): string
Trouve le début commun des chaînes. Ou retourne une chaîne vide si le préfixe commun n'a pas été trouvé.
Strings::findPrefix('prefix-a', 'prefix-bb', 'prefix-c'); // 'prefix-'
Strings::findPrefix(['prefix-a', 'prefix-bb', 'prefix-c']); // 'prefix-'
Strings::findPrefix('Nette', 'is', 'great'); // ''
before (string $haystack, string $needle, int $nth=1): ?string
Retourne la partie de la chaîne $haystack
avant la n-ième occurrence $nth
de la chaîne
$needle
. Ou null
si $needle
n'a pas été trouvé. Avec une valeur négative
$nth
, la recherche se fait depuis la fin de la chaîne.
Strings::before('Nette_is_great', '_', 1); // 'Nette'
Strings::before('Nette_is_great', '_', -2); // 'Nette'
Strings::before('Nette_is_great', ' '); // null
Strings::before('Nette_is_great', '_', 3); // null
after (string $haystack, string $needle, int $nth=1): ?string
Retourne la partie de la chaîne $haystack
après la n-ième occurrence $nth
de la chaîne
$needle
. Ou null
si $needle
n'a pas été trouvé. Avec une valeur négative
$nth
, la recherche se fait depuis la fin de la chaîne.
Strings::after('Nette_is_great', '_', 2); // 'great'
Strings::after('Nette_is_great', '_', -1); // 'great'
Strings::after('Nette_is_great', ' '); // null
Strings::after('Nette_is_great', '_', 3); // null
indexOf (string $haystack, string $needle, int $nth=1): ?int
Retourne la position en caractères de la n-ième occurrence $nth
de la chaîne $needle
dans la
chaîne $haystack
. Ou null
s'il n'a pas été trouvé $needle
. Avec une valeur négative
$nth
, la recherche se fait depuis la fin de la chaîne.
Strings::indexOf('abc abc abc', 'abc', 2); // 4
Strings::indexOf('abc abc abc', 'abc', -1); // 8
Strings::indexOf('abc abc abc', 'd'); // null
Encodage
fixEncoding (string $s): string
Supprime de la chaîne les caractères UTF-8 invalides.
$correctStrings = Strings::fixEncoding($string);
checkEncoding (string $s): bool
Détermine s'il s'agit d'une chaîne UTF-8 valide.
$isUtf8 = Strings::checkEncoding($string);
Utilisez Nette\Utils\Validator::isUnicode().
toAscii (string $s): string
Convertit une chaîne UTF-8 en ASCII, c'est-à-dire supprime les diacritiques, etc.
Strings::toAscii('žluťoučký kůň'); // 'zlutoucky kun'
Nécessite l'extension PHP intl
.
chr (int $code): string
Retourne un caractère spécifique en UTF-8 à partir du point de code (nombre dans la plage 0×0000..D7FF et 0xE000..10FFFF).
Strings::chr(0xA9); // '©' en encodage UTF-8
ord (string $char): int
Retourne le point de code d'un caractère spécifique en UTF-8 (nombre dans la plage 0×0000..D7FF ou 0xE000..10FFFF).
Strings::ord('©'); // 0xA9
Expressions régulières
La classe Strings offre des fonctions pour travailler avec les expressions régulières. Contrairement aux fonctions natives de
PHP, elles disposent d'une API plus compréhensible, d'un meilleur support Unicode et surtout d'une détection d'erreurs. Toute
erreur lors de la compilation ou du traitement de l'expression lance une exception Nette\RegexpException
.
split (string $subject, string $pattern, bool $captureOffset=false, bool $skipEmpty=false, int $limit=-1, bool $utf8=false): array
Divise une chaîne en tableau selon une expression régulière. Les expressions entre parenthèses seront capturées et retournées également.
Strings::split('hello, world', '~,\s*~');
// ['hello', 'world']
Strings::split('hello, world', '~(,)\s*~');
// ['hello', ',', 'world']``
Si $skipEmpty
est true
, seuls les éléments non vides seront retournés :
Strings::split('hello, world, ', '~,\s*~');
// ['hello', 'world', '']
Strings::split('hello, world, ', '~,\s*~', skipEmpty: true);
// ['hello', 'world']
Si $limit
est spécifié, seules les sous-chaînes jusqu'à la limite seront retournées et le reste de la chaîne
sera placé dans le dernier élément. Une limite de –1 ou 0 signifie aucune restriction.
Strings::split('hello, world, third', '~,\s*~', limit: 2);
// ['hello', 'world, third']
Si $utf8
est true
, l'évaluation passe en mode Unicode. Similaire à quand vous spécifiez le
modificateur u
.
Si $captureOffset
est true
, pour chaque correspondance trouvée, sa position dans la chaîne sera
également retournée (en octets ; si $utf8
est défini, alors en caractères). Cela change la valeur de retour en
tableau, où chaque élément est une paire composée de la chaîne correspondante et de sa position.
Strings::split('žlutý, kůň', '~,\s*~', captureOffset: true);
// [['žlutý', 0], ['kůň', 9]]
Strings::split('žlutý, kůň', '~,\s*~', captureOffset: true, utf8: true);
// [['žlutý', 0], ['kůň', 7]]
match (string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $utf8=false): ?array
Recherche dans la chaîne une partie correspondant à l'expression régulière et retourne un tableau avec l'expression
trouvée et les sous-expressions individuelles, ou null
.
Strings::match('hello!', '~\w+(!+)~');
// ['hello!', '!']
Strings::match('hello!', '~X~');
// null
Si $unmatchedAsNull
est true
, les sous-modèles non capturés sont retournés comme null ; sinon, ils
sont retournés comme une chaîne vide ou non retournés :
Strings::match('hello', '~\w+(!+)?~');
// ['hello']
Strings::match('hello', '~\w+(!+)?~', unmatchedAsNull: true);
// ['hello', null]
Si $utf8
est true
, l'évaluation passe en mode Unicode. Similaire à quand vous spécifiez le
modificateur u
:
Strings::match('žlutý kůň', '~\w+~');
// ['lut']
Strings::match('žlutý kůň', '~\w+~', utf8: true);
// ['žlutý']
Le paramètre $offset
peut être utilisé pour spécifier la position à partir de laquelle commencer la recherche
(en octets ; si $utf8
est défini, alors en caractères).
Si $captureOffset
est true
, pour chaque correspondance trouvée, sa position dans la chaîne sera
également retournée (en octets ; si $utf8
est défini, alors en caractères). Cela change la valeur de retour en
tableau, où chaque élément est une paire composée de la chaîne correspondante et de son offset :
Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true);
// [['lut', 2]]
Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
// [['žlutý!', 0], ['!', 5]]
matchAll (string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator
Recherche dans la chaîne toutes les occurrences correspondant à l'expression régulière et retourne un tableau de tableaux avec l'expression trouvée et les sous-expressions individuelles.
Strings::matchAll('hello, world!!', '~\w+(!+)?~');
/* [
0 => ['hello'],
1 => ['world!!', '!!'],
] */
Si $patternOrder
est true
, la structure des résultats change de sorte que dans le premier élément
se trouve un tableau des correspondances complètes du modèle, dans le deuxième se trouve un tableau des chaînes auxquelles
correspond le premier sous-modèle entre parenthèses, et ainsi de suite :
Strings::matchAll('hello, world!!', '~\w+(!+)?~', patternOrder: true);
/* [
0 => ['hello', 'world!!'],
1 => ['', '!!'],
] */
Si $unmatchedAsNull
est true
, les sous-modèles non capturés sont retournés comme null ; sinon, ils
sont retournés comme une chaîne vide ou non retournés :
Strings::matchAll('hello, world!!', '~\w+(!+)?~', unmatchedAsNull: true);
/* [
0 => ['hello', null],
1 => ['world!!', '!!'],
] */
Si $utf8
est true
, l'évaluation passe en mode Unicode. Similaire à quand vous spécifiez le
modificateur u
:
Strings::matchAll('žlutý kůň', '~\w+~');
/* [
0 => ['lut'],
1 => ['k'],
] */
Strings::matchAll('žlutý kůň', '~\w+~', utf8: true);
/* [
0 => ['žlutý'],
1 => ['kůň'],
] */
Le paramètre $offset
peut être utilisé pour spécifier la position à partir de laquelle commencer la recherche
(en octets ; si $utf8
est défini, alors en caractères).
Si $captureOffset
est true
, pour chaque correspondance trouvée, sa position dans la chaîne sera
également retournée (en octets ; si $utf8
est défini, alors en caractères). Cela change la valeur de retour en
tableau, où chaque élément est une paire composée de la chaîne correspondante et de sa position :
Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true);
/* [
0 => [['lut', 2]],
1 => [['k', 8]],
] */
Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
/* [
0 => [['žlutý', 0]],
1 => [['kůň', 6]],
] */
Si $lazy
est true
, la fonction retourne un Generator
au lieu d'un tableau, ce qui
apporte des avantages significatifs en termes de performance lors du travail avec de grandes chaînes. Le générateur permet de
rechercher les correspondances progressivement, au lieu de toute la chaîne en une fois. Cela permet de travailler efficacement
même avec des textes d'entrée extrêmement grands. De plus, vous pouvez interrompre le traitement à tout moment si vous trouvez
la correspondance recherchée, ce qui économise du temps de calcul.
$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
foreach ($matches as $match) {
echo "Trouvé: $match[0]\n";
// Le traitement peut être interrompu à tout moment
}
replace (string $subject, string|array
$pattern, string|callable $replacement=''
, int $limit=-1, bool $captureOffset=false, bool
$unmatchedAsNull=false, bool $utf8=false): string
Remplace toutes les occurrences correspondant à l'expression régulière. $replacement
est soit un masque de
chaîne de remplacement, soit un callback.
Strings::replace('hello, world!', '~\w+~', '--');
// '--, --!'
Strings::replace('hello, world!', '~\w+~', fn($m) => strrev($m[0]));
// 'olleh, dlrow!'
La fonction permet également d'effectuer plusieurs remplacements en passant dans le deuxième paramètre un tableau sous la
forme pattern => replacement
:
Strings::replace('hello, world!', [
'~\w+~' => '--',
'~,\s+~' => ' ',
]);
// '-- --!'
Le paramètre $limit
limite le nombre de remplacements effectués. Une limite de –1 signifie aucune
restriction.
Si $utf8
est true
, l'évaluation passe en mode Unicode. Similaire à quand vous spécifiez le
modificateur u
.
Strings::replace('žlutý kůň', '~\w+~', '--');
// 'ž--ý --ůň'
Strings::replace('žlutý kůň', '~\w+~', '--', utf8: true);
// '-- --'
Si $captureOffset
est true
, pour chaque correspondance trouvée, sa position dans la chaîne sera
également passée au callback (en octets ; si $utf8
est défini, alors en caractères). Cela change la forme du
tableau passé, où chaque élément est une paire composée de la chaîne correspondante et de sa position.
Strings::replace(
'žlutý kůň',
'~\w+~',
function (array $m) { dump($m); return ''; },
captureOffset: true,
);
// dumps [['lut', 2]] et [['k', 8]]
Strings::replace(
'žlutý kůň',
'~\w+~',
function (array $m) { dump($m); return ''; },
captureOffset: true,
utf8: true,
);
// dumps [['žlutý', 0]] et [['kůň', 6]]
Si $unmatchedAsNull
est true
, les sous-modèles non capturés sont passés au callback comme null ;
sinon, ils sont passés comme une chaîne vide ou non passés :
Strings::replace(
'ac',
'~(a)(b)*(c)~',
function (array $m) { dump($m); return ''; },
);
// dumps ['ac', 'a', '', 'c']
Strings::replace(
'ac',
'~(a)(b)*(c)~',
function (array $m) { dump($m); return ''; },
unmatchedAsNull: true,
);
// dumps ['ac', 'a', null, 'c']