Обрежьте слова, но остановитесь в конце элемента html, если он найден

Эта функция отлично работает, однако, если html-элемент найден, она остановится там, где будет отсчет 45-го символа, независимо от того, что ломает html-элемент. Как я могу сделать исключение для этого? Я предполагаю какое-то регулярное выражение, но не уверен, что лучше в этом случае.

public function fts_custom_trim_words( $text, $num_words = 45, $more ) {
    ! empty( $num_words ) && 0 !== $num_words ? $more = __( '...' ) : '';
    $text = nl2br( $text );
    $text = strip_shortcodes( $text );
    // Add tags that you don't want stripped.
    $text        = strip_tags( $text, '<strong><br><em><i><a>' );
    $words_array = preg_split( "/[\n\r\t ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY );
    $sep         = ' ';
    if ( count( $words_array ) > $num_words ) {
        array_pop( $words_array );
        $text_string = implode( $sep, $words_array );
        $text        = $text_string . $more;
    } else {
        $text = implode( $sep, $words_array );
    }

    return wpautop( $text );
}

Сейчас что-то подобное сломает....

@aeocreative и я на церемонии награждения журнала Sarasota Magazine «Дом года»! Я сфотографировал дом для @tracee_murphy < a href="https://www.instagram.com/trade"...

Вы хотите, чтобы ссылка была кликабельной или текстовым после полосы?

Daniel G 06.03.2019 21:51

С чего начинается строка и чем она должна заканчиваться?

user3783243 06.03.2019 21:59

Я надеялся, что если он найдет html-элемент, он будет ждать его конца, прежде чем добавлять...

SlickRemix 06.03.2019 22:00

Может быть, что-то вроде regex101.com/r/KxyVTT/1 Это должно пропускать элементы, за некоторыми исключениями, и может пропускать некоторые химические формулы и математические уравнения, но если предположить, что все в порядке?

user3783243 06.03.2019 22:02

Строка является динамической и может содержать любое количество ссылок, поэтому в идеале мне нужно что-то, если она найдет ссылку перед остановкой, обязательно включите остальную часть ссылки перед остановкой... Я видел множество так называемых решений, но ни одно из них работает на меня.

SlickRemix 07.03.2019 00:09
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
5
85
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

У вас есть два варианта:

1) Использовать PHP stript_tags() (простой вариант) Это вернет обычный текст, любые теги в строке больше не будут работать (например, <a>, <strong>, <li> и т. д. Реализация будет выглядеть так:

$text = strip_tags($text);

2) Используйте предложение @Chris Harrison здесь: Ограничение текстовой строки PHP, НЕ включая теги html?

Этот вариант сохраняет теги, но потребует перестройки вашей функции, чтобы сделать ее более сложной.

Обновлено:

Возможно, это не то, что вы ищете, но я создал простое решение, которое разбивает строку на фрагменты, а затем проверяет каждый фрагмент. Это не так точно, как вариант 2, но требует намного меньше кода.

function truncate($string, $maxChars) {
    // Explode input string on a character
    $stringParts = explode(' ', $string);
    $finalString = '';
    $charCount = 0;
    foreach ($stringParts as $part) {
        if ($charCount <= $maxChars) {
            $charCount += strlen(strip_tags($part));
            $finalString .= (' ' . $part);
        } else {
            return $finalString;
        }
    }
}

Спасибо, я думаю, что № 2 - это ответ для меня, я проверю его и вернусь к вам.

SlickRemix 06.03.2019 22:06

Строка является динамической и может содержать любое количество ссылок, поэтому в идеале мне что-то нужно, если она найдет ссылку перед остановкой, обязательно включите остальную часть ссылки перед остановкой, ни одно из ваших решений не работает для меня, к сожалению.

SlickRemix 07.03.2019 00:10
Ответ принят как подходящий

это может работать, непроверено, но оно должно работать и делать то, что вы просили...

этот первый - обрезать @ количество символов

<?php

function truncate_by_characters ( $s, $l = 45, $e = '...' )
{
    $sl = strlen ( $s );

    $ns = 0;

    $cr = 0;

    $rs = '';

    preg_match_all ( '/<[^>]*>[^<]+</[^>]*>|<(?!/)[^>]*>/', $s, $m, PREG_OFFSET_CAPTURE | PREG_SET_ORDER );

    foreach ( $m as $v )
    {
        if ( ( $v[0][1] - $ns ) >= $l )
        {
            break;
        }

        $ss = substr ( $s, $ns, ( $v[0][1] - $ns ) );

        $cr += strlen ( $ss );

        $rs .= $ss . $v[0][0];

        $ns = ( $v[0][1] + strlen ( $v[0][0] ) );
    }

    if ( $cr < $l )
    {
        if ( ( $ns + ( $l - $cr ) ) > $sl )
        {
            $ts = substr ( $s, $ns, ( $sl - $ns ) );
        }
        else
        {
            $ts = substr ( $s, $ns, ( $l - $cr ) );
        }

        for ( $x = ( strlen ( $ts ) - 1 ); $x >= 0; $x -= 1 )
        {
            $z = array ( "\t", "\r", "\n", " ", "\0", "\x0B" );

            if ( in_array ( $ts[$x], $z ) )
            {
                $rs .= substr ( $ts, 0, $x );

                break;
            }
        }
    }

    return $rs . $e;
}

$truncate_text = 'This <img src = "" alt = ""> function works great however if a <a href = "http://.com/page.html?test=1">html element</a> is found it will stop where the 45th character count is no matter what, which breaks the html element. How can I make an exception for this? I\'m guessing some kind of regex but not sure what is best in this case.';

//$truncate_text = 'This function works great however if a html element is found it will stop where the 45th character count is no matter what, which breaks the html element. How can I make an exception for this? I\'m guessing some kind of regex but not sure what is best in this case.';

$truncate_characters = 45;

$truncate_ending = '...';

echo truncate_by_characters ( $truncate_text, $truncate_characters, $truncate_ending );

?>

ПРИМЕЧАНИЕ. Функция, указанная выше, работает, однако функция, указанная ниже, в настоящий момент не дает никаких результатов.

этот второй - обрезать @ количество слов

<?php

function truncate_by_words ( $s, $l = 45, $e = '...' )
{
    $sl = strlen ( $s );

    $ns = 0;

    $tw = 0;

    $rs = '';

    preg_match_all ( '/<[^>]*>[^<]+</[^>]*>|<(?!/)[^>]*>/', $s, $m, PREG_OFFSET_CAPTURE | PREG_SET_ORDER );

    foreach ( $m as $v )
    {
        $ss = substr ( $s, $ns, ( $v[0][1] - $ns ) );

        $wf = str_word_count ( $ss, 2 );

        $wc = count ( $wf );

        if ( ( $tw + $wc ) >= $l )
        {
            $mw = 1;

            foreach ( $wf AS $wp => $wv )
            {
                if ( ( $tw + $mw++ ) == $l )
                {
                    $ss = substr ( $s, $ns, ( $wp - $ns ) );

                    $rs .= $ss . $wv;

                    $ns = ( $wp + strlen ( $wv ) );

                    $tw = $l;

                    break;
                }
            }
        }

        $tw += $wc;

        $rs .= $ss . $v[0][0];

        $ns = ( $v[0][1] + strlen ( $v[0][0] ) );
    }

    if ( $tw < $l )
    {
        $ss = substr ( $s, $ns, ( $sl - $ns ) );

        $wf = str_word_count ( $ss, 2 );

        $wc = count ( $wf );

        if ( ( $tw + $wc ) <= $l )
        {
            $rs .= $ss;
        }
        else
        {
            $mw = 1;

            foreach ( $wf AS $wp => $wv )
            {
                if ( ( $tw + $mw++ ) == $l )
                {
                    $ss = substr ( $ss, 0, $wp );

                    $rs .= $ss . $wv;

                    break;
                }
            }
        }
    }

    return $rs . $e;
}

$truncate_text = 'This <img src = "" alt = ""> function works great however if a <a href = "http://.com/page.html?test=1">html element</a> is found it will stop where the 45th character count is no matter what, which breaks the html element. How can I make an exception for this? I\'m guessing some kind of regex but not sure what is best in this case.';

//$truncate_text = 'This function works great however if a html element is found it will stop where the 45th character count is no matter what, which breaks the html element. How can I make an exception for this? I\'m guessing some kind of regex but not sure what is best in this case.';

$truncate_words = 35;

$truncate_ending = '...';

echo truncate_by_words ( $truncate_text, $truncate_words, $truncate_ending );

?>

Хорошо, первый для количества символов работает отлично, однако я бы очень хотел, чтобы слова работали, если это возможно, прямо сейчас функция слов не работает. Также вы можете рассмотреть такие теги, как @foo_underscore, иначе _underscore тоже останется несвязанным. Большое спасибо за вашу помощь здесь.

SlickRemix 07.03.2019 18:01

Просто вдогонку :)

SlickRemix 08.03.2019 15:53

@ 10826537 не могли бы вы помочь :)

SlickRemix 10.03.2019 02:16

Другие вопросы по теме