Удаление текста и замена стандартной функции the_excerpt()
Я заметил, что функция WordPress the_excerpt()
довольно тяжелая. Она использует много ресурсов и времени для выполнения, так как вызывает другие функции, такие как get_the_excerpt()
и the_content()
, и применяет к ним различные хуки, включая саму the_excerpt()
. В итоге выполняется много операций, которые не всегда необходимы. Например, я обрабатываю отрывки текста просто — это короткое описание статьи, в котором я вырезаю небольшую часть.
Я терпел этот недостаток, пока не понадобилось обрезать текст до определенного количества символов. Тогда я решил написать функцию для обрезки текста.
Результат замены the_excerpt()
меня порадовал: время генерации страницы снизилось в среднем с 0.850 секунд до 0.550 секунд при 9 вызовах the_excerpt()
(это на компьютере, на сервере обычно меньше). 9 вызовов — это количество записей, отображаемых в категории, к каждой из которых применялась функция the_excerpt()
.
Ниже представлена функция, которая может заменить станда��тную функцию WordPress the_excerpt()
.
<?php
/**
- Обрезает указанный текст до заданного количества символов.
- Удаляет любые шорткоды.
- !ВАЖНО: Эта функция НЕ экранирует текст.
- Предполагается, что текст уже экранирован с помощью wp_kses() или аналогичной функции.
- @version 2.8.1
- @param string|array $args {
- Необязательно. Аргументы для настройки вывода.
- @type int $maxchar Максимальное количество символов.
- @type string $text Текст, который надо обрезать. По умолчанию 'post_excerpt', если 'post_content' отсутствует.
- @type bool $autop Заменять ли переносы строк на
и
? - @type string $more_text Текст ссылки 'Читать далее'.
- @type string $save_tags Теги, которые будут оставлены в тексте. Например .
- @type string $sanitize_callback Функция для очистки текста.
- @type bool $ignore_more Игнорировать ли тег в содержимом.
- }
-
@return string HTML
*/
function kama_excerpt( $args = '' ): string {
global $post;if( is_string( $args ) ){
parse_str( $args, $args );
}$rg = (object) array_merge( [
'maxchar' => 350,
'text' => '',
'autop' => true,
'more_text' => 'Читать далее...',
'ignore_more' => false,
'save_tags' => '',
'sanitize_callback' => static function( string $text, object $rg ) {
return strip_tags( $text, $rg->save_tags );
},
], $args );$rg = apply_filters( 'kama_excerpt_args', $rg );
if( ! $rg->text ){
$rg->text = $post->post_excerpt ?: $post->post_content;
}$text = $rg->text;
// Удаляем шорткоды
$text = pregreplace( '~[([a-z0-9-]+)[^]]](?!().?[/1]~is', '', $text );
$text = preg_replace( '~[/?[^]]*](?!()~', '', $text );
// Удаляем прямые URLs
$text = preg_replace( '~(?<=s)https?://.+s~', '', $text );
$text = trim( $text );//
if( ! $rg->ignore_more && strpos( $text, '' ) ){
preg_match( '/(.*)/s', $text, $mm );
$text = trim( $mm[1] );
$text_append = sprintf( ' %s', get_permalink( $post ), $post->ID, $rg->more_text );
}
// обрезаем текст
else {
$text = call_user_func( $rg->sanitize_callback, $text, $rg );
$has_tags = false !== strpos( $text, '<' );if( $has_tags ){ $tags_collection = []; $nn = 0; $text = preg_replace_callback( '/<[^>]+>/', static function( $match ) use ( & $tags_collection, & $nn ) { $nn++; $holder = "~$nn"; $tags_collection[ $holder ] = $match[0]; return $holder; }, $text ); } // Обрезаем текст $cuted_text = mb_substr( $text, 0, $rg->maxchar ); if( $text !== $cuted_text ){ // Удаляем последнее слово, если оно не закончено $text = preg_replace( '/(.*)sS*$/s', '1...', trim( $cuted_text ) ); } // Возвращаем HTML теги if( $has_tags ){ $text = strtr( $text, $tags_collection ); $text = force_balance_tags( $text ); }
}
// Добавляем
теги.
if( $rg->autop ){
$text = preg_replace(
[ "/r/", "/n{2,}/", "/n/" ],
[ '', '', '
' ],
"$text
"
);
}$text = apply_filters( 'kama_excerpt', $text, $rg );
if( isset( $text_append ) ){
$text .= $text_append;
}return $text;
}
Как работает функция
-
Обрезает текст до заданного количества символов, указанного в параметре
maxchar
. -
Понимает тег
<!--more-->
. Если он присутствует, количество символов игнорируется, и отображается все, что выше тега<!--more-->
, включая HTML-разметку. -
Можно указать, нужно ли сохранять переносы строк или выводить весь текст в одной строке. По умолчанию переносы строк сохраняются. Если хотите "непрерывный текст", установите параметр
autop = 0
. -
Можно указать, какие HTML-теги не следует удалять. Например, если мы хотим сохранить теги
<strong>
и<em>
, укажите их так:save_tags=<strong><em>
. -
Функцию также можно использовать для обрезки любого текста, переданного ей. Для этого укажите текст в параметре
text
.
Во всех случаях функция обрезки считает количество символов и затем удаляет последние символы до пробела. Это нужно, чтобы в конце осталоcь целое слово, а не его обрывок (это выглядит некрасиво).
Как использовать
Вставьте приведенный выше код в файл functions.php
вашей темы. А чтобы вывести обрезанный текст, вызовите функцию так:
<?php echo kama_excerpt( [ 'maxchar'=>100, 'text'=>'blabla' ] ); ?>
Чтобы заменить стандартную функцию the_excerpt()
, просто замените the_excerpt()
на kama_excerpt()
. Все это должно быть внутри цикла WordPress.
ВАЖНО: Параметр text
не нужен, когда вы заменяете the_excerpt()
!
Пример использования функции для обрезки любого текста:
$str = "Функция [foo]некоторый текст[/foo] делает обрезку текста для WordPress,
может быть применена [foo url='bar'] и на других движках.";
echo kama_excerpt([ 'text'=>$str, 'maxchar'=>70 ]);
Мы получим:
Функция делает обрезку текста для WordPress,
может быть применена и на других ...
Когда обрезается текст, переданный функции, срабатывает только необходимая часть функции (без лишних операций).
Очень простой пример обрезки текста
Если вы не хотите использовать функцию и просто хотите обрезать текст без сохранения HTML-тегов и т.д., вы можете использовать следующую короткую строку внутри цикла WordPress:
<?php
$maxchar = 152;
$text = strip_tags( get_the_content() );
echo mb_substr( $text, 0, $maxchar );
?>
152 — это количество оставшихся символов.
Или воспользуйтесь функцией wp_trim_words()
.