PHP substr, но оставить HTML-теги? - PullRequest
19 голосов
/ 20 января 2012

Мне интересно, есть ли элегантный способ обрезать текст, но при этом знать тег HTML?

Например, у меня есть эта строка:

$data = '<strong>some title text here that could get very long</strong>';

И скажем, мне нужно возвращать / выводить эту строку на странице, но хотелось бы, чтобы она была длиной не более X символов. Давайте скажем 35 для этого примера.

Тогда я использую:

$output = substr($data,0,20);

Но теперь я получаю:

<strong>some title text here that 

, который, как вы можете видеть, закрывающие сильные теги отбрасываются, нарушая отображение HTML.

Есть ли способ обойти это? Также обратите внимание, что в строке можно использовать несколько тегов, например:

<p>some text here <strong>and here</strong></p>

Ответы [ 3 ]

5 голосов
/ 27 декабря 2015

Несколько месяцев назад я создал специальную функцию, которая решает вашу проблему.

Вот функция:

function substr_close_tags($code, $limit = 300)
{
    if ( strlen($code) <= $limit )
    {
        return $code;
    }

    $html = substr($code, 0, $limit);
    preg_match_all ( "#<([a-zA-Z]+)#", $html, $result );

    foreach($result[1] AS $key => $value)
    {
        if ( strtolower($value) == 'br' )
        {
            unset($result[1][$key]);
        }
    }
    $openedtags = $result[1];

    preg_match_all ( "#</([a-zA-Z]+)>#iU", $html, $result );
    $closedtags = $result[1];

    foreach($closedtags AS $key => $value)
    {
        if ( ($k = array_search($value, $openedtags)) === FALSE )
        {
            continue;
        }
        else
        {
            unset($openedtags[$k]);
        }
    }

    if ( empty($openedtags) )
    {
        if ( strpos($code, ' ', $limit) == $limit )
        {
            return $html."...";
        }
        else
        {
            return substr($code, 0, strpos($code, ' ', $limit))."...";
        }
    }

    $position = 0;
    $close_tag = '';
    foreach($openedtags AS $key => $value)
    {   
        $p = strpos($code, ('</'.$value.'>'), $limit);

        if ( $p === FALSE )
        {
            $code .= ('</'.$value.'>');
        }
        else if ( $p > $position )
        {
            $close_tag = '</'.$value.'>';
            $position = $p;
        }
    }

    if ( $position == 0 )
    {
        return $code;
    }

    return substr($code, 0, $position).$close_tag."...";
}

Вот DEMO: http://sandbox.onlinephpfunctions.com/code/899d8137c15596a8528c871543eb005984ec0201 (нажмите «Выполнить код», чтобы проверить, как он работает).

0 голосов
/ 14 ноября 2017

Используя @newbieuser его функцию, у меня возникла такая же проблема, как @ pablo-pazos, что она (не) ломалась, когда $ limit попадал в html-тег (в моем случае <br /> на r)

Исправлено с кодом

if ( strlen($code) <= $limit ){
    return $code;
}

$html = substr($code, 0, $limit);       

//We must find a . or > or space so we are sure not being in a html-tag!
//In my case there are only <br>
//If you have more tags, or html formatted text, you must do a little more and also use something like http://htmlpurifier.org/demo.php

$_find_last_char = strrpos($html, ".")+1;
if($_find_last_char > $limit/3*2){
    $html_break = $_find_last_char;
}else{
    $_find_last_char = strrpos($html, ">")+1;
    if($_find_last_char > $limit/3*2){ 
        $html_break = $_find_last_char;
    }else{
        $html_break = strrpos($html, " ");
    }
}

$html = substr($html, 0, $html_break);
preg_match_all ( "#<([a-zA-Z]+)#", $html, $result );
......
0 голосов
/ 18 февраля 2014

substr (strip_tags ($ content), 0, 100)

...