Функція 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 () .

/**
 * Cuts the specified text up to specified number of characters.
 * Strips any of shortcodes.
 *
 * @author Kama (wp-kama.ru)
 *
 * @version 2.7.1
 *
 * @param string|array $args {
 *     Optional. Arguments to customize output.
 *
 *     @type int       $maxchar            Макс. количество символов.
 *     @type string    $text               Текст который нужно обрезать. По умолчанию post_excerpt, если нет post_content.
 *                                         Если в тексте есть `<!--more-->`, то `maxchar` игнорируется и берется
 *                                         все до `<!--more-->` вместе с HTML.
 *     @type bool      $autop              Заменить переносы строк на `<p>` и `<br>` или нет?
 *     @type string    $more_text          Текст ссылки `Читать дальше`.
 *     @type string    $save_tags          Теги, которые нужно оставить в тексте. Например `'<strong><b><a>'`.
 *     @type string    $sanitize_callback  Функция очистки текста.
 *     @type bool      $ignore_more        Нужно ли игнорировать <!--more--> в контенте.
 *
 * }
 *
 * @return string HTML
 */
function kama_excerpt( $args = '' ){
	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' => 'strip_tags',
	], $args );

	$rg = apply_filters( 'kama_excerpt_args', $rg );

	if( ! $rg->text ){
		$rg->text = $post->post_excerpt ?: $post->post_content;
	}

	$text = $rg->text;
	// strip content shortcodes: [foo]some data[/foo]. Consider markdown
	$text = preg_replace( '~\[([a-z0-9_-]+)[^\]]*\](?!\().*?\[/\1\]~is', '', $text );
	// strip others shortcodes: [singlepic id=3]. Consider markdown
	$text = preg_replace( '~\[/?[^\]]*\](?!\()~', '', $text );
	$text = trim( $text );

	// <!--more-->
	if( ! $rg->ignore_more && strpos( $text, '<!--more-->' ) ){
		preg_match( '/(.*)<!--more-->/s', $text, $mm );

		$text = trim( $mm[1] );

		$text_append = ' <a href="' . get_permalink( $post ) . '#more-' . $post->ID . '">' . $rg->more_text . '</a>';
	}
	// text, excerpt, content
	else {

		$text = 'strip_tags' === $rg->sanitize_callback
			? strip_tags( $text, $rg->save_tags )
			: call_user_func( $rg->sanitize_callback, $text, $rg );

		$text = trim( $text );

		// cut
		if( mb_strlen( $text ) > $rg->maxchar ){
			$text = mb_substr( $text, 0, $rg->maxchar );
			$text = preg_replace( '/(.*)\s[^\s]*$/s', '\\1...', $text ); // del last word, it not complate in 99%
		}
	}

	// add <p> tags. Simple analog of wpautop()
	if( $rg->autop ){
		$text = preg_replace(
			[ "/\r/", "/\n{2,}/", "/\n/", '~</p><br ?/?>~' ],
			[ '', '</p><p>', '<br />', '</p>' ],
			$text
		);
	}

	$text = apply_filters( 'kama_excerpt', $text, $rg );

	if( isset( $text_append ) ){
		$text .= $text_append;
	}

	return ( $rg->autop && $text ) ? "<p>$text</p>" : $text;
}

/* Сhangelog:
 * 2.7.0 - Параметр sanitize_callback
 * 2.6.5 - Параметр ignore_more
 * 2.6.4 - Забрав пробіл між словом і крапками
 * 2.6.3 - Рефакторинг
 * 2.6.2 - Добавив регулярку для видалення блочних шорткодів вида: [foo]some data[/foo]
 * 2.6   - Видалив параметр 'save_format' и замінив його на два параметри 'autop' і 'save_tags'.
 *       - Немного изменил логику кода.
 */

Як працює функція?

  1. Обрізає до певної кількості символів. Вказується в параметрі maxchar.
  2. Розуміє тег <! - more -> в запису. Якщо він присутній бажану кількість виведених символів ігнорується і виводиться все що вище  <! - more -> зі збереженням HTML розмітки.
  3. Можна вказати зберігати переноси рядків або писати весь текст в один рядок. За замовчуванням переноси зберігаються, якщо потрібен "суціль" ставимо параметр autop = 0 .
  4. Можна вказано які HTML теги не потрібно вирізати. Наприклад ми хочемо залишити теги <strong> і <em> , тоді вказуємо їх так:save_tags=<strong><em>
  5. Функцію також можна використовувати для обрізки будь-якого тексту, який їй буде переданий. Для цього вказуємо текст в параметрі text.

Обрізка в усіх випадках обчислює кількість символів, а потім прибирає останні символи до пробілу. Потрібно це для того, щоб в кінці завжди залишалося закінчене слово, а не шматок недописаний (думаю це некрасиво).

Використання

<? php  echo kama_excerpt (  [  'maxchar' = > 100 ,  'text' = > 'бла бла'  ]  ) ;  ?>

Щоб замінити стандартний the_excerpt () потрібно просто замінити the_excerpt () на kama_excerpt () . Все це повинно бути всередині циклу WordPress .

ВАЖЛИВО: Параметр textпри заміні the_excerpt () ; вказувати не треба!

Приклад використання функції для обрізки будь-якого тексту:
$str = "Функцию [foo]some text[/foo] [foo]some text[/foo] обрезки текста для Worpress,
можно применять [foo url='bar'] и на других движках.";

echo kama_excerpt([ 'text'=>$str, 'maxchar'=>70 ]);

Отримаємо

<p>Функцию   обрезки текста для Worpress,<br />
можно применять  и на других ...</p>

При обрізанні переданого функції тексту, спрацьовує тільки та частина функції яка необхідна (ніяких зайвих операцій).

Дуже простий приклад обрізки тексту

Якщо ви не хочете використовувати функцію і вам потрібно просто обрізати текст не збереження html теги та інше, то можна скористатися такою короткою рядком всередині циклу WordPress:

<?php
$maxchar = 152;
$text = strip_tags( get_the_content() );
echo mb_substr( $text, 0, $maxchar );
?>
Поширити