0

I am getting the error

PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 33292313 bytes)

when i am running my pagination function and i don't know what is happening and/or why i'm getting the error.

From what i've seen on the other questions here, most people recommend that i change the memory limit in the php.ini file.However, i would like to know why this error is happening and what i can do to prevent it form happening in the future.

From this question Meaning of "Fatal error: Allowed memory size of x bytes exhausted (tried to allocate y bytes)"? i can see that the php script has exceeded the allocated memory limit (duh!) but it isn't really helpful.

Question:

  • Isn't php simply a language that interacts with a database? Why then does it need memory to run?
  • What causes the error?(i know that there isn't enough memory, but why is there so much memory used up)
  • What can i do to prevent it from happening again

My Pagination function:

function Pagination( $connection, $num, $page, $view  ) {

    $view=$view;

    //Results per page
    $pagerows=10;

    //Tells us the last page number
    $last=ceil( $num/$pagerows );

    // Establish the $PaginationNav variable(used to navigate the paginated results)
    $PaginationNav = '';

    //Check how many pages of results there are
    //If there is more than 1 page
    if( $last != 1 ) {

        //Check if we are on page 1, if so we don't need the 'previous' link
        //We are on page one
        if( $page == 1 ) {

            //Adds the current page
            $PaginationNav .= $page;

            //Adds the next 3 pages to the pagination
            for( $i=$page+1;$i<$last;$i++ ) {
                $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$i\">$i</a>";
                if( $i > $page+4 ) {
                    break;
                }
            }

            $PaginationNav .= "...";

            //Adds the last page to the pagination
            $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$last\">$last</a>";

            //Adds the next page button
            $next=$page + 1;

            $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$next\">Next </a> ";
        } else {
            //we are not on page 1

            //Adds the previous button to pagination
            $previous=$page - 1;

            $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$previous\">Previous</a>";

            //Adds the current page
            $PaginationNav .=$page;

            //Adds the left navigations
            for( $i = $page-4;$i=$page;$i++ ) {
                if( $i>0 ) {
                    $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$i\">$i</a>";
                }
            }

            //Adds the right navigations
            for( $i=$page;$i<$last;$i++ ) {
                $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$i\">$i</a>";
                if( $i > $page+4 ) {
                    break;
                }
            }

            //Adds the last page to the pagination
            $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$last\">... $last</a>";

            //Adds the next page button
            $next=$page + 1;

            $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$next\">Next </a> ";
        }
    }

    //There is only one page
    if( $last == 1 ) {
        $PaginationNav .= $page;
    }

    return $PaginationNav;
}

There was a comment on one of the question i've seen that states that simply increasing the memory limit isn't a good substitute for good coding. I agree, and i would like to change that code to be better instead of simply mindlessly increasing memory.

P.S I've no formal training in programming, and am learning simply by throwing myself into coding, so i apologise if the answer is pretty obvious.

Community
  • 1
  • 1
Kenneth .J
  • 1,433
  • 8
  • 27
  • 49

2 Answers2

3

you have:

 for($i = $page-4;$i=$page;$i++)   // change to ==
 {
     if($i>0)
     {
         $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$i\">$i</a>";
     }
 }

you are assigning $page to $i in $i=$page and it will return $page (probably a positive number) every time, which will result in true condition. Change it to ==

galchen
  • 5,252
  • 3
  • 29
  • 43
1

As galchen caught, you had an incorrect for loop terminator, causing an infinite loop that was finally broken by running out of memory. Increasing the memory limit would not have fixed this problem.

I'd like to offer my rewrite of your Pagination function. I haven't tested it, but I believe it will produce more consistent results overall.

function Pagination($connection,$num,$page,$view,$pagerows=10) {
    //Tells us the last page number
    $last = ceil($num/$pagerows);
    if( $last == 1) return $page;

    // Establish the $PaginationNav variable(used to navigate the paginated results)
    $PaginationNav = '';

    // Helper function to reduce repeated code - great if you want to change the link!
    $addpage = function($p,$custom="") use (&$PaginationNav) {
        $PaginationNav .= "<a class='Pagination' href='".$_SERVER['PHP_SELF']."?view=".$view."&page=".$i.">".($custom ? $custom : $i)."</a>";
    };

    //Check if we are on page 1, if so we don't need the 'previous' link
    if( $page != 1) {
        //Adds the previous button to pagination
        $addpage($page-1,"Previous");
    }
    if( $page > 4) {
        //Adds the first page to the pagination
        $addpage(1);
        $PaginationNav .= "...";
    }
    //Adds the left navigations
    for($i = max(1,$page-4); $i < $page; $i++) {
        $addpage($i);
    }
    //Adds the current page
    $PaginationNav .= $page;
    //Adds the right navigations
    for($i=$page; $i<$last && $i < $page+4; $i++) {
        $addpage($i);
    }
    if( $page < $last-4) {
        $PaginationNav .= "...";
        //Adds the last page to the pagination
        $addpage($last);
    }
    if( $page != $last) {
        //Adds the next page button
        $addpage($page+1,"Next");
    }
    return $PaginationNav;
}
Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • Hi Niet, i've had a look, specifically at the addpage helper function and there were a few parts i didn't understand, specifically the pass by reference, the use keyword(closure) and the ternary operator at the end of the function. From what i read here on SO after a google search, people seem to be recommend NOT using pass by reference and instead pass by value(i.e return $PaginationNav after calling the addpage function).If so, what are the benefits of using it in your example?Also, whats the use of the 'use' keyword and the ternary operator at the end? – Kenneth .J Dec 24 '13 at 13:06
  • If you don't pass by reference, you'd have to do `$PaginationNav .= $addpage(1);` everywhere else. This makes it simpler, in my opinion. The ternary operator is to use the `$custom` text (for Next and Previous) or the number if no custom text is given. – Niet the Dark Absol Dec 24 '13 at 13:11