tags:

views:

49

answers:

3

The code below is resulting in an error on a site in which there are ~ 1500 posts. It performs fine when post count is nominal, however, this heavy load is exposing the weakness of the code and I'd like to optimize it.

Interestingly, when I disable this menu and instead use the "Recent Posts" widget, the posts are drawn fine. So I'd probably do good to borrow from that code if I knew where to find it, or better yet, If I could call the widget directly in my theme, passing it a post count variable.

Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 16384 bytes) in /home1/est/public_html/mysite/wp-includes/post.php on line 3462

The code is below. Its purpose is to list "recent posts".

global $post; 
$cat=get_cat_ID('myMenu'); 
$cathidePost=get_cat_ID('hidePost'); 
$myrecentposts = get_posts(array('post_not_in' => get_option('sticky_posts'), 'cat' => "-$cat,-$cathidePost",'showposts' => $count-of-posts));
$myrecentposts2 = get_posts(array('post_not_in' => get_option('sticky_posts'), 'cat' => "-$cat,-$cathidePost",'showposts' => -1));
$myrecentpostscount = count($myrecentposts2);

if ($myrecentpostscount > 0) 
{ ?>
    <div class="recentPosts"><h4><?php if ($myHeading !=="") { echo $myHeading; } else { echo "Recent Posts";} ?></h4><ul>
    <?php 
    $current_page_recent = get_post( $current_page );
    foreach($myrecentposts as  $idxrecent=>$post) {
        if($post->ID == $current_page_recent->ID)
            {
                $home_menu_recent = ' class="current_page_item';
            } 
            else 
            {
                $home_menu_recent = ' class="page_item';
            }
            $myclassrecent = ($idxrecent == count($myrecentposts) - 1 ? $home_menu_recent.' last"' : $home_menu_recent.'"'); 
        ?>
    <li<?php echo $myclassrecent ?>><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
    <?php } ; if (($myrecentpostscount > $count-of-posts) && $count-of-posts > -1){ ?><li><a href="<?php bloginfo('url'); ?>/recent">View All Posts</a></li><?php } ?></ul></div>
+3  A: 

Don't take this the wrong way. I'm not going to solve your memory problem at all in this answer. I will post another answer with a reason I believe you could have the mem problem The following is just a suggestion I hope you take as helpful: You have so much html jumbled in between your layout logic it is going to take you 3x as long to do figure out what is breaking and why.

Following the principles of refactoring I'm going to give one example and show how you can clean this up to the point where you can actually debug it yourself.

I'm taking this section of code to refactor a bit:

if ($myrecentpostscount > 0) 
{ ?>
    <div class="recentPosts"><h4><?php if ($myHeading !=="") { echo $myHeading; } else `{ echo "Recent Posts";} ?></h4><ul>`

First, pull the logic out of the template display (reformat for readability at the same time:

if ($myrecentpostscount > 0)
{
    if ($myHeading !=="") 
    {
        $displayHeading =  $myHeading; 
    } 
    else 
    { 
        $displayHeading =  "Recent Posts";
    }

?>

Second, replace temporary variables with function calls [$myHeading]

/**
* This function determines if a heading is null, and returns the default if it is.
*/
function getDisplayHeading($customHeading)
{
    if ($customHeading == "") 
    { 
        return "Recent Posts";
    }
    return $customHeading;
}   

if ($myrecentpostscount > 0)
{
    ?>
    <div class="recentPosts"><h4>
    <?php echo getDisplayHeading($myHeading); ?></h4><ul>

Now finally, when you have all your logic at the top of the page, you can profile each function to see how much memory it uses and at which point too much memory is used in your page request. I'm going to post another answer to try to help there though, because I believe I have an idea.

Zak
Great teaching example. Thanks for taking the time Zak.
Scott B
+1  A: 

When you see the Allowed memory size of exhausted, is usually means that you have an endless loop on your hands. Check to make sure there are parameters to stop it from looping forever.

tylerpenney
+1  A: 

In your code, you do the following thing:

$myrecentposts = get_posts(array('post_not_in' => get_option('sticky_posts'), 'cat' => "-$cat,-$cathidePost",'showposts' => $count-of-posts));
$myrecentposts2 = get_posts(array('post_not_in' => get_option('sticky_posts'), 'cat' => "-$cat,-$cathidePost",'showposts' => -1));
$myrecentpostscount = count($myrecentposts2);

You are actually fetching all of the posts, then counting them in code... I don't have the source of the "get_posts" function, but I would bet about 10 bucks that if you create a new function called "get_post_count" that doesn't fetch all the posts into the page, but rather does something like a "select count(*)" and gives you 1 result, you will eliminate your memory prob. If you post the body of your get_posts function we can probably help determine the easiest way to make a get_post_count function.

Zak
Thanks Zak. I appreciate the help.
Scott B
Zak, I'm going to refactor the code as an example in learning, but I just realized that I can simply pull the "Recent Posts" widget from WordPress and insert it into my template where my spaghetti code currently resides :) The only thing I'm missing is a means to highlight the current_page_item (as I've done in my custom code here).
Scott B
@Zak > The get_posts() function is a built-in WP function inside the core. I'll search in posts.php and update the question with the code, then perhaps someone can help with the get_post_count function...
Scott B
sounds good. If you have/can find the wordpress source, it should be easy enough to create another similar function that just gives the count back.
Zak