Мне интересно, есть ли элегантный способ обрезать какой-то текст, но, будучи осведомленным в тегах 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>
Несколько месяцев назад я создал специальную функцию, которая является решением вашей проблемы.
Вот функция:
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."..."; }
с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."..."; }
не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 (нажмите «Выполнить код», чтобы проверить, как он работает).
Используя @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 ); ......
substr (strip_tags ($ content), 0, 100)