Getting a substr without breaking tags
I am pulling a string from a database and displaying the first X characters of it. The string may have HTML in it. I don't want to break into a tag, though.
Right now I have
<?php
if(strlen(strip_tags($news[0]->post_content)) > 110)
{
echo substr($news[0]->post_content, 0, 110) . '... [<a href=\"'. $news[0]->guid .'\">more</a>]';
}
else
echo $news[0]->post_content;
?>
But say the string is
<?php
$string = 'blah blah <a href=\"http://somewhere.com\">this is a link</a> blah blah blah';
?>
If I want to get the first 25 characters and display them, the output would be the first two words and then half of the link tag.
I can't really think of a good way to get around this. I could write a function to go through each character in the string and grab each one until I reach the limit, but keep going until I reach the end of the tag if the limit is reached inside a tag, but that gets too complex when you consider that tags can stop and then have an ending tag (like [a href=""...]text here[/a]). I could just strip the tags before geting the substr, but I need the output to display any tags that are in the string.
Any ideas?
Greg K posted this at 00:26 — 3rd February 2006.
He has: 2,145 posts
Joined: Nov 2003
i suck at doing it, but look into the http://www.php.net/manual/en/function.eregi-replace.php function to replace everything between the < and > (including the <>'s) with an empty string.
-Greg
Dux0r posted this at 12:13 — 3rd February 2006.
She has: 31 posts
Joined: Jan 2006
I recently needed a function to do exactly the same thing. I modified one I found on PHP.net
It isn't 100% perfect but it does the job.
function html_substr($posttext, $minimum_length, $length_offset) {
// The approximate length you want the concatenated text to be
$minimum_length = 200;
// The variation in how long the text can be
// in this example text length will be between 200-10=190 characters
// and the character where the last tag ends
$length_offset = 10;
// Reset tag counter & quote checker
$tag_counter = 0;
$quotes_on = FALSE;
// Check if the text is too long
if (strlen($posttext) > $minimum_length) {
// Reset the tag_counter and pass through (part of) the entire text
for ($i = 0; $i < strlen($posttext); $i++) {
// Load the current character and the next one
// if the string has not arrived at the last character
$current_char = substr($posttext,$i,1);
if ($i < strlen($posttext) - 1) {
$next_char = substr($posttext,$i + 1,1);
}
else {
$next_char = "";
}
// First check if quotes are on
if (!$quotes_on) {
// Check if it's a tag
// On a "<" add 3 if it's an opening tag (like )
if ($current_char == "<") {
if ($next_char == "/") {
$tag_counter++;
}
else {
$tag_counter = $tag_counter + 3;
}
}
// Slash signifies an ending (like or ... />)
// substract 2
if ($current_char == "/") $tag_counter = $tag_counter - 2;
// On a ">" substract 1
if ($current_char == ">") $tag_counter--;
// If quotes are encountered, start ignoring the tags
// (for directory slashes)
if ($current_char == "\"") $quotes_on = TRUE;
}
else {
// IF quotes are encountered again, turn it back off
if ($current_char == "\"") $quotes_on = FALSE;
}
// Check if the counter has reached the minimum length yet,
// then wait for the tag_counter to become 0, and chop the string there
if ($i > $minimum_length - $length_offset && $tag_counter == 0) {
$posttext = substr($posttext,0,$i + 1) . "...";
return $posttext;
}
}
}
return $posttext;
}
IanD posted this at 02:33 — 5th February 2006.
They have: 222 posts
Joined: Sep 1999
Thanks Dux0r, that helps a lot
Want to join the discussion? Create an account or log in if you already have one. Joining is fast, free and painless! We’ll even whisk you back here when you’ve finished.