正确使用PHP包含'a'元素的字符串

时间:2011-09-09 08:20:01

标签: php html substr

我目前正在撰写一个获取Facebook和Twitter提要的课程,然后将它们组合成一个用于在网站上显示的课程。

但是由于a个元素在一个简单的substr函数后最终没有被关闭,我遇到一个限制输入文本输出的问题。

想象一下我有这个字符串:

'Check out our site at <a href="http://site.com/">site.com</a>'

我想将此限制为50个字符。如果我只是做substr($input,0,50),我将会得到以下内容:

'Check out our site at <a href="http://site.com/">s'

一个未关闭的a元素,它会将我网站的其余部分转换为链接。

我想可能正在使用DOMDocument我可以暂时用<a></a>之间的部分替换完整的URL,进行减法,然后重新应用链接。

然而我无法弄清楚如何做到这一点,它给我留下了另一个问题/选择:如果 - 假设我能够暂时替换链接 - 在减法后我最终得到了一半的链接:

'Check out our site at sit'

然后很难重新应用链接,所以最好用[[id]]替换它,并让脚本记住文本的长度。

无论如何,有没有人可以帮我解决这个问题?

编辑它仅适用于a个标签,因为我strip_tags就是其他所有标签。

3 个答案:

答案 0 :(得分:1)

php.net/substr的这段代码非常适用于此。

示例:

echo substrws("Check out our site at <a href=\"http://site.com/\">site.com</a>. It's really <strong>nice</strong>", 50);

收率:

Check out our site at <a href="http://site.com/">site.com</a>.

代码:

/**
* word-sensitive substring function with html tags awareness
* @param text The text to cut
* @param len The maximum length of the cut string
* @returns string
**/
function substrws( $text, $len=180 ) {

    if( (strlen($text) > $len) ) {

        $whitespaceposition = strpos($text," ",$len)-1;

        if( $whitespaceposition > 0 )
            $text = substr($text, 0, ($whitespaceposition+1));

        // close unclosed html tags
        if( preg_match_all("|<([a-zA-Z]+)>|",$text,$aBuffer) ) {

            if( !empty($aBuffer[1]) ) {

                preg_match_all("|</([a-zA-Z]+)>|",$text,$aBuffer2);

                if( count($aBuffer[1]) != count($aBuffer2[1]) ) {

                    foreach( $aBuffer[1] as $index => $tag ) {

                        if( empty($aBuffer2[1][$index]) || $aBuffer2[1][$index] != $tag)
                            $text .= '</'.$tag.'>';
                    }
                }
            }
        }
    }

    return $text;
}

答案 1 :(得分:0)

另一个解决方案是strip_tags() - php的功能如下:

<?php
$text = '<p>Check out our site at </p><!-- other html stuff anywhere--> <a href="http://site.com/">site.com</a>';
echo strip_tags($text);
echo "\n";

// juts allow <p> and <a>
echo strip_tags($text, '<p><a>');
?>

答案 2 :(得分:0)

我最后编写了自己的函数,也许可以使用一些改进,但它有效:

private function substr_html($input,$limit){

    $original = $input;

    if(strlen($input) <= $limit)
        return $input;

    $pattern = '#<a\s+.*?href=[\'"]([^\'"]+)[\'"]\s*?.*?>((?:(?!</a>).)*)</a>#i';   

    // Match all 'a' elements
    preg_match_all($pattern,$input,$matches);

    // If no links were found, perform a simple substr()
    if(count($matches[0]) == 0)
        return substr($input,0,$limit).'...';

    $uni     = sha1(uniqid());      

    preg_replace($pattern,$uni,$input);

    $input  = explode($uni,$input);
    $tmp    = $output = '';

    // Go through the splitted input        
    foreach($input as $i){

        if(strlen($tmp.$i) < $limit){

            // If we can fit the next text value without reaching the limit, do it  
            $tmp    .= $i;
            $output .= $i;

        }else{

            // Add whatever we can fit from the last text value and break the loop
            $diff    = abs($limit - strlen($tmp));
            $output .= substr($i,0,$diff);
            break;

        }

        if(strlen($tmp) < $limit){ // Do we still have room before we reach the limit?

            $nextlink = array_shift($matches[1]);
            $nexttext = array_shift($matches[2]);

            if(strip_tags($nexttext,$this->allowed_tags) != '')
                if(strlen($tmp.$nexttext) < $limit){        

                    // Add the next link if it fits
                    $tmp    .= $nexttext;
                    $output .= '<a href="'.$nextlink.'" target="_blank">'.$nexttext.'</a>';

                }else{

                    // Add whatever we can fit from the last link and break the loop
                    $diff    = abs($limit - strlen($tmp));
                    $output .= '<a href="'.$nextlink.'" target="_blank">'.substr($nexttext,0,$diff).'</a>';
                    break;

                }

        }

    }

    // Trim string and remove linebreaks
    $output = trim(preg_replace('/((<br>|<br\/>|<br \/>){1,})/'," ",$output));

    return $output.(strip_tags($original) != strip_tags($output) ? '...' : '');

}