fi1a / format
PHP форматирование строковых шаблонов
Installs: 2 888
Dependents: 7
Suggesters: 0
Security: 0
Stars: 1
Watchers: 1
Forks: 0
Open Issues: 0
Requires
- php: ^7.3 || ^8
- ext-mbstring: *
- fi1a/collection: ^2.0
- fi1a/tokenizer: ^1.1
Requires (Dev)
- captainhook/captainhook: ^5.4
- phpunit/phpunit: ^9.3
- slevomat/coding-standard: ^6.3
- squizlabs/php_codesniffer: ^3.5
- vimeo/psalm: ^4.3
README
Пакет предоставляет возможность форматирования строковых шаблонов с использованием функций спецификаторов.
Возможности пакета:
- форматирование строки и числа;
- форматирование даты и времени на русском языке (месяцы и дни недели);
- преобразование специальных символов в HTML-сущности;
- преобразование HTML-сущностей обратно в соответствующие символы;
- форматирование размера памяти;
- форматирование времени;
- склонение слов после числительных;
- форматирование номера телефона;
- форматирование цены;
- условные конструкции (if, elseif, else, endif);
- собственные функции спецификаторы;
- возможность задать сокращения для функций спецификаторов;
- применение функций спецификаторов цепочкой к одному значению.
Установка
Установить этот пакет можно как зависимость, используя Composer.
composer require fi1a/format
Использование
use Fi1a\Format\Formatter; Formatter::format('[{{user:login}}] - {{user:name}}', ['user' => ['name' => 'John', 'login' => 'john85']]); // [john85] - John Formatter::format('{{0}}, {{1}}',[1, 2]); // 1, 2 Formatter::format('{{}}, {{}}',[1, 2]); // 1, 2 Formatter::format('{{foo}}, {{foo}}, {{foo}}', ['foo' => 'bar',]); // bar, bar, bar
При отсутствии ключа в массиве значений выбрасывается исключение \Fi1a\Format\AST\Exception\NotFoundKey
use Fi1a\Format\Formatter; use Fi1a\Format\AST\Exception\NotFoundKey; try { Formatter::format('{{not_exists}}', []); } catch (NotFoundKey $exception) { }
Все значения преобразовываются в специальные символы HTML-сущности, с помощью функции htmlspecialchars
.
Для того чтобы преобразовать обратно, воспользуйтесь функцией спецификатором unescape
или передайте четвертым аргументом
значение false
отменяющее автоматическое преобразование специальных символов в HTML-сущности.
use Fi1a\Format\Formatter; Formatter::format('{{value}}', ['value' => '&']); // "&" Formatter::format('{{value|unescape}}', ['value' => '&']); // "&" // или Formatter::format('{{value}}', ['value' => '&'], [], false); // "&"
C доступом по пути
Строковый шаблон содержит путь до значения в ассоциативном массиве.
use Fi1a\Format\Formatter; Formatter::format('[{{user:login}}] - {{user:name}}', ['user' => ['name' => 'John', 'login' => 'john85']]); // [john85] - John
C доступом по индексам
Строковый шаблон содержит индексы значений в массиве.
use Fi1a\Format\Formatter; Formatter::format('{{0}}, {{1}}',[1, 2]); // 1, 2 Formatter::format('{{}}, {{}}',[3, 4]); // 3, 4
Экранирование спец. символов
Для экранирования спец. символов используется символ "\".
use Fi1a\Format\Formatter; Formatter::format('\\{{0\\}}', [0 => 'foo']); // {{0}} Formatter::format('{{0}}', [0 => 'foo']); // foo
Для экранирования всех спец. символов в строке,
можно воспользоваться функцией escape
класса Fi1a\Format\Safe
:
use Fi1a\Format\Formatter; use Fi1a\Format\Safe; Formatter::format(Safe::escape(('{{0}}'), [0 => 'foo']); // {{0}}
Для того чтобы убрать экранирование спец. символов в строке,
можно воспользоваться функцией unescape
класса Fi1a\Format\Safe
:
use Fi1a\Format\Formatter; use Fi1a\Format\Safe; Formatter::format(Safe::unescape(('\\{{0}}'), [0 => 'foo']); // foo
Использование функций спецификаторов
Доступные функции спецификаторов:
- date - форматирование даты и времени;
- sprintf - форматирование строки и чисел;
- escape - преобразует специальные символы в HTML-сущности;
- unescape - преобразует специальные HTML-сущности обратно в соответствующие символы;
- memory - форматирование размера памяти (x.x Б, x.x КБ, x.x МБ, x.x ГБ, x.x ТБ, x.x ПБ);
- time - форматирование времени (< 1 сек., x сек., x мин., x ч., x д.);
- declension - склонение слов после числительных;
- phone - форматирование номера телефона (+7(ddd)ddd-dddd);
- price - форматирование цены.
Указание функции спецификатора следует после указания ключа с разделителем "|".
use Fi1a\Format\Formatter; Formatter::format('{{0|sprintf("04d")}}-{{1|sprintf("02d")}}-{{2|sprintf("02d")}}',[2016, 2, 27,]); // 2016-02-27
Модификаторы функций спецификаторов можно динамически задавать через массив передаваемый третьим аргументом функции format
.
use Fi1a\Format\Formatter; Formatter::format('{{value|sprintf(modifier)}}', ['value' => 100.5], ['modifier' => '01.2f']); // 100.50
Возможно указание функций спецификатора цепочкой с разделителем "|". Тогда значение будет передаваться последовательно, по цепочке, от одной функции спецификатора к другой.
use Fi1a\Format\Formatter; Formatter::format('{{value|unescape|sprintf|escape}}', ['value' => 'a&b']); // "a&b"
PHP форматирование строки и числа с помощью sprintf
Спецификаторы функции sprintf. Указание функции спецификатора следует после указания ключа с разделителем "|".
Форматирование строк и чисел. Спецификаторы используемые в функци sprintf.
- b - Аргумент рассматривается как целое число и печатается в бинарном представлении.
- c - Аргумент рассматривается как целое число и печатается как символ из таблицы ASCII с соответствующим кодом.
- d - Аргумент рассматривается как целое число и печатается как целое число со знаком.
- e - Аргумент считается за число в научной нотации (т.е. 1.2e+2). Спецификатор точности задает количество цифр после десятичной запятой. В более ранних версиях он задавал общее количество значащих цифр (т.е. после запятой выводилось на 1 символ меньше).
- E - Аналогично спецификатору e, но использует заглавные символы (т.е. 1.2E+2).
- f - Аргумент считается за число с плавающей точкой (с учетом локали).
- F - Аргумент считается за число с плавающей точкой (без учета локали). Доступно с PHP 5.0.3.
- o - Аргумент рассматривается как целое число и печатается в восьмеричном представлении.
- s - Аргумент рассматривается и печатается как строка.
- u - Аргумент рассматривается как целое число и печатается как беззнаковое целое число.
- x - Аргумент рассматривается как целое число и печатается в шестнадцатеричном представлении (буквы будут в нижнем регистре).
- X - Аргумент рассматривается как целое число и печатается в шестнадцатеричном представлении (буквы будут в верхнем регистре).
Использование символа заполнения
use Fi1a\Format\Formatter; Formatter::format('{{0|sprintf("\'.9d")}}', [123]); // ......123 Formatter::format('{{0|sprintf("\'.09d")}}', [123]); // 000000123
Целое с лидирующими нулями
use Fi1a\Format\Formatter; Formatter::format('{{0|sprintf("04d")}}-{{1|sprintf("02d")}}-{{2|sprintf("02d")}}', [2020, 6, 7]); // 2020-06-07
PHP форматирование даты и времени
Спецификаторы функции date, форматирование даты и времени. Указание функции спецификатора следует после указания ключа с разделителем "|".
Формат модификатора используемого в функции:
День
- d - День месяца, 2 цифры с ведущим нулём (от 01 до 31).
- D - Текстовое представление дня недели на русском языке (от Пн до Вс).
- j - День месяца без ведущего нуля (от 1 до 31).
- l - Полное наименование дня недели на русском языке (от Понедельник до Воскресенье).
- N - Порядковый номер дня недели в соответствии со стандартом ISO 8601 (от 1 (понедельник) до 7 (воскресенье)).
- S - Английский суффикс порядкового числительного дня месяца, 2 символа (st, nd, rd или th. Применяется совместно с j).
- w - Порядковый номер дня недели (от 0 (воскресенье) до 6 (суббота)).
- z - Порядковый номер дня в году (От 0 до 365).
Неделя
- W - Порядковый номер недели года в соответствии со стандартом ISO 8601; недели начинаются с понедельника, начиная с 0. Например: 42 (42-я неделя года).
Месяц
- F - Полное наименование месяца на русском языке, например, "Января" или "Марта" (от "Января" до "Декабря").
- f - Полное наименование месяца на русском языке, например, "Январь" или "Март" (от "Январь" до "Декабрь").
- m - Порядковый номер месяца с ведущим нулём (от 01 до 12).
- M - Сокращённое наименование месяца на русском языке, 3 символа (от "Янв" до "Дек").
- n - Порядковый номер месяца без ведущего нуля (от 1 до 12).
- t - Количество дней в указанном месяце (от 28 до 31).
Год
- L - Признак високосного года (1, если год високосный, иначе 0.).
- o - Номер года в соответствии со стандартом ISO 8601. Имеет то же значение, что и Y, кроме случая, когда номер недели ISO (W) принадлежит предыдущему или следующему году; тогда будет использован год этой недели. (Примеры: 1999 или 2003).
- X - Расширенное полное числовое представление года, не менее 4 цифр, с - для годов до нашей эры и + для годов нашей эры. (Примеры: -0055, +0787, +1999, +10191).
- x - Расширенное полное числовое представление, если требуется или стандартное полное числовое представление, если возможно (например, Y). Не менее четырёх цифр. Для годов до нашей эры указан префикс -. У годов после (и включая) 10000 префикс +. (Примеры: -0055, 0787, 1999, +10191).
- Y - Полное числовое представление года, не менее 4 цифр, с - для годов до нашей эры. (Примеры: -0055, 0787, 1999, 2003, 10191.).
- y - Номер года, 2 цифры (Примеры: 99, 03).
Время
- a - Ante meridiem (лат. "до полудня") или Post meridiem (лат. "после полудня") в нижнем регистре (am или pm).
- A - Ante meridiem или Post meridiem в верхнем регистре (AM или PM).
- B - Время в формате Интернет-времени (альтернативной системы отсчёта времени суток) (от 000 до 999).
- g - Часы в 12-часовом формате без ведущего нуля (от 1 до 12).
- G - Часы в 24-часовом формате без ведущего нуля (от 0 до 23).
- h - Часы в 12-часовом формате с ведущим нулём (от 01 до 12).
- H - Часы в 24-часовом формате с ведущим нулём (от 00 до 23).
- i - Минуты с ведущим нулём (от 00 до 59).
- s - Секунды с ведущим нулём (от 00 до 59).
- u - Микросекунды. (Например: 654321).
- v - Микросекунды. (Пример: 654).
- v - Микросекунды. (Пример: 654).
Часовой пояс
- e - Идентификатор часового пояса (Примеры: UTC, GMT, Atlantic/Azores).
- I - Признак летнего времени (1, если дата соответствует летнему времени, 0 в противном случае.).
- O - Разница с временем по Гринвичу без двоеточия между часами и минутами (Например: +0200).
- P - Разница с временем по Гринвичу с двоеточием между часами и минутами (Например: +02:00).
- p - То же, что и P, но возвращает Z вместо +00:00 (доступен, начиная с PHP 8.0.0) (Например: +02:00).
- T - Аббревиатура часового пояса, если известна; в противном случае смещение по Гринвичу. (Примеры: EST, MDT, +05).
- Z - Смещение часового пояса в секундах. Для часовых поясов, расположенных западнее UTC, возвращаются отрицательные числа, а для расположенных восточнее UTC - положительные. (от -43200 до 50400).
Полная дата/время
- c - Дата в формате стандарта ISO 8601 (2004-02-12T15:19:21+00:00).
- r - Дата в формате » RFC 222/» RFC 5322 (Например: Thu, 21 Dec 2000 16:01:07 +0200).
- U - Количество секунд, прошедших с начала Эпохи Unix (1 января 1970 00:00:00 GMT) (Смотрите также time()).
Ключи форматирования даты на русском языке
- F - Полное наименование месяца на русском языке, например, "Января" или "Марта" (от "Января" до "Декабря").
- f - Полное наименование месяца на русском языке, например, "Январь" или "Март" (от "Январь" до "Декабрь").
- M - Сокращённое наименование месяца на русском языке, 3 символа (от "Янв" до "Дек").
- D - Текстовое представление дня недели на русском языке (от "Пн" до "Вс").
- l - Полное наименование дня недели на русском языке (от "Понедельник" до "Воскресенье").
use Fi1a\Format\Formatter; Formatter::format('{{foo|date("d.m.Y")}}', ['foo' => time()]); // 28.09.2022 echo Formatter::format('{{|date("d F Y")}}', [time()]); // 18 Октября 2022 echo Formatter::format('{{|date("f")}}', [time()]); // Октябрь
Установить используемый формат по умолчанию:
use Fi1a\Format\Specifier\Date; use Fi1a\Format\Formatter; Formatter::format('{{foo|date}}', ['foo' => time()]); // 28.09.2022 07:06:00 Date::setDefaultFormat('d.m.Y'); Formatter::format('{{foo|date}}', ['foo' => time()]); // 28.09.2022
Функция спецификатор escape
Преобразует специальные символы в HTML-сущности {{|escape(flags, encoding, doubleEncode)}}
use Fi1a\Format\Formatter; Formatter::format('{{|escape}}', ['"test"']); // "test"
Функция спецификатор unescape
Преобразует специальные HTML-сущности обратно в соответствующие символы {{|escape(flags)}}
use Fi1a\Format\Formatter; Formatter::format('{{|unescape}}', ['&quot;test&quot;']); // "test"
PHP форматирование размера памяти
Функция спецификатор memory. Форматирование размера памяти.
use Fi1a\Format\Formatter; Formatter::format('{{|memory}}', [1024]); // 1.0 КБ Formatter::format('{{|memory("B")}}', [1024]); // 1024.0 Б Formatter::format('{{|memory}}', [1024 * 1024]); // 1.0 МБ
PHP форматирование времени
Функция спецификатор time, форматирование времени.
Доступные аргументы функции спецификатора:
- seconds - результат форматирования в секундах;
- minutes - результат форматирования в минутах;
- hours - результат форматирования в часах;
- days - результат форматирования в днях.
Если аргумент спецификатора не указан, форматирование осуществляется в наиболее подходящей размерности.
use Fi1a\Format\Formatter; Formatter::format('{{|time}}', [60 * 60]); // 1 ч. Formatter::format('{{|time("minutes")}}', [60 * 60]); // 60 мин. Formatter::format('{{|time}}', [2 * 24 * 60 * 60]); // 2 д.
PHP склонение слов после числительных
С помощью функции спецификатора declension
можно склонять существительные после чисел.
Например: 1 год, 2 года, 5 лет.
use Fi1a\Format\Formatter; Formatter::format('{{year}} {{year|declension("год", "года", "лет")}}', ['year' => 1]); // 1 год Formatter::format('{{year}} {{year|declension("год", "года", "лет")}}', ['year' => 2]); // 2 года Formatter::format('{{year}} {{year|declension("год", "года", "лет")}}', ['year' => 5]); // 5 лет
Модификаторы функции спецификатора склонения существительного после числа:
- первый модификатор задает текст для единичных значений;
- второй для значений с 2-х до 4-х;
- третий для всех остальных.
Форматирование телефонных номеров
С помощью функции спецификатора phone
можно форматировать номера телефонов по заданной маске (формату):
use Fi1a\Format\Formatter; Formatter::format('{{value|phone("+7(ddd)ddd-dddd")}}', ['value' => '+79228223576']); // +7(922)822-3576 Formatter::format('{{value|phone("+7(ddd)ddd-dddd")}}', ['value' => '9228223576']); // +7(922)822-3576 Formatter::format('{{value|phone("(dddd)dd-dd-dd")}}', ['value' => '(6783)44-00-44']); // (6783)44-00-44
Форматирование числа
С помощью функции спецификатора number
можно форматировать числа:
Модификаторы функции спецификатора форматирования числа:
- int decimals (2) - число знаков после запятой;
- string decimalSeparator ('.') - разделитель дробной части;
- string thousandsSeparator ('') - разделитель тысяч;
- bool allowZeroDecimal (false) - разрешить вывод 0 в конце дробной части.
use Fi1a\Format\Formatter; Formatter::format('{{value|number}}', ['value' => 100.00]); // 100 Formatter::format( '{{value|number(decimals, decimalSeparator, thousandsSeparator, allowZeroDecimal)}}', ['value' => 100100.00], [ 'decimals' => 2, 'decimalSeparator' => '.', 'thousandsSeparator' => ' ', 'allowZeroDecimal' => true, ] ); // 100 100.00 Formatter::format( '{{value|number(decimals, decimalSeparator, thousandsSeparator, allowZeroDecimal)}}', ['value' => 100100.00], [ 'decimals' => 2, 'decimalSeparator' => '.', 'thousandsSeparator' => ' ', 'allowZeroDecimal' => false, ] ); // 100 100 Formatter::format( '{{value|number(decimals, decimalSeparator, thousandsSeparator, allowZeroDecimal)}}', ['value' => 100100.12], [ 'decimals' => 2, 'decimalSeparator' => '.', 'thousandsSeparator' => ' ', 'allowZeroDecimal' => false, ] ); // 100 100.12
Для упрощения ввода функций спецификаторов форматирования числа, воспользуйтесь сокращением.
use Fi1a\Format\Formatter; Formatter::addShortcut('number', 'number(2, ".", " ", false)'); Formatter::format('{{value|~number}}', ['value' => 100100.12]); // 100 100.12 Formatter::format('{{value|~number}}', ['value' => 100100]); // 100 100
PHP форматирование цены
С помощью функции спецификатора price
можно форматировать цены:
Модификаторы функции спецификатора форматирования цены:
- int decimals (2) - число знаков после запятой;
- string decimalSeparator ('.') - разделитель дробной части;
- string thousandsSeparator ('') - разделитель тысяч;
- bool allowZeroDecimal (false) - разрешить вывод 0 в конце дробной части.
- int round (null) - округляет цену. Передавать константы: PHP_ROUND_HALF_UP - округляет от нуля, когда следующий знак находится посередине, PHP_ROUND_HALF_DOWN - округляет к нулю, когда следующий знак находится посередине.
- int roundPrecision (0) - количество десятичных знаков, до которых производится округление.
- bool floor (false) - округляет в меньшую сторону (до целового).
use Fi1a\Format\Formatter; Formatter::format('{{value|price}} руб.', ['value' => 100.00]); // 100 руб. Formatter::format( '{{value|price(decimals, decimalSeparator, thousandsSeparator, allowZeroDecimal)}} руб.', ['value' => 100100.00], [ 'decimals' => 2, 'decimalSeparator' => '.', 'thousandsSeparator' => ' ', 'allowZeroDecimal' => true, ] ); // 100 100.00 руб. Formatter::format( '{{value|price(decimals, decimalSeparator, thousandsSeparator, allowZeroDecimal)}} руб.', ['value' => 100100.00], [ 'decimals' => 2, 'decimalSeparator' => '.', 'thousandsSeparator' => ' ', 'allowZeroDecimal' => false, ] ); // 100 100 руб. Formatter::format( '{{value|price(decimals, decimalSeparator, thousandsSeparator, allowZeroDecimal)}} руб.', ['value' => 100100.12], [ 'decimals' => 2, 'decimalSeparator' => '.', 'thousandsSeparator' => ' ', 'allowZeroDecimal' => false, ] ); // 100 100.12 руб. Formatter::format( '{{value|price(decimals, decimalSeparator, thousandsSeparator, allowZeroDecimal, round, roundPrecision)}} руб.', ['value' => 100100.5], [ 'decimals' => 2, 'decimalSeparator' => '.', 'thousandsSeparator' => ' ', 'allowZeroDecimal' => false, 'round' => PHP_ROUND_HALF_UP, 'roundPrecision' => 0, ] ); // 100 101 руб. Formatter::format( '{{value|price(decimals, decimalSeparator, thousandsSeparator, allowZeroDecimal, round, roundPrecision)}} руб.', ['value' => 100100.5], [ 'decimals' => 2, 'decimalSeparator' => '.', 'thousandsSeparator' => ' ', 'allowZeroDecimal' => false, 'round' => PHP_ROUND_HALF_DOWN, 'roundPrecision' => 0, ] ); // 100 100 руб. Formatter::format( '{{value|price(decimals, decimalSeparator, thousandsSeparator, allowZeroDecimal, round, roundPrecision, floor)}} руб.', ['value' => 100100.6], [ 'decimals' => 0, 'decimalSeparator' => '.', 'thousandsSeparator' => ' ', 'allowZeroDecimal' => false, 'round' => null, 'roundPrecision' => 0, 'floor' => true, ] ); // 100 100 руб.
Для упрощения ввода функций спецификаторов форматирования цены, воспользуйтесь сокращением.
use Fi1a\Format\Formatter; Formatter::addShortcut('price', 'price(0, ".", " ", false, null, 0, true)'); Formatter::format('{{value|~price}} руб.', ['value' => 100100.6]); // 100 100 руб.
Условные конструкции
Доступны следующий условные конструкции: if, elseif, else, endif
.
При отсутствии ключа в массиве значений исключение не выбрасывается.
use Fi1a\Format\Formatter; Formatter::format('{{if(foo)}}{{bar}}{{else}}false{{endif}}', ['foo' => true, 'bar' => 'bar']); // bar Formatter::format('{{if(not_exists)}}{{foo}}{{elseif(bar)}}{{bar}}{{endif}}', ['foo' => 'foo', 'bar' => 'bar']); // bar
Возможно использование функций спецификаторов в условных конструкциях:
use Fi1a\Format\Formatter; Formatter::format('{{if(value|unescape==="a&b")}}{{value}}{{endif}}', ['value' => 'a&b']); // "a&b"
Добавление функций спецификаторов
Класс функции спецификатора должен реализовывать интерфейс \Fi1a\Format\Specifier\ISpecifier
Добавление новой функции спецификатора осуществляется с помощью метода Fi1a\Format\Formatter::addSpecifier()
:
use Fi1a\Format\Formatter; Formatter::addSpecifier('spf', Specifier::class); // true Formatter::format('{{foo|spf(true)}}', ['foo' => 'foo']); // foo
Сокращения
Для упрощения ввода функций спецификаторов можно использовать сокращения.
Сокращения добавляются методом Formatter::addShortcut
с указанием имени сокращения.
Для использования сокращения, введите название начиная с символа "~".
use Fi1a\Format\Formatter; Formatter::addShortcut('dt', 'date("d.m.Y", "en")'); Formatter::format('{{foo|~dt}}', ['foo' => time()]); // 29.09.2022