Generate a Text Excerpt with PHP
Sometimes showing a title just isn't enough to grab a user's attention. You need to give them a taste of the article to get them to click through and read your content. Generating a text preview is actually fairly simple; below, we'll go through one method of displaying the first few words of an entry.
View the Demo | Download Source
Define the function and it's variables
We'll be writing a function called textPreview(). It will accept an array of information, then break that information into smaller pieces and only return the pieces that we need for our preview.
We'll have to pass a few variables to our function: one to hold our text ($text), one to tell our function how many characters we want to display ($length), and one to let the function know whether or not we want to display the full entry ($full), which we will set to NULL as a default.
function textPreview($text,$length,$full=NULL)
{
// Process our entries...
}
I'll be passing $text as an array. There are a couple reasons for this: first, by using an array, we can use one function call to process all of our entries, rather than calling the function individually for each entry; second, I use this function to process entries retrieved from a MySQL table, and that resource is returned from mysql_fetch_array() as an array.
Set Up the Loops and Conditional Statements
With our variables declared, we're ready to start processing our entries. To process the whole array, we're going to use a for loop. In plain English, this loop says, "As long as $i, which starts at 0, is less than the number of elements in the array $text, do the following actions, then increment the value of $i by 1."
function textPreview($text, $length, $full=NULL)
{
for($i = 0; $i < count($text); $i++) {
// Process array elements here...
}
}
Since we've set a flag to let our function know whether or not to display the full entry, we need to set up an if...else statement to see if the value of $full is both set and matches the value of the entry we are displaying.
function textPreview($text, $length, $full=NULL)
{
for($i = 0; $i < count($text); $i++) {
if(isset($full) && $i == $full) {
// If $full matches our check, show the full entry
} else {
// Or else create a preview...
}
}
}
Our output is going to be another array. The reason behind this is that it's good practice to separate presentation logic from business logic, and by returning an array, it's easy to format the processed entries in another function (which we'll get to in a minute).
Check for Full-Display Flags
If the $full flag matches our required conditions, we'll return the full entry. We do this by setting three array elements:
function textPreview($text, $length, $full=NULL)
{
for($i = 0; $i < count($text); $i++) {
if($i == $full && isset($full)) {
$entry['id'] = $i;
$entry['text'] = $text[$i];
$entry['full'] = true;
} else {
// Or else create a preview...
}
$entryArray[] = $entry;
}
return $entryArray;
}
Our first array element (id) creates a numeric index so we can easily identify individual entries in order to allow access to them later (i.e. via JavaScript). The next element (text), since we're returning the full entry, is set to the original value of $text[$i]. Then, to let our formatting function know that this entry is being shown full-length, we set the third element (full) to true.
At the bottom of the function, we also added $entryArray[] = $entry. What we're doing with that is assigning our new array, $entry, as an element in a new array, $entryArray, which is our return value. This is a concept known as multi-dimensional arrays. Again, this is for easy access to our information later down the road in our formatting function.
Create the Preview
Now it's time to figure out how to create the preview of the entries that don't meet our required conditions. To start, we need to decide about how many characters we want to display. For this example, we'll use 150 characters as our starting point.
The method I've chosen to use involves finding the first occurrence of a whitespace character from the end of the first 150 characters in the entry. There are other ways to create a substring, but this method allows for a little more fine-grain control over the length of the returned string. If we were to use explode(), for example, and return the first 15 words of the entry, we're at the mercy of the length of those 15 words. If all the words are short, we'll have a very short preview, whereas a string of five-dollar words might push our preview outside the bounds of our alloted preview space. By setting a character starting point, then finding the first whitespace character, we can be pretty sure that our entry previews will all be pretty darn close to the same length.
After setting our id element, we need to create the preview. To find the first space after our desired starting point, we use the strpos() function. This returns the string position of the space, which means we can now create a sub-string of the entry without cutting any words off. We do this using the function substr(). To indicate that there's more to see, we'll append an ellipsis to the returned preview string, then set it as the text element.
Finally, we'll set the full element to false, since this isn't a full entry display.
function textPreview($text, $length, $full=NULL)
{
for($i = 0; $i < count($text); $i++) {
if($i == $full && isset($full)) {
$entry['id'] = $i;
$entry['text'] = $text[$i];
$entry['full'] = true;
} else {
$entry['id'] = $i;
$pos = strpos($text[$i],' ',$length);
$entry['text'] = substr($text[$i],0,$pos) . '...';
$entry['full'] = false;
}
$entryArray[] = $entry;
}
return $entryArray;
}
Format the Entries
We've now returned the processed entries in the variable $entryArray. To format them, we'll pass that variable to another function, which we'll call formatText():
function formatText($entryArray) {
$display = NULL;
foreach($entryArray as $entry) {
if($entry['full']===true) {
$highlight = ' class="highlight"'; // For CSS formatting
$toggle = '<a href="./">Collapse Entry</a>';
} else {
$highlight = NULL;
$toggle = '<a href="?full=' . $entry['id'] . '">Expand Entry</a>';
}
$display .= <<<ENTRY_DISPLAY
<p id="entry{$entry['id']}"$highlight>
{$entry['text']}
$toggle
</p>
ENTRY_DISPLAY;
}
return $display;
}
This function starts out by setting a variable, $display, which will contain our formatted information. It then starts a loop to process each entry stored in $entryArray separately.
If the full element is set to true, we add a class attribute set to "highlight" to allow for easy CSS styling, and set a link to allow our user to collapse the entry back to a preview. If it's set to false, we don't add any class attributes, and we create a link to expand the entry to full length.
Now we simply place all that information into XHTML markup and append it to our $display variable. Now we're ready to put the functions in action!
Using the Functions
To use our functions, we just add the following to the page of our choice:
<?php $length = 150; $text = mysql_fetch_array($result); $full = (isset($_GET['full'])) ? urlencode($_GET['full']) : NULL; $entryArray = textPreview($text,$length,$full); echo formatText($entryArray); ?>
And that's it! We have successfully created a text preview of an array of entries. For a working example, download the source code.
Comments.
Nice and clean tutorial.
BTW, every tuesday ?
Rodney 12:22pm Feb 3, 2009 permalink | flag
@Rodney:
Yeah, I'm going to do my best to post a new tip every Tuesday. I figured I needed a weekly deadline to keep me honest with my posting. :)
Jason Lengstorf 7:53pm Feb 3, 2009 permalink | flag
I noticed your comment in this thread:
http://www.lateralcode.com/2009/03/create-a-simple-picture-gallery-using-php/
How about some tuesday-tipping on how it should be done ?
Rodney 12:24am Mar 17, 2009 permalink | flag
Rodney-
I've been planning an article on the image gallery software I've written, but it's a little too big to tackle in an ITT post. I'll probably spread it across two or three entries due to the complexity of the topic.
Thanks for reading!
Jason Lengstorf 12:18pm Mar 17, 2009 permalink | flag
Join In.
Have something to say? By all means, speak up!
But first, a few rules:
Happy commenting!