Easy PHP Pagination

I’ve had a few pagination scripts over the years but I thought i’d share the one that i’m currently using as it’s a useful script to have in your toolbox. As a developer you’ll soon find a need to paginate data when displaying contents from the database, and rather than use JavaScript which could require all the data to be loaded into the page on load, we can use PHP to ensure that we’re only requesting the data that we need from the database. For those who have no clue what i’m talking about. Pagination is a way of splitting up data into manageable chunks to display to a user, if you’ve spent more than two minutes on the internet chances are you’ve come into contact with some form of pagination. as a simple example you can checkout my homepage, at the bottom you’ll see a list of page numbers allowing you to browse through pages of data, this script was originally written by the guys over at Stranger Studios and allows you to split data up with it being paginated across however many pages dynamically.

The Code

pagination

pagination

To start with you’ll see that we have our database connection file which we’re including into the page. Next you’ll see we’re setting three variables. ‘$tableName’, this refers to the table in your database that you want to get the data from, in our case it’s ‘countries_list’, ‘$targetpage’ refers to whatever you’ve saved the file as, in the case of the demo we’re saving the file as ‘index.php’. ‘$limit’ is the number of rows per page that we want to display from the database in the case of the demo you’ll see that we’re displaying just 10 rows.

Here are the main bullet points of what this file does in the simplest form.

  • Set the three variables at the top of the page declaring our database table, document filename, and number of results to display per page
  • Next we connect to the database and count the number of rows, so we know exactly how much data we’re dealing with
  • As the current page number is passed as a GET variable we check to see if a page number has been passed if there isn’t one then we set it to the first page
  • Then we have the query for the page content
  • Now we work out the next and previous page number as well as the last page number
  • Now we have a set of if statements, to determine which page the user is currently on relative to the total pages, so we can work out whether we need to display the first two page numbers with dots etc
  • Finally we echo ‘$paginate’ which will display our page numbers
  • Then we have our while loop which you can modify to suit your contents
<?php
	include('connect.php');	

	$tableName="countries_list";
	$targetpage = "index.php";
	$limit = 10; 

	$query = "SELECT COUNT(*) as num FROM $tableName";
	$total_pages = mysql_fetch_array(mysql_query($query));
	$total_pages = $total_pages[num];

	$stages = 3;
	$page = mysql_escape_string($_GET['page']);
	if($page){
		$start = ($page - 1) * $limit;
	}else{
		$start = 0;
		}	

    // Get page data
	$query1 = "SELECT * FROM $tableName LIMIT $start, $limit";
	$result = mysql_query($query1);

	// Initial page num setup
	if ($page == 0){$page = 1;}
	$prev = $page - 1;
	$next = $page + 1;
	$lastpage = ceil($total_pages/$limit);
	$LastPagem1 = $lastpage - 1;					

	$paginate = '';
	if($lastpage > 1)
	{	

		$paginate .= "<div class='paginate'>";
		// Previous
		if ($page > 1){
			$paginate.= "<a href='$targetpage?page=$prev'>previous</a>";
		}else{
			$paginate.= "<span class='disabled'>previous</span>";	}

		// Pages
		if ($lastpage < 7 + ($stages * 2))	// Not enough pages to breaking it up
		{
			for ($counter = 1; $counter <= $lastpage; $counter++)
			{
				if ($counter == $page){
					$paginate.= "<span class='current'>$counter</span>";
				}else{
					$paginate.= "<a href='$targetpage?page=$counter'>$counter</a>";}
			}
		}
		elseif($lastpage > 5 + ($stages * 2))	// Enough pages to hide a few?
		{
			// Beginning only hide later pages
			if($page < 1 + ($stages * 2))
			{
				for ($counter = 1; $counter < 4 + ($stages * 2); $counter++)
				{
					if ($counter == $page){
						$paginate.= "<span class='current'>$counter</span>";
					}else{
						$paginate.= "<a href='$targetpage?page=$counter'>$counter</a>";}
				}
				$paginate.= "...";
				$paginate.= "<a href='$targetpage?page=$LastPagem1'>$LastPagem1</a>";
				$paginate.= "<a href='$targetpage?page=$lastpage'>$lastpage</a>";
			}
			// Middle hide some front and some back
			elseif($lastpage - ($stages * 2) > $page && $page > ($stages * 2))
			{
				$paginate.= "<a href='$targetpage?page=1'>1</a>";
				$paginate.= "<a href='$targetpage?page=2'>2</a>";
				$paginate.= "...";
				for ($counter = $page - $stages; $counter <= $page + $stages; $counter++)
				{
					if ($counter == $page){
						$paginate.= "<span class='current'>$counter</span>";
					}else{
						$paginate.= "<a href='$targetpage?page=$counter'>$counter</a>";}
				}
				$paginate.= "...";
				$paginate.= "<a href='$targetpage?page=$LastPagem1'>$LastPagem1</a>";
				$paginate.= "<a href='$targetpage?page=$lastpage'>$lastpage</a>";
			}
			// End only hide early pages
			else
			{
				$paginate.= "<a href='$targetpage?page=1'>1</a>";
				$paginate.= "<a href='$targetpage?page=2'>2</a>";
				$paginate.= "...";
				for ($counter = $lastpage - (2 + ($stages * 2)); $counter <= $lastpage; $counter++)
				{
					if ($counter == $page){
						$paginate.= "<span class='current'>$counter</span>";
					}else{
						$paginate.= "<a href='$targetpage?page=$counter'>$counter</a>";}
				}
			}
		}

				// Next
		if ($page < $counter - 1){
			$paginate.= "<a href='$targetpage?page=$next'>next</a>";
		}else{
			$paginate.= "<span class='disabled'>next</span>";
			}

		$paginate.= "</div>";		

}
 echo $total_pages.' Results';
 // pagination
 echo $paginate;
?>

<ul>

<?php 

		while($row = mysql_fetch_array($result))
		{

		echo '<li>'.$row['country'].'</li>';

		}

	?>
</ul>

A bit of style

Here’s the css to style you pagination
.paginate {
font-family:Arial, Helvetica, sans-serif;
	padding: 3px;
	margin: 3px;
}

.paginate a {
	padding:2px 5px 2px 5px;
	margin:2px;
	border:1px solid #999;
	text-decoration:none;
	color: #666;
}
.paginate a:hover, .paginate a:active {
	border: 1px solid #999;
	color: #000;
}
.paginate span.current {
    margin: 2px;
	padding: 2px 5px 2px 5px;
		border: 1px solid #999;

		font-weight: bold;
		background-color: #999;
		color: #FFF;
	}
	.paginate span.disabled {
		padding:2px 5px 2px 5px;
		margin:2px;
		border:1px solid #eee;
		color:#DDD;
	}

	li{
		padding:4px;
		margin-bottom:3px;
		background-color:#FCC;
		list-style:none;}

	ul{margin:6px;
	padding:0px;}

Download:

Author: Ashley Ford

Prepare for PHP 6

As you may be aware the core PHP group of developers all met in Paris on November the 11th and 12th 2005. The minutes from the meeting are fascinating reading, but there is a lot to go through. So I’ve gone through all of the points raised and chewed them over from a developers point of view. Your comments as always are welcome.

Before I get started however I’d just like to make one thing very clear: what you read here (or in the original minutes) are in no way the ‘fully 100% decided’ end results / changes that we’ll see in PHP6. They will most likely all be discussed further (on internals and wider), but even so we can take the information presented in the minutes as being the PHP teams most ‘current’ way of thinking about any given subject.

Unicode

Unicode support at present can be set on a per request basis. This equates to PHP having to store both Unicode and non-Unicode variants of class, method and function names in the symbol tables. In short – it uses up more resources. Their decision is to make the Unicode setting server wide, not request wide. Turning Unicode off where not required can help performance and they quote some string functions as being up to 300% slower and whole applications 25% slower as a result. The decision to move it to the php.ini in my mind does take the control away from the user, and puts it into the hands of the Web Host.

If you compile PHP yourself or are responsible for this on your servers then you may be interested to know that PHP 6 will require the ICU libs (regardless if Unicode is turned on or off). The build system will bail out if the required ICU libs cannot be found. In a nutshell, you’ll have another thing to install if you want to compile PHP.

Register Globals to go

Say goodbye folks, this one is finally going. It will no longer be an ini file setting, and if found it will raise an E_CORE_ERROR, pointing you to the documentation on why it’s “bad”. This means that PHP6 will finally break all PHP3 era scripts (or any script using reg globals) with no recourse at all but to re-code it. That’s a bold move, but a needed one.

Magic Quotes to go

The magic quotes feature of PHP will be going, and as with register globals it’s going to raise an E_CORE_ERROR if the setting is found anywhere. This will affect magic_quotes, magic_quotes_sybase and magic_quotes_gpc.

Safe Mode to go

This may please developers who have web hosts that insist upon safe mode! But it will now go totally, again raising an E_CORE_ERROR if found. The reason is that apparently they felt it gave the ‘wrong signal’, implying that it made PHP secure, when infact it didn’t at all. open_basedir will (thankfully) be kept.

‘var’ to alias ‘public’

PHP4 used ‘var’ within classes. PHP5 (in its OO move) caused this to raise a warning under E_STRICT. This warning will be removed in PHP6 and instead ‘var’ will mean the same thing as ‘public’. This is a nice move but I if anyone has updated their scripts to work under E_STRICT in PHP5 it will be a redundant one for them.

Return by Reference will error

Both ‘$foo =& new StdClass()’ and ‘function &foo’ will now raise an E_STRICT error.

zend.ze1 compatbility mode to go

ze1 always tried to retain old PHP4 behaviour, but apparently it “doesn’t work 100%” anyway, so it will be removed totally and throw an E_CORE_ERROR if detected.

Freetype 1 and GD 1 support to go

Support for both of these (very very old) libs will be removed.

dl() moves to SAPI only

Each SAPI will register the use of this function as required, only the CLI and embed SAPIs will do this from now on. It will not be available elsewhere.

FastCGI always on

The FastCGI code will be cleaned up and always enabled for the CGI SAPI, it will not be able to be disabled.

Register Long Arrays to go

Remember the HTTP_*_VARS globals from yesteryear? Well if you’re not already using $_GET, $_POST, etc – start doing so now, because the option to enable long arrays is going (and will throw an E_CORE_ERROR).

Extension Movements

The XMLReader and XMLWriter extensions will move into the core distribution and will be on by default.

The ereg extension will move to PECL (and thus be removed from PHP). This means that PCRE will not be allowed to be disabled. This will make way for the new regular expression extension based on ICU.

The extremely useful Fileinfo exntesion will move into the core distribution and enabled by default.

PHP Engine Additions

64 bit integers
A new 64 bit integer will be added (int64). There will be no int32 (it is assumed unless you specify int64)

Goto
No ‘goto’ command will be added, but the break keyword will be extended with a static label – so you could do ‘break foo’ and it’ll jump to the label foo: in your code.

ifsetor()
It looks like we won’t be seeing this one, which is a shame. But instead the ?: operator will have the ‘middle parameter’ requirement dropped, which means you’d be able to do something like this: “$foo = $_GET['foo'] ?: 42;” (i.e. if foo is true, $foo will equal 42). This should save some code, but I personally don’t think it is as ‘readable’ as ifsetor would have been.

foreach multi-dim arrays
This is a nice change – you’ll be able to foreach through array lists, i.e. “foreach( $a as $k => list($a, $b))”.

{} vs []
You can currently use both {} and [] to access string indexes. But the {} notation will raise an E_STRICT in PHP5.1 and will be gone totally in PHP6. Also the [] version will gain substr and array_slice functionality directly – so you could do “[2,]” to access characters 2 to the end, etc. Very handy.

OO changes

Static Binding
A new keyword will be created to allow for late static binding – static::static2(), this will perform runtime evaluation of statics.

Namespaces
It looks like this one is still undecided – if they do implement namespaces it will be using their style only. My advice? Don’t hold your breath!

Type-hinted Return Values
Although they decided against allowing type-hinted properties (becaue it’s “not the PHP way”) they will add support for type-hinted return values, but have yet to decide on a syntax for this. Even so, it will be a nice addition.

Calling dynamic functions as static will E_FATAL
At the moment you can call both static and dynamic methods, whether they are static or not. Calling a dynamic function with the static call syntax will raise an E_FATAL.

Additions to PHP

APC to be in the core distribution
The opcode cache APC will be included in the core distribution of PHP as standard, it will not however be turned on by default (but having it there saves the compilation of yet another thing on your server, and web hosts are more likely to allow it to be enabled)

Hardened PHP patch
This patch implements a bunch of extra security checks in PHP. They went over it and the following changes will now take place within PHP: Protection against HTTP Response Splitting will be included. allow_url_fopen will be split into two: allow_url_fopen and allow_url_include. allow_url_fopen will be enabled by default. allow_url_include will be disabled by default.

E_STRICT merges into E_ALL
Wow, this is quite a serious one! E_STRICT level messages will be added to E_ALL by default. This shows a marked move by the PHP team to educate developers on ‘best practises’ and displaying language-level warnings in a “Hey, you’re doing it the wrong way”.

Farewell <%
They will remove support for the ASP style tags, but the PHP short-code tag will remain (<?) – so to those on php general who reckon the short-tag is ‘depreceated’ – hah! ;)

Conclusion

PHP6 is taking an interesting move in my mind – it’s as if the PHP developers want to now educate developers about the right way to code something, and remove those lingering issues with “Well you SHOULD be doing it this way, but you can still do it the old way”. This will not be the case any longer. Removing totally the likes of register globals, magic quotes, long arrays, {} string indexes and call-time-pass-by-references will force developers to clean up their code.

It will also break a crapload of scripts beyond repair that doesn’t involve some serious re-writing. Is this a bad thing? I don’t think so myself, but I see it making the adoption of PHP6 even slower than that of PHP5, which is a real shame. However they have to leap this hurdle at some point, and once they’ve done it progression to future versions should be swifter.

Read the full minutes here: http://www.php.net/~derick/meeting-notes.html

Author: Richard Davey

Mapping Using PHP

There are a number of great online GIS ( Geographic Information System ) solutions out there, ranging from Mappoint to Mapquest to some cool PHP projects. However, it is still nice to be able to be able plot you own data and put some basic mapping utilities on your site with a minimum of fuss and bother. Over the next couple of articles I will hopefully be able to give you a few pointers on how to create you own basic GIS system for free. I do not claim to be a GIS expert, and there may be better ways to do things, but hopefully these articles will give you a start in the right direction.

In this article we will start with the absolute basics – plotting a single location on a pre drawn map of the world. Later articles will go into drawing vector maps, drawing roads and rivers and labeling objects all using the principles in this article.

For this article you will need:

PHP with GD installed
A pair of scissors
An adult to help you

Finding your place in this world

To plot an object on any map, be it a house or a herd of caramelized Wombats, the object needs to be geocoded – that is have a map coordinate allocated to it. For all examples we used a standard longitude (long) and latitude (lat) coordinate. There a numerous other coordinate systems out there – some a lot more accurate, but this is the most common, the easiest to plot and suits our needs. The downside of directly plotting long/lat coordinates is that you will get distortion as you near the poles. However, for our uses this doesn’t pose a problem.

The two coordinates of a longitude and latitude refer to the angle in degrees from the equatorial plane of the earth, both up and down. Longitude lines extend from pole to pole giving us an “X” coordinate, Latitude lines give us the “Y” coordinate. These can either be written as a decimal value ( ie 23.323232 ) or as degrees, minutes and seconds ( D’M'S ). For storing our coordinates we used the decimal version as it’s a lot easier and saves a lot of processing time. There are a number of sites with Javascript utilities which will convert coordinates from D’M'S ( degrees, minutes and seconds ) to the decimal format. I happen to use a Sharp EL-546 scientific calculator which has the function built in.

There are a number of ways to finding the long/lat of a point in the world, however a quick and easy way is to used Microsofts online GIS service Mappoint ( www.mappoint.com ). Find your location using Mappoint search utilities and make sure it is in the center of the map. Right mouse click on the map, and you will find long/lat coordinates embedded in the URL of the map image. It is also worth looking at www.geogratis.com, plus a number of government operated environmental sites will have map data which you can download for free. Those of you who have Mapinfo will also find very useful geocoded data on the sample discs which come with it.

The point we are plotting for this article is my  current location which is Chennai – Tamil Nadu – India.

Longitude: 80.24963
Latitude: 13.06042

We now need a base map to plot our point on. In future articles we will generate this ourselves, however to start we will use a simple pre drawn JPG file. The base map we are using is called earth_310.jpg, and is and view of the earth in what is called a Cylindrical projection.

World Map

World Map

The original of this image can be found in various forms all over the web in various sizes and scales. A cylindrical projection is the simplest projection to plot long/lat coordinates onto, again with a minimum of conversion needed reducing processor overhead. For our purposes you can simply right click the image and “Save picture as …” to your hard drive.

The base map is scaled to 310×155 for ease of use, but you can rescale this map to any size.

We are now ready to generate the code to plot our point.

Plots and schemes

The basic steps for generating the map are:

Load the background map.
Convert and scale the long/lat coordinates to screen coordinates.
Plot the point.
Return the finished map as an image.

To convert the long/lat to screen coordinate we have a created a function called getlocationcoords. This takes the longitude and latitude coordinates plus the size of the base map and return the screen coordinates in an associative array. $width and $height are calculated from the size of the background image. In future projects these variables are used scale the map and set the zoom level.

<?php
function getlocationcoords($lat, $lon, $width, $height)
{
$x = (($lon + 180) * ($width / 360));
$y = ((($lat * -1) + 90) * ($height / 180));
return array(“x”=>round($x),”y”=>round($y));
}
?>

Once the coordinates have been converted it’s as simple as drawing a rectangle on the base map using the returned array to mark our location.

So, the code to create the map:

<?php

// These are the coordinates the location we wish to plot.
// These are being passed in the URL, but we will set them to a default if nothing is passed.

if(empty($long))$long = 80.24963;
if(empty($lat)) $lat = 13.06042;

// First we load the background/base map. We assume it’s located in same dir as the script.
// This can be any format but we are using JPG in this example
// We will also allocate the color for the marker

$im = imagecreatefromjpeg(“earth_310.jpg”);
$red = imagecolorallocate ($im, 255,0,0);

// Next need to find the base image size.
// We need these variables to be able scale the long/lat coordinates.

$scale_x = imagesx($im);
$scale_y = imagesy($im);

// Now we convert the long/lat coordinates into screen coordinates

$pt = getlocationcoords($lat, $long, $scale_x, $scale_y);

// Now mark the point on the map using a red 4 pixel rectangle

imagefilledrectangle($im,$pt["x"]-2,$pt["y"]-2,$pt["x"]+2,$pt["y"]+2,$red);

// Return the map image. We are using a PNG format as it gives better final image quality than a JPG

header (“Content-type: image/png”);
imagepng($im);
imagedestroy($im);

?>

To load the map call the PHP code from an IMG tag, passing the longitude and latitude in the long and lat variables:

<IMG SRC=”map_code.php?long=long&lat=lat“>

Chennai - Tamil Nadu - India

Chennai - Tamil Nadu - India

You could easily modify this code to read long/lat coordinates from a database or a delimited text file and plot multiple points.

Summary

This is a very basic script. However the basic principle will allow you to draw very complicated maps.

The important part is the getlocationcoords function – once you have geocoded your data and have the routines to plot the points on the screen, the sky’s the limit!

Author: Simon Moss

Solve PHP Fatal error: Allowed memory size of 8388608 bytes exhausted (tried…

This error message can spring up in a previously functional PHP script when the memory requirements exceed the default 8MB limit. Don’t fret, though, because this is an easy problem to overcome.

To change the memory limit for one specific script by including a line such as this at the top of the script:

ini_set(“memory_limit”,”12M”);

The 12M sets the limit to 12 megabytes (12582912 bytes). If this doesn’t work, keep increasing the memory limit until your script fits or your server squeals for mercy.

You can also make this change permanently for all PHP scripts running on the server by adding a line like this to the server’s php.ini file:

memory_limit = 12M

Keep in mind that a huge memory limit is a poor substitute for good coding. A poorly written script may inefficiently squander memory which can cause severe problems for frequently executed scripts. However, some applications are run infrequently and require lots of memory like importing and processing a big data file.

Still if you have problem, then delete the cache file or write a condition to delete the cache file, when the size exceed max memory limit.

Author: Rex

Determine Whether JavaScript Is Enabled/Disabled Via PHP

Recently i was working on a project where there is a need to determine whether JavaScript is enabled or was disabled by the user. Depending whether the JavaScript is enable or not, the system will rely on JavaScript operation if it does and PHP operation if it doesn’t. The fundamental solution to this is to detect whether JavaScript is enable before the system can determine which approach can be used. However, there is no easy solution to determine whether a client scripting is enable in a server scripting language (PHP) without finish loading the page! Therefore, in this article we will discuss whether there is such possibility to use PHP to determine whether JavaScript is enabled for your web application.

The Problem

The main problem is that a server script language can never be able to determine whether a client script language is available as the server script language will always run first. Furthermore, the client script is always run on the client side and never executed on the server side. Therefore, when the server scripting is running at the server side and send to the client for display, the server scripting language will have no idea what is going on with the client environment. Hence, strictly speaking will be unable to determine JavaScript is enable or disable.

The Solution

Although it sounds impossible for server side to determine whether a client scripting is available such as JavaScript but certain tricks can be perform in order to achieve this. However, it won’t be a convenient one. Recall that every web system should have a redirect index.php page to prevent our code from showing in plaintext if anything happen? We can use that page to determine whether javascript is enable by writing a script to either append a value and post over to the next page or a better alternative is to store it into the user cookie. If you store a value and post it to the next page, the validation can only occur within the main page. However, if you utilize cookie to determine whether JavaScript is available, you can always use php to determine whether that cookie value is available. If it is not available (they delete their browser cookie on the way) you can redirect that user to the index.php to revalidate JavaScript is enable. Once it is being verify, you will just show a message to the user after index.php has redirect or run on pure php.

On the index.php script, it will be something like this,

01.<script type='javascript/text'>
02.function createCookie(name,value,days) {
03. if (days) {
04. var date = new Date();
05. date.setTime(date.getTime()+(days*24*60*60*1000));
06. var expires = "; expires="+date.toGMTString();
07. }
08. else var expires = "";
09. document.cookie = name+"="+value+expires+"; path=/";
10.}
11.createCookie('verify_cookie', 'Y', 1);
12.</script>
13.<meta http-equiv="refresh" content="2;url=main.php?c=1">

We have a function that help us to create a cookie if JavaScript available. Once this is done, we redirect the user to main.php where our real page is located with a get value of c=1. This value is needed to avoid recursive request. We can’t use PHP header function because it will redirect before JavaScript has the opportunity to run and the code should be placed before the head tag to make this valid. On all other pages we will have something like this before the header.

01.<?php
02. //filter the global variable first.
03. if(!isset($_COOKIE['verify_cookie']) && $_GET['c'] == 1){
04. echo 'JavaScript is disable';
05. }else if(!isset($_COOKIE['verify_cookie'])){
06. //perform check to determine whether the cookie expire OR it really was disabled.
07. header('location: index.php');
08. }else{
09. //perform another check on javascript similar to index.php if you afraid that the cookie exist but javascript was disabled.
10. }
11.?>

The above is to verify whether javascript exist in each page and use to run either pure php or combination with JavaScript as these script can be imported using PHP if needed. The solution above can be use as a references and not necessary a solid solution.

Alternative Solution

The alternative solution to this is to use the noscript tag which is very simple and make your life a better place to live in.

1.<script>
2.document.getElementsByTagName('body')[0].innerHTML = 'JavaScript is enable.';
3.<script>
4.<noscript>
5.JavaScript is disabled.
6.<noscript>

Conclusion

Many will turn to noscript tag that can really ease and simplify the way we code. However, for some system which required to determine whether script is enabled for different server script to run. This might help those that are doing such approach as noscript tag will only run after the server has processed its information. On the other hand, you can combine this approach with the no tag approach to better validate your logic.

Author: Clay Lua

« Older entries