• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Parsing Blog Posts for first <p> and <img> elements

#1
[eluser]waynhall[/eluser]
I'm trying to create a view that displays a thumbnail image and first paragraph of each post in a foreach loop.

I tried using simplexml and xpath to parse the document, but I think that's a little overkill, since I just want to grab the first and ignore the rest. There are also some character encoding issues when echoing out the text.

I tried using substr and strpos to parse the elements, which works, but the code is kind of ugly.

I don't want to use regex.

Anybody know of a simple way to do this in CodeIgniter?

#2
[eluser]JoostV[/eluser]
substr and strpos are a good way to do this. Fast & efficient.
You could chuck the code into a helper, so you can reuse it and your view code stays clean.

Code:
echo get_first_paragraph($body);

Helper code:
Code:
/**
* Return the first paragraph of a string, if it exists.
* If no paragraph exists, return the entire string.
*/
function get_first_paragraph($str) {
    if (stristr($str, '</p>')) {
        return substr($str, 0, strpos($str, '</p>') + 4);
    }
    return $str;
}

#3
[eluser]waynhall[/eluser]
Thanks. First I put these functions at the top of my view:
Code:
&lt;?php
    
    function get_thumbnail($content) {      // Returns src of first <img>
        
        $start = strpos($content, '<img');
        
        if($start !== FALSE) {      // '!==' Because '0' evaluates to false
            
            $end = strpos($content, '/>', $start) + 2;
            $length = $end - $start;
            $img_tag = substr($content, $start, $length);
            
            if($start = strpos($img_tag, 'src="') ){
                $start = $start + 5;
                $end = strpos($img_tag, '" ');  // assumes a space
                $length = $end - $start;
                $img_src = substr($img_tag, $start, $length);
                
                return $img_src;
            }
        }
    }
    
    function get_excerpt($content) {        // Returns contents of the first <p> tag
        
        $start = stripos($content, '<p');
        
        if($start !== FALSE) {   // '!==' Because '0' evaluates to false
            
            $p_open = strpos($content, '>', $start) + 1;
            $p_close = strpos($content, '</p>', $p_open);
            $length = $p_close - $p_open;
            $p_contents = substr($content, $p_open, $length);
            
            return $p_contents;
        }
        else return 'Excerpt not available';
    }

?&gt;

Then later, within the loop:

Code:
&lt;?php
            // if the post contains an image
            if($thumbnail = get_thumbnail($post->content)) {    
                $img = '<img class="post-thumbnail" src="' . $thumbnail . '" />';
                echo anchor($url, $img, array('title'=>$post->title));
            }
        ?&gt;

        &lt;?php
        
            $excerpt = get_excerpt($post->content);
            
            $continue = anchor($url, 'Continue reading &quot;' . $post->title . '&quot;', 'class="continue-reading"');
            $excerpt .= $continue;
            
        ?&gt;
        
        <p class="excerpt">
            &lt;?php echo $excerpt; ?&gt;
        </p>

Although it's probably not good MVC to have these functions in the view. I'll work on moving these to private functions within the controller and passing the results along with the post array to the view.

#4
[eluser]waynhall[/eluser]
Actually, I'll just keep them in the view, since I'd have to loop through all of them in the controller.

I improved the get_excerpt function to fall back on CI's word_limiter (text helper)
Code:
function get_excerpt($content) {        // Returns contents of the first <p> tag
        
        $start = stripos($content, '<p');
        
        if( ($start !== FALSE) && ($start < 200) ) {   // if reasonably close to top
            
            $p_open = strpos($content, '>', $start) + 1;
            $p_close = strpos($content, '</p>', $p_open);
            $length = $p_close - $p_open;
            
            if($length > 200) {    // if a reasonable size paragraph
                $p_contents = substr($content, $p_open, $length);
            } else {
                $p_contents = word_limiter(strip_tags($content));
            }
            
            return $p_contents;
        } else {
            
            $first_bit = word_limiter(strip_tags($content));
            return $first_bit;
        }
    }


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2020 MyBB Group.