tags:

views:

157

answers:

8

Hi guys, I have a problem with a PHP breadcrumb function I am using, when the page name is very long, it overflows out of the box, which then looks really ugly.

My question is, how can I achieve this: "This is a very long string" to "This is..." with PHP?

Any other ideas on how I could handle this problem would also be appreciated, thanx in advance!

Here is the breadcrumb function:

function breadcrumbs() {
 // Breadcrumb navigation
    if (is_page() && !is_front_page() || is_single() || is_category()) {
        echo '<ul class="breadcrumbs">';
        echo '<li class="front_page"><a href="'.get_bloginfo('url').'">'.get_bloginfo('name').'</a> <span style="color: #FFF;">&raquo;</span> </li>';

        if (is_page()) {
            $ancestors = get_post_ancestors($post);

            if ($ancestors) {
                $ancestors = array_reverse($ancestors);

                foreach ($ancestors as $crumb) {
                    echo '<li><a href="'.get_permalink($crumb).'">'.get_the_title($crumb).'</a> <span style="color: #FFF;">&raquo;</span> </li>';
                }
            }
        }

        if (is_single()) {
            $category = get_the_category();
            echo '<li><a href="'.get_category_link($category[0]->cat_ID).'">'.$category[0]->cat_name.'</a></li>';
        }

        if (is_category()) {
            $category = get_the_category();
            echo '<li>'.$category[0]->cat_name.'</li>';
        }

        // Current page
        if (is_page() || is_single()) {
            echo '<li class="current">'.get_the_title().'</li>';
        }
        echo '</ul>';
    } elseif (is_front_page()) {
        // Front page
        echo '<ul class="breadcrumbs">';
        echo '<li class="front_page"><a href="'.get_bloginfo('url').'">'.get_bloginfo('name').'</a></li>';
        echo '<li class="current">Home Page</li>';
        echo '</ul>';
    }
}
+2  A: 

You can safely use substr.

fabrik
...But this would give partial endings of the last word most times.
Martin Bean
It wasn't declared in the question. I don't like this kind of approach like yours: given a question, given an answer then a commenter coming and downvote every other answers. Nice, man.
fabrik
@Martin Bean - Maybe if the OP had specified that partial word endings were out of bounds your comment would be worth something. Stick to the OP request or put a comment to the question for clarification.
Joel Etherton
@fabrik I didn't down-vote every other answer...?
Martin Bean
Maybe just mine. Nevermind.
fabrik
+5  A: 

If you want a more nice (word limited) trucation you can use explode to split the string by spaces and then append each word (array entry) until you've reached your max limit

Something like:

define("MAX_LEN", 15);
$sentance = "Hello this is a long sentance";
$words = explode(' ', $sentance);
$newStr = "";
foreach($words as $word) {
  if(strlen($newStr." ".$word) >= MAX_LEN) {
     break;
  }
  $newStr = $newStr." ".$word;
}
sewa
Similar to how I truncate strings to avoid sub-word cutting.
Martin Bean
@Martin: except the fact your answer given after almost an hour after than this.
fabrik
I never questioned time? I added my two pence afterwards.
Martin Bean
+1  A: 

and eventually wordwrap() to break long words

killer_PL
How would that help in a breadcrumb list? Breadcrumbs are traditionally horizontal...
Martin Bean
+5  A: 

If you are working with UTF-8 as charset, I suggest using the mb_strimwidth method as it is multibyte safe and won´t mess up multibyte chars. It also appends a placeholder string like ... automatically, with substr you´d have to do that in an additional step.

Usage sample:

echo mb_strimwidth("Hello World", 0, 10, "...", "UTF-8"); // .. or some other charset
// outputs Hello W...
Max
+1 for I didn't know about that function! I wrote the exact same myself :)
Kau-Boy
+1  A: 

$string = "This is a very long string";

$newString = substr( $string, 0, 7)."...";

// Output = This is...

tummy.developer
A: 

You're after a truncate function. This is what I use:

/**
 * @param string $str
 * @param int $length
 * @return string
 */
function truncate($str, $length=100)
{
    $str = substr($str, $length);
    $words = explode(' ', $str); // separate words into an array
    array_pop($words); // discard last item, as 9/10 times it's a partial word
    $str = implode(' ', $words); // re-glue the string
    return $str;
}

And usage:

echo truncate('This is a very long page name that will eventually be truncated', 15);
Martin Bean
@Martin Bean - 9 times out of 10 is not 10 times out of 10.
Joel Etherton
Thanks for the maths lesson.
Martin Bean
+1  A: 

Ideally, it should be done on the client side. You can use CSS/JS for the same.

Set this CSS property: text-overflow: ellipsis. However, it will work only in IE. To use the same in Firefox as well, you can do something like this.

If you do not mind javascript plugins, use one of the jQuery ellipsis plugin.

Edit: These methods will work even when dealing with unicode, which can be a bit tricky if you try to handle this using php. (Like substr function)

Edit 2: If your problem is just the overflowing text and you do not mind not having the "..." at the end then it is even more simple. Simply, use the CSS: text-overflow: hidden;.

Vikash
A: 

You can truncate the string at max length and then search for the last space:

Multibyte safe (Requires PHP > = 4.2)

function mb_TruncateString($string, $length = 40, $marker = "...")
{
    if (mb_strlen($string) <= $length)
        return $string;

    // Trim at given length
    $string = mb_substr($string, 0, $length);

    // Get the text before the last space
    if(mb_ereg("(.*)\s", $string, $matches))
        $string = $matches[1];

    return $string  . $marker;
}

Following is not multibyte safe

function TruncateString($string, $length = 40, $marker = "...")
{
    if (strlen($string) <= $length)
        return $string;

    // Trim at given length
    $string = substr($string, 0, $length);

    // Get the text before the last space
    if(preg_match("/(.*)\s/i", $string, $matches))
        $string = $matches[1];

    return $string  . $marker;
}
Ozgur Ozcitak