Solved

substr text without cutting off words

Posted on 2016-09-12
15
45 Views
Last Modified: 2016-09-14
I am creating a blog and on the page that lists a bunch of articles there is a bit of the article followed by.... and a "read more" button.

My problem is that what I have done cuts words off. Is is possible to get it to show a complete word and then... as opposed to for example a bit of a word e.g.:   the big, grey eleph......

$post_content = substr($post_content_safe,0,100);

Open in new window

0
Comment
Question by:Black Sulfur
  • 7
  • 4
  • 2
  • +1
15 Comments
 
LVL 30

Expert Comment

by:Marco Gasi
ID: 41794863
This could be a possible solution:
$pos=strpos($content, ' ', 100);
substr($content,0,$pos ); 

Open in new window

WIth the first line you get the index of the first occurrence of a blank space in the given string starting the search  from the character 100. The second line get the text starting from 0 to the value of the blank space found with the first line. This will likely give you a string longer than 100 so you could use a lower value, maybe 90?

Here you find a function written using this tecnique: http://www.ebrueggeman.com/blog/abbreviate-text-without-cutting-words-in-half
0
 

Author Comment

by:Black Sulfur
ID: 41794879
Thanks marco,

I tried your code before the one on the link and get error:

Warning: strpos(): Offset not contained in string
0
 
LVL 108

Assisted Solution

by:Ray Paseur
Ray Paseur earned 200 total points
ID: 41794885
Check this function.  What you're asking for is called a "teaser fragment" in the publishing industry.  Here's how it's done.
https://iconoun.com/demo/teaser_fragment.php
<?php // demo/teaser_fragment.php
/**
 * Create a teaser fragment headline.
 * Return first few whole words followed by ellipses,
 * with a link to the full article.
 * "$length" is minimum truncation character count
 */
error_reporting(E_ALL);


function teaser_fragment($text, $length=32, $url='#', $delim='|||')
{
    // IF TRUNCATION IS NEEDED
    if (strlen($text) > $length)
    {
        // IF TRUNCATION IS NEEDED, BREAK STRING APART
        $t = wordwrap($text, $length, $delim);
        $a = explode($delim, $t);
        $z = '...';
    }
    // IF TRUNCATION IS NOT NEEDED
    else
    {
        $a[0] = $text;
        $z = NULL;
    }

    // CONSTRUCT THE FRAGMENT WITH THE LINK AND ADD ELLIPSIS (LINK) TO THE END
    $teaser
    = '<a target="_blank" href="'
    . $url
    . '">'
    . $a[0]
    . $z
    . '</a>'
    ;
    return $teaser;
}


// USE CASES
$headline = 'Now is the time for all good men to come to the aid of their party';
echo "<pre>";
echo PHP_EOL;
echo "1...5...10...15...20...25...30...35...40...45..." . PHP_EOL;
echo teaser_fragment($headline);

echo PHP_EOL;
echo teaser_fragment($headline, 300);

echo PHP_EOL;
echo teaser_fragment($headline, 15, 'http://en.wikipedia.org/wiki/Filler_text');

Open in new window

0
 
LVL 30

Expert Comment

by:Marco Gasi
ID: 41794899
The do a check before (like in a function I linked above)
if(strlen($post_content_safe) >= 100 ){
    $pos=strpos($content, ' ', 100);
    $post_content = substr($post_content_safe,0,$pos ); 
}else{
   $post_content = $post_content_safe;
}

Open in new window

0
 

Author Comment

by:Black Sulfur
ID: 41794962
Thanks guys, I will try these out and get back to you. Will unfortunately only be tomorrow.
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41794999
Another option is this (for interest)
$str = "The quick brown fox jumps over the lazy dog and the whale with the tail jumped into the pail";
$teaser = cutoff($str, 40);
function cutoff($s, $len)
{
   if (strlen($s) <= $len) return $s;
   for($i = $len; $i > 0 && $s[$i] != ' '; $i--);

   return substr($s, 0, $i);
}

Open in new window

About 33% more efficient.
0
 

Author Comment

by:Black Sulfur
ID: 41796471
@Julian, your solution doesn't show ... after it truncates the text?
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 51

Accepted Solution

by:
Julian Hansen earned 300 total points
ID: 41796505
Then just add an echo statement to see what is in the string.
$str = "The quick brown fox jumps over the lazy dog and the whale with the tail jumped into the pail";
$teaser = cutoff($str, 40);
echo $teaser;
function cutoff($s, $len)
{
   if (strlen($s) <= $len) return $s;
   for($i = $len; $i > 0 && $s[$i] != ' '; $i--);

   return substr($s, 0, $i);
}

Open in new window

0
 

Author Comment

by:Black Sulfur
ID: 41796516
I just added ... after echoing $teaser. Am I meant to echo $teaser?

echo $teaser."...";

Open in new window


It works but just want to double check that $teaser is what I should be echoing.
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41796541
The function cutoff() does the work and returns the trimmed text - so you call that function with the original string and the max length you want it to be and it returns the truncated string.

[Aside: cutoff is a bit of a lame name - brain was on strike - truncate might be better]

So long story short $teaser is what you should be echo ing out.
0
 

Author Comment

by:Black Sulfur
ID: 41796545
Okay, here is where I am at. I could not get Marco's solution to work (I didn't try out that external link of his). I got Ray's example to work using my database. And I got Julian's example to work from the database except that for some reason it repeats content i.e.

But I must explain to you how all thisBut I must explain to you how all this...

Julian Code:

$sql = "SELECT * FROM `posts`";
$result = $link->query($sql);
if($result->num_rows > 0){
	while($row = $result->fetch_assoc()){
		
		$post_content = htmlentities($row['post_content']);
	}
}


$str = $post_content;
$teaser = cutoff($str, 40);
echo $teaser;
function cutoff($s, $len)
{
   if (strlen($s) <= $len) return $s;
   for($i = $len; $i > 0 && $s[$i] != ' '; $i--);

   return substr($s, 0, $i);
}

echo $teaser."...";

Open in new window


Ray's code:

$sql = "SELECT * FROM `posts`";
$result = $link->query($sql);
if($result->num_rows > 0){
	while($row = $result->fetch_assoc()){
		
		$post_content = htmlentities($row['post_content']);
	}
}

function teaser_fragment($text, $length=32, $url='#', $delim='|||')
{
    // IF TRUNCATION IS NEEDED
    if (strlen($text) > $length)
    {
        // IF TRUNCATION IS NEEDED, BREAK STRING APART
        $t = wordwrap($text, $length, $delim);
        $a = explode($delim, $t);
        $z = '...';
    }
    // IF TRUNCATION IS NOT NEEDED
    else
    {
        $a[0] = $text;
        $z = NULL;
    }

    // CONSTRUCT THE FRAGMENT WITH THE LINK AND ADD ELLIPSIS (LINK) TO THE END
    $teaser
    = '<a target="_blank" href="'
    . $url
    . '">'
    . $a[0]
    . $z
    . '</a>'
    ;
    return $teaser;
}


// USE CASES
$headline = $post_content;
echo "<pre>";
echo PHP_EOL;
echo "1...5...10...15...20...25...30...35...40...45..." . PHP_EOL;
echo teaser_fragment($headline);

echo PHP_EOL;
echo teaser_fragment($headline, 300);

echo PHP_EOL;
echo teaser_fragment($headline, 25, 'http://en.wikipedia.org/wiki/Filler_text');

Open in new window

0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41796572
Look at Line 13 then look at Line 22

You are doing echo twice.
0
 

Author Comment

by:Black Sulfur
ID: 41796576
Ah. Okay, I fixed that and now it works perfectly :)
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 41796832
$sql = "SELECT * FROM `posts`";
If you have something like SELECT * in your code, you need to start understanding why we avoid antipatterns!
https://www.experts-exchange.com/articles/12293/AntiPHPatterns-and-AntiPHPractices.html
0
 

Author Comment

by:Black Sulfur
ID: 41798331
Oh yes, sorry. I was doing a tutorial that had * in it for simplicity's sake. In real world applications I certainly won't use * but thanks for the link!
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Consider the following scenario: You are working on a website and make something great - something that lets the server work with information submitted by your users. This could be anything, from a simple guestbook to a e-Money solution. But what…
Both Easy and Powerful How easy is PHP? http://lmgtfy.com?q=how+easy+is+php (http://lmgtfy.com?q=how+easy+is+php)  Very easy.  It has been described as "a programming language even my grandmother can use." How powerful is PHP?  http://en.wikiped…
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now