ksnk / text
一个类中的基于文本的功能
Requires
- php: >=7.3
Requires (Dev)
- phpunit/phpunit: 10.2.4
README
所有工具都以 tpl
类中的函数的形式实现。直接实现功能的类是 Model_tpl
,但为了方便使用,每个函数都可以作为 tpl
的静态函数调用。静态函数调用的别名通常更紧凑,不需要预先创建类,但在经典形式下可以更灵活地设置行为。而且使用继承会更好。不过,通常不需要这样做。
这个类的明显好处是它在普通和 Bitrix 服务器环境中都能很好地工作。
使用
use Ksnk\text\tpl;
$data=[
'promo'=>'СКОРОЛЕТО',
'first_name'=>'Вагоноуважатый',
'discountrub'=>250,
'prop'=>tpl::prop(2345,tpl::RUB),
'date'=>'now'
];
echo tpl::text('Глубокоуважаемый{first_name?{ first_name}{ second_name}}!
При оформлении заказа от {date|d}, Вам предоставлена скидка {discountrub?{discountrub}₽:{discount}%} по промокоду `{promo}`
Общая сумма заказа составляет: {prop}
',$data);
/*
Глубокоуважаемый Вагоноуважатый!
При оформлении заказа от 25 октября, Вам предоставлена скидка 250₽ по промокоду `СКОРОЛЕТО`
Общая сумма заказа составляет: две тысячи триста сорок пять рублей
*/
安装
composer require ksnk/text
实际上,这里只有两个文件,如果真的有需要,可以查看仓库,复制到本地并做任何操作。但不要让BГ太饿了))) 编译器确实很方便。
实现本身允许在运行时对模板化器进行少量修改或完全继承类,同时保留已重定义函数的静态调用选项。
输出数字的大写。tpl::prop($number, $podpis, $kop = FALSE)
第一个参数是数字,如果数字不是整数,则整数部分以文字输出,第二部分以数字输出,截断为两位数字。两部分的签名是第二个参数。"рубл|ь|я|ей;+копе|йка|йки|ек";
第三个参数表示是否可以省略输出 00 коп
。
在输出数字时考虑了词尾变化。如果指定了函数的第二个参数,女性性别用前导符号 +
标记。
$number=101;
//'сто один баран на поле', склонение в мужском роде - один-два
tpl::text('{prop} на поле', [
'prop'=>tpl::prop($number,"баран||а|ов")]);
);
// проверка склонения в женском роде одна-две вместо один-два
//'сто одна овца на поле',
tpl::text('{prop} на поле', [
'prop'=>tpl::prop($number,"+овц|а|ы|ец")]) ;
经典的带有分币的价格输出
// двадцать три тысячи четыреста пятьдесят шесть рублей 45 копеек
echo tpl:prop(23456.45, tpl::RUB, true);
输出俄语日期。tpl::rusd($time,$format)
令人惊讶的是,在PHP中,仍然缺少默认的俄语日期输出功能,日期名称使用的是属格,而不是普通格。这是怎么回事呢?
// так советуют писать тру ПХПшники
setlocale(LC_ALL, 'ru_RU', 'ru_RU.UTF-8', 'ru', 'russian');
echo strftime("%B %d, %Y", time()).PHP_EOL;
// Октябрь 25, 2022
// Так хочет бухгалтер
tpl::rusd(time(), "j F"); // 25 октября.
使用日期格式进行常规日期输出。可以是时间戳,也可以是从数据库中理解的操作符 strtotime 的字符串值。如果需要智能日期转换,最好在模板化器之外进行,并传递所需的正确时间戳。
复数形式。tpl::pl
数词的结尾。参数是字符串形式,ОДИН, ТРИ, ПЯТЬ
。
echo 25.' копе'.tpl::pl(25, 'копейка', 'копейки', 'копеек');
不过,它几乎没有任何独立的应用,通常作为模板的一部分。同样,字符串中参数的格式与 text
函数使用的格式略有不同,这使显式使用该函数成为一种有害的做法。在模板中使用了更紧凑的调用形式——一行参数,用 |
分隔。例如,通过 ::text
的这个示例看起来更易于管理
echo tpl::text('{kop} копе{|йка|йки|еек}',['kop'=>25]);
解析缩写数字。tpl::parseKMG
将字符串缩写转换为数字。.5k 1K 等。
echo tpl::parseKMG('.25Г'); // четверть гига - 268435456
在解析控制台实用程序的输出时非常方便。缺点是它不会对这不是数字的情况做出任何反应。
tpl::text
带值替换的格式化输出。
- 第一个参数是模板
- 第二个参数是数据。最好是对象,但不是必需的,在函数内部它将被显式转换为对象。由于检查对象中的属性是通过
property_exists
方法进行的,因此不能传递具有魔术属性的对象。
在模板中可能存在占位符替换运算符——花括号中的变量。变量的末尾可能跟有修饰符,由 |
分隔。例如 {date|t}
。如果替换的值不为空,则替换值前的前导空格将与替换值一起输出。
$data=[
'first_name'=>'Вассисуалий',
'second_name'=>'Лоханкин',
'joined'=>'2022-10-15'
];
echo tpl::text('Уважаемый{ first_name}{ second_name}!', $data);
这种非标准的对前导空格的处理允许生成在空格处理方面正确的结构——Уважаемый Вассисуалий!
Уважаемый!
Уважаемый Лоханкин!
Уважаемый Вассисуалий Лоханкин!
一些符号具有特殊含义,在某些地方可能需要转义,以防止模板化器使用。这些符号是 {}?:\|
。
我们将展示转义符的奇迹。从技术角度看,在占位符内部并不一定需要转义所有特殊符号,只需那些根据语法预期的符号即可。然而,如果全部转义,结果将完全相同。在PHP中设置所需斜杠的最便捷方法是 addcslashes($x,'{}?:\|');
。
// не все служебные символы прослешены, но синтаксис позволяет
$pattern = 'Сумма прописью:{ Очень странная переменная {1\|2\}\?: }';
// 'Сумма прописью: А вот!',
echo tpl::text($pattern, ['Очень странная переменная {1|2}?:' => 'А вот!']);
// все служебные символы прослешены
$pattern = 'Сумма прописью:{ Очень странная переменная \{1\|2\}\?\: }';
// 'Сумма прописью: А вот еще!',
echo tpl::text($pattern, ['Очень странная переменная {1|2}?:' => 'А вот еще!']);
// правильный способ, всегда дающий правильный результат
$key='Очень странная переменная {1|2}?:';
$pattern = 'Сумма прописью:{ '.addcslashes($key,'{}?:\|').' }';
echo tpl::text($pattern, [$key => 'А вот еще!']);
除了占位符,还有逻辑三目运算符。如果占位符参数值非空,则选择第一个操作数,如果为空,则选择第二个。需要注意的是,三目运算符条件中的前导空格将被忽略,操作数内部的工作模式是正常的。
echo tpl::text('Уважаемый {joined?подписчик:посетитель}!', $data);
操作数内部也可能包含占位符和逻辑运算符。
echo tpl::text('Уважаемый {first_name?:посетитель}!', $data);
条件运算符 ?:
的输出逻辑与直观的不同。如果参数非空,则输出该参数,如果为空,则输出默认值。实际上,它是 {first_name?{first_name}:посетитель}
的缩写。
三目运算符的“条件”部分也可以包含可计算的构造。
tpl::text(
"<b>Ваш счет - {count} из {total}</b>. {10<count?Поздравляем с успешным прохождением тестирования!
Ваш сертификат будет отправлен на почту указанную в Личном кабинете \ или ваш сертификат находится в вашем ЛК в разделе Обучение (возможно ли создать такую вкладку)
:Вам немного не хватило баллов для сертификата Проф уровня.}",$data)
如果数据数组包含子数组,可以通过点来指定值。如果数据数组中存在“点”键,将使用其值。
$tpl::text('{POINT}{ CURRENT.POINT}{ CURRENT.diff}',
['POINT'=>'111', 'CURRENT.POINT'=>'22', 'CURRENT'=>['diff'=>444,'POINT'=>333]]); // '111 22 444'
数字的结尾是 |||。
$data['number]=23;
echo tpl::text('{number} баран{||а|ов} пас{|ё|у|у}тся на поле!', $data);
echo tpl::text('{number} баран{number||а|ов} пас{|ё|у|у}тся на поле!', $data);
echo tpl::text('{number} {баран||а|ов} пас{|ё|у|у}тся на поле!', $data);
// 23 барана пасутся на поле
包含3个字符 |
的修饰符。可以有两种形式,完整形式为 баран{number||а|ов}
,缩短形式为 баран{||а|ов}
。在后一种情况下,数值取自最后一个数字占位符。
修饰符列表。
数字结尾
- 如上所述。|q
- 单引号。值被引号引用并包围在单引号中。|qq
- 双引号。值被引号引用并包围在双引号中。此时,值占据一行。对于插入javascript很有用。|t
- 时间以25 апреля 2022 г. в 10:00
的形式输出。|d
- 时间以25 апреля
或25 апреля 2020 г.
的形式输出,如果日期的年份与当前年份不匹配。|d|j F Y г. в H\:i
- 带有显式输出格式的日期。格式在括号之前输出。请注意,如果与t
修饰符一起指定了格式,则与d
没有区别。
使用日期修饰符时,可以使用与 strtotime 兼容的值。
可以添加自己的修饰符,用于此的是 tpl::mod
函数。
tpl::mod('x', function ($data, $mod_ext, $spaces, $key, $mod) {
//...
return $spaces . $data;
});
回调函数的参数将包括
- $data - 从参数获取的值
- $mod_ext - 如果在模板中指定了修饰符参数,则为修饰符参数
- $spaces - 在指定键之前的前导空格字符串。其他参数可以在函数修饰符中省略,但在调用时传递,并可以根据需要使用。
- $key - 用于查找值的键。在特殊情况下可能适用,例如当键为
''
时,$data 没有明确指定,而是从上一个数字占位符获取。或者在参数数据缺失时,需要通过键在附加数据数组中执行额外搜索。 - $mod - 自身的修饰符,如果同一个函数用于不同的修饰符,可以通过此参数区分调用方式。
tpl::utext
与 text 不同的是,使用双花括号而不是单花括号来定义占位符和逻辑运算符的边界。在其余方面,模板的逻辑和运算符相同。包括条件运算符和修饰符符号也没有重复。在某种程度上,模板包含 Unisender 的模板语言。至少,我正在处理从那里下载的模板,就是在这个模式下。与 Unisender 相比,有更多功能,但与它本身不冲突。
tpl::sql
是模板化器的实验模式。允许在相当异乎寻常的条件下准备 sql 查询。不推荐广泛使用。这个模式的好处是 sql 与使用的 CMS 无关,这允许编写更可移植的系统到系统模块,但实验模式不允许广泛推荐这种方法来处理数据库。
如果非常需要继承,可以使用 tpl::_。
假设我们想扩展或修改类的功能,但无法访问仓库。可以创建类的子类,并在其中进行所有必要的扩展。
class ChildTpl extends Model_tpl
{
function xxx()
{
return 'xxx';
}
}
为了保留静态调用功能,请执行以下代码:
tpl::_(new ChildTpl);
之后,您将能够调用 tpl::xxx()
而不会收到 PHP 的错误信息。请注意 - 类继承者的函数不应被定义为静态的。在定义和初始化之后,所有对实用工具的使用将通过重定义的类进行。
更复杂的继承示例是仓库中的 Model_sql
类。它完全重定义了模板化器的逻辑,使其可用于准备 SQL 查询。为了保留在普通文本中使用模板的能力,引入了一个单独的 SQL 函数,在其中可以开启和关闭特殊工作模式。