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

Advertisements

MySQL Stored Procedures

What are Stored Procedures

MySQL 5.0 finally introduces functionality for Stored Procedures. So what exactly are stored procedures? That is the kind of question that gets database professionals who use other DBMS’s raising their eyebrows. Stored procedures have been integral to Oracle, PostgreSQL, DB-2, MS-SQL server and others for years, and it has long been a sore point that MySQL has not had them. But there is no snobbery here – if you are a MySQL newbie, or have been using MySQL for years and want to find out what all the fuss is about, read on. If it is your eyebrows that are raised, and you just want to know how MySQL implements them, you will be relieved to know MySQL stored procedures are very similar to the DB2 implementation, as both are based on the SQL:2003 standard.

A stored procedure is simply a procedure that is stored on the database server. MySQL developers have to date unthinkingly written and stored their procedures on the application (or web) server, mainly because there hasn’t been an option. That has been limiting. Some have claimed that there are two schools of thought – one claiming that logic should be in the application, the other saying it should reside in the database. However, most professionals would not bind themselves to one or other viewpoint at all times. As always, there are times when doing either makes sense. Unfortunately, some of the staunchest adherents of the in the application school are only there because until now they have had no choice, and it is what they are used to doing. So why would we want to place logic on the database server?Why use stored procedures?
They will run in all environments, and there is no need to recreate the logic. Since they are on the database server, it makes no difference what application environment is used – the stored procedure remains consistent. If your setup involves different clients, different programming languages – the logic remains in one place. Web developers typically make less use of this feature, since the web server and database server are usually closely linked. However, in complex client-server setups, this is a big advantage. The clients are automatically always in sync with the procedure logic as soon as its been updated.
They can reduce network traffic. Complex, repetitive tasks may require getting results, applying some logic to them, and using this to get more results. If this only has to be done on the database server, there is no need to send result sets and new queries back and forth from application server to database server. Network traffic is a common bottleneck causing performance issues, and stored procedures can help reduce this. More often though, it is the database server itself that is the bottleneck, so this may not be much of an advantage.
A simple example

A stored procedure is simply some SQL statements. Almost any valid SQL can go inside a stored procedure, with a few exceptions, which we will look at, at a later date. Let’s set up a basic stored procedure first. This one will simply say ‘Hello’ in the Xhosa language – Molo.
mysql> CREATE PROCEDURE molo() SELECT ‘Molo’;
Query OK, 0 rows affected (0.00 sec)

It is as simple as that. And to call it:
mysql> CALL molo()\G
*************************** 1. row ***************************
Molo: Molo
1 row in set (0.00 sec)

Hardly useful, but the basics are there. CREATE PROCEDURE sp_name() will define the procedure, and CALL sp_name() will call the procedure.
Parameters

The real benefit of a stored procedure is of course when you can pass values to it, as well as receive values back. The concept of parameters should be familiar to anyone who has had experience with any procedural programming experience.

There are three types of parameter:
IN: The default. This parameter is passed to the procedure, and can change inside the procedure, but remains unchanged outside.
OUT: No value is supplied to the procedure (it is assumed to be NULL), but it can be modified inside the procedure, and is available outside the procedure.
INOUT: The characteristics of both IN and OUT parameters. A value can be passed to the procedure, modified there as well as passed back again.

Mastery of stored procedures does require knowledge of session variables. Most of you probably know how to use session variables already, but if not, the concept is simple. You can assign a value to a variable, and retrieve it later. Here is an example, setting the variable x to the Xhosa word for hello to a group of people.
mysql> SET @x=’Molweni’;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @x\G
*************************** 1. row ***************************
@x: Molweni
1 row in set (0.00 sec)
An IN example

Here is an example of a stored procedure demonstrating the use of an IN parameter. Since IN is the default, there is no need to specify the parameter as such.
mysql> CREATE PROCEDURE sp_in(p VARCHAR(10)) SET @x = P;
Query OK, 0 rows affected (0.00 sec)

mysql> CALL sp_in(‘Molo’);
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @x\G
*************************** 1. row ***************************
@x: Molo
1 row in set (0.00 sec)

The session variable @x is set inside of the procedure, based upon the parameter P, which is passed to the procedure, and remains unchanged.
An OUT example
mysql> SET @x=’Molweni’;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE PROCEDURE sp_out(OUT p VARCHAR(10)) SET P=’molo’;
Query OK, 0 rows affected (0.00 sec)

mysql> CALL sp_out(@x);
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @x\G
*************************** 1. row ***************************
@x: molo
1 row in set (0.00 sec)

We reset @x just to make sure the final result is not a legacy of the previous procedure. This time, the parameter P is changed inside of the procedure, while the session variable is passed to the procedure, ready to receive the result.
An INOUT example
mysql> CREATE PROCEDURE sp_inout(INOUT P INT) SET @x=P*2;
Query OK, 0 rows affected (0.00 sec)

mysql> CALL sp_inout(2);
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @x\G
*************************** 1. row ***************************
@x: 4
1 row in set (0.00 sec)

Here, a parameter is passed to the procedure, used in the calculation, and the results are made available to the session variable @x.

Getting information about existing stored procedures

It is clearly necessary to be able to get more information about any stored procedures later, such as a list of procedures available, and the definitions. There are MySQL-specific ways to do this, and the syntax should be familiar to experienced MySQL users. SHOW PROCEDURE STATUS returns a list of stored procedures, and some metadata about them, while SHOW CREATE PROCEDURE returns the definition of a particular procedure.
mysql> SHOW PROCEDURE STATUS\G
************* 1. row ************
Db: test
Name: molo
Type: PROCEDURE
Definer: ian@localhost
Modified: 2005-07-29 19:20:27
Created: 2005-07-29 19:20:27
Security_type: DEFINER
Comment:
************* 2. row ************
Db: test
Name: sp_in
Type: PROCEDURE
Definer: ian@localhost
Modified: 2005-08-02 11:58:34
Created: 2005-08-02 11:58:34
Security_type: DEFINER
Comment:
************* 3. row ************
Db: test
Name: sp_inout
Type: PROCEDURE
Definer: ian@localhost
Modified: 2005-08-02 12:16:18
Created: 2005-08-02 12:16:18
Security_type: DEFINER
Comment:
************* 4. row ************
Db: test
Name: sp_out
Type: PROCEDURE
Definer: ian@localhost
Modified: 2005-08-02 12:01:56
Created: 2005-08-02 12:01:56
Security_type: DEFINER
Comment:
4 rows in set (0.00 sec)

It will become clear what all these fields mean as we progress through the rest of this tutorial series.
mysql> SHOW CREATE PROCEDURE molo\G
*************************** 1. row ***************************
Procedure: molo
sql_mode:
Create Procedure: CREATE PROCEDURE ‘test’.’molo'()
SELECT ‘Molo’
1 row in set (0.00 sec)

There is also an ANSI-standard way of doing it, which will be more familiar to other users.
mysql> SELECT * FROM INFORMATION_SCHEMA.ROUTINES\G
*************************** 1. row ***************************
SPECIFIC_NAME: molo
ROUTINE_CATALOG: NULL
ROUTINE_SCHEMA: test
ROUTINE_NAME: molo
ROUTINE_TYPE: PROCEDURE
DTD_IDENTIFIER:
ROUTINE_BODY: SQL
ROUTINE_DEFINITION: SELECT ‘Molo’
EXTERNAL_NAME: NULL
EXTERNAL_LANGUAGE: NULL
PARAMETER_STYLE:
IS_DETERMINISTIC: NO
SQL_DATA_ACCESS: CONTAINS_SQL
SQL_PATH: NULL
SECURITY_TYPE: DEFINER
CREATED: 2005-07-29 19:20:27
LAST_ALTERED: 2005-07-29 19:20:27
SQL_MODE:
ROUTINE_COMMENT:
DEFINER: ian@localhost
*************************** 2. row ***************************
SPECIFIC_NAME: sp_in
ROUTINE_CATALOG: NULL
ROUTINE_SCHEMA: test
ROUTINE_NAME: sp_in
ROUTINE_TYPE: PROCEDURE
DTD_IDENTIFIER:
ROUTINE_BODY: SQL
ROUTINE_DEFINITION: SET @x = P
EXTERNAL_NAME: NULL
EXTERNAL_LANGUAGE: NULL
PARAMETER_STYLE:
IS_DETERMINISTIC: NO
SQL_DATA_ACCESS: CONTAINS_SQL
SQL_PATH: NULL
SECURITY_TYPE: DEFINER
CREATED: 2005-08-02 11:58:34
LAST_ALTERED: 2005-08-02 11:58:34
SQL_MODE:
ROUTINE_COMMENT:
DEFINER: ian@localhost
*************************** 3. row ***************************
SPECIFIC_NAME: sp_inout
ROUTINE_CATALOG: NULL
ROUTINE_SCHEMA: test
ROUTINE_NAME: sp_inout
ROUTINE_TYPE: PROCEDURE
DTD_IDENTIFIER:
ROUTINE_BODY: SQL
ROUTINE_DEFINITION: SET @x=P*2
EXTERNAL_NAME: NULL
EXTERNAL_LANGUAGE: NULL
PARAMETER_STYLE:
IS_DETERMINISTIC: NO
SQL_DATA_ACCESS: CONTAINS_SQL
SQL_PATH: NULL
SECURITY_TYPE: DEFINER
CREATED: 2005-08-02 12:16:18
LAST_ALTERED: 2005-08-02 12:16:18
SQL_MODE:
ROUTINE_COMMENT:
DEFINER: ian@localhost
*************************** 4. row ***************************
SPECIFIC_NAME: sp_out
ROUTINE_CATALOG: NULL
ROUTINE_SCHEMA: test
ROUTINE_NAME: sp_out
ROUTINE_TYPE: PROCEDURE
DTD_IDENTIFIER:
ROUTINE_BODY: SQL
ROUTINE_DEFINITION: SET P=’molo’
EXTERNAL_NAME: NULL
EXTERNAL_LANGUAGE: NULL
PARAMETER_STYLE:
IS_DETERMINISTIC: NO
SQL_DATA_ACCESS: CONTAINS_SQL
SQL_PATH: NULL
SECURITY_TYPE: DEFINER
CREATED: 2005-08-02 12:01:56
LAST_ALTERED: 2005-08-02 12:01:56
SQL_MODE:
ROUTINE_COMMENT:
DEFINER: ian@localhost
4 rows in set (0.01 sec)

Let’s introduce some more complex examples. First, we will create a sample table.

mysql> CREATE table sp1 (id INT, txt VARCHAR(10), PRIMARY KEY(id));
Query OK, 0 rows affected (0.11 sec)

Delimiters, and multi-statement procedures

Stored procedures of course are not that useful if they are just one statement. The effects of all the procedures we have looked at so far could have had been duplicated much more easily with a single SQL statement. Useful procedures are much longer than that. Those of you who are on the ball may be thinking of a complication. How can we differentiate between multiple statements inside the procedure, and the end of the procedure? We have to create a different delimiter to end the CREATE PROCEDURE statement. Here is how:
mysql> DELIMITER |

Note that there is no semicolon after the ‘|’ symbol, which we will use as the delimiter for our purposes. You have to choose a delimiter that does not appear in your procedure, and it can be more than one character.

mysql> CREATE PROCEDURE sp_ins (P VARCHAR(10))
-> BEGIN
-> SET @x=CHAR_LENGTH(P);
-> SET @y = HEX(P);
-> INSERT INTO sp1(id,txt) VALUES(@x,@y);
-> END|

Query OK, 0 rows affected (0.05 sec)

mysql> CALL sp_ins(‘ABC’);
-> |

Query OK, 1 row affected (0.00 sec)

mysql> DELIMITER ;
mysql> SELECT * FROM sp1\G

*************************** 1. row ***************************
id: 3
txt: 414243
1 row in set (0.00 sec)

Note what happened when we tried to call the procedure. Because MySQL was still using the | symbol as a delimiter, and not the semicolon, the statement did not run after the semicolon. We first needed to close it with the piping symbol. Afterwards, we reset the delimiter back to normal, and test that the records were correctly added to the sp1 table.
Procedure variables

Stored procedures do not only make use of the standard SQL statements. You can also DECLARE variables that exist only inside the procedure, as well as assign values to them with the SET statement without using the ‘@’ symbol, required for session variables. Here is an example.
mysql> DELIMITER |
mysql> CREATE PROCEDURE sp_declare (P INT)
-> BEGIN
-> DECLARE x INT;
-> DECLARE y INT DEFAULT 10;
-> SET x = P*y;
-> INSERT INTO sp1(id,txt) VALUES(x,HEX(‘DEF’));
-> END|

Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;
mysql> CALL sp_declare(4);

Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM sp1\G
*************************** 1. row ***************************
id: 3
txt: 414243
*************************** 2. row ***************************
id: 40
txt: 444546
2 rows in set (0.00 sec)

Variables that are declared without a default, such as x above, are set to NULL.
Populating variables from a pre-existing table

Now that you have seen how to INSERT records into a table from within a procedure, you may be wondering how we get values out of an existing table. Here is a simple example.
mysql> DELIMITER |
mysql> CREATE PROCEDURE sp_select ()
-> BEGIN
-> DECLARE x INT;
-> DECLARE y VARCHAR(10);
-> SELECT id,txt INTO x,y FROM sp1 LIMIT 1;
-> SELECT x,y;
-> END|

Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;
mysql> CALL sp_select()\G

*************************** 1. row ***************************
x: 3
y: 414243
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Author: Ian Gilfillan

input[type=submit] css not working in IE6

<style type="text/css">
form input[type=submit]{
background-color:#FE9900;
font-weight:bold;
font-family:Arial,Helvetica,sans-serif;
border:1px solid #000066;
}
</style>

the above code wont work in IE6, either i cant put class or id in it.

The Internet Explorer 6 doesn’t support the attribute selector
[attr="value"]. 

So there is no way to address that submit input element with CSS only 
(IE 6 doesn’t support the adjacence selector + and :last-of-type selector 
neither that would help in this case).

So the only options you have is to either make that element uniquely addressable
by adding a class or ID or wrapping it into an additional span element.

Or – use JavaScript to select that element and apply the CSS rule to it. 
jQuery can make this fairly easy:

$("form input[type=submit]").css({
    "background-color": "#FE9900",
    "font-weight": "bold",
    "font-family": "Arial,Helvetica,sans-serif",
    "border": "1px solid #000066"
});

or another way you can call is using javascript,

Let’s just change our HTML to this.


<input type="text" class="text" value="" />
<input type="button" class="button" value="I am a button" />
<input type="submit" class="button" value="I am a submit" />

Then have the complimenting CSS:


input.text { /* my text css */ }
input.button { /* my button css */ }

Simple enough… but I’m still not satisifed. I’m thinking to myself, What a hassle. Who really wants to append all those classes.

Javascript will do it for you

Need I say more….

A plus i added to the code is that instead of hardcoding in text strings the types,

you the type assign as the class for each element, like:

window.onload = function()
{
var coll = document.getElementsByTagName(”input”);
for(var i=0; i<coll.length; i++)
{
if(coll[i].type)
{
coll[i].className += ‘ ‘ + coll[i].type + ‘ ‘;
}
}
}

This way, all inputs are assigned classes with their own names 
(without overwriting any additional classes the input might have)

Author: Gumbo and Ded

The Internet Explorer 6 doesn’t support the attribute selector [attr="value"]. So there is no way to address that submit input element with CSS only (IE 6 doesn’t support the adjacence selector + and :last-of-type selector neither that would help in this case).

So the only options you have is to either make that element uniquely addressable by adding a class or ID or wrapping it into an additional span element.

Or – as you’ve already stated that you can’t do that – use JavaScript to select that element and apply the CSS rule to it. jQuery can make this fairly easy:

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 ( http://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 http://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