Quantcast
Channel: PHP Starter » Andrew
Viewing all articles
Browse latest Browse all 10

Separating the Application & Presentation and Alternative Syntax

$
0
0

One of the biggest pet peeves I have when looking at (and unfortunately – working with) other people’s PHP code is the way they integrate their code into the HTML. Many people don’t take the time to organize, and they end up with a PHP & HTML mess. I believe that it is critical to separate the application logic from the presentation. In other words – do the bulk of the application operations in a script file that has no text/HTML output. When that processing is done, send the data to the presentation file that takes the data and outputs that along with the static HTML for that page. In this article, I will present an easy way to do it using no template engines.

I have some perfect textbook examples that I would love to post of very badly-formatted code, but because of privacy and confidentially reasons with my clients, I can’t do that. You will just have to take my word for it – I have seen some major hackjobs thrown together by the most obvious of n00bs I didn’t even know existed.

So the main thing to remember is this: Think of your web application as having two layers – application & presentation. The only job for the presentation layer is to format the data into the HTML and send it to the browser. Everything else falls to the application layer.

Bad Example

I decided to write a script that would utilize a database table in my sample database. This example uses data from the article on how to Locate the Nearest Radar Station and Display Radar Images. This script will take your IP’s location, and show the 10 closest radar stations to that location – but displaying the results in way that should make you cringe.

Run This Example

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>IP Geolocation Example</title>
<meta name="generator" content="Bluefish 1.0.7">
<meta name="author" content="Andrew Wells">
<meta name="date" content="2008-12-26T17:05:21-0600">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8">
</head>
<body>
<?php
/* replace with your own DB connection code */
require('../includes/database.php');
$db = db_connect();

/* get the IP address and make sure it is an unsigned integer */
$ip = sprintf('%u', ip2long($_SERVER['REMOTE_ADDR']));

/* fetch the location id */
$query = "SELECT locId FROM CityBlocks WHERE $ip BETWEEN startIpNum AND endIpNum LIMIT 1";
$result = mysql_query($query, $db) or die(mysql_error());
$row = mysql_fetch_assoc($result);

/* now fetch the location */
$locId = $row['locId'];
$query = "SELECT * FROM CityLocation WHERE locId = $locId LIMIT 1";
$result = mysql_query($query, $db) or die(mysql_error());
$location = mysql_fetch_assoc($result);

echo '<h2>Details on IP Location:</h2>';
echo '<b>Location ID:</b> ' . $location['locId'] . "<br />\n";
echo '<b>Country:</b> ' . $location['country'] . "<br />\n";
echo '<b>Region:</b> ' . $location['region'] . "<br />\n";
echo '<b>City:</b> ' . $location['city'] . "<br />\n";
echo '<b>Postal Code:</b> ' . $location['postalCode'] . "<br />\n";
echo '<b>Latitude:</b> ' . $location['latitude'] . "<br />\n";
echo '<b>Longitude:</b> ' . $location['longitude'] . "<br />\n";
echo '<b>Metro Code:</b> ' . $location['metroCode'] . "<br />\n";
echo '<b>Area Code:</b> ' . $location['areaCode'] . "<br />\n";

/* offset the coordinates by 3, and find the closest station */
$lat = $location['latitude'] + 3;
$lon = $location['longitude'] - 3;
$query = "SELECT *, SQRT(POW(69.1 * (lat - $lat), 2) + 
			POW(69.1 * ($lon - lon) * COS(lat / 57.3 ), 2 )) AS distance 
			FROM RadarSites ORDER BY distance ASC LIMIT 10";
$result = mysql_query($query, $db) or die(mysql_error());

echo'<h2>Radar Site Details</h2><table width="800">';
echo '<tr>';
echo '<th>Station ID</th>';
echo '<th>Lat</th>';
echo '<th>Lon</th>';
echo '<th>Updated</th>';
echo '<th>Distance</th>';
echo '</tr>';
for ($i = 0, $n = mysql_num_rows($result); $i < $n; $i++)
{
	$radar = mysql_fetch_assoc($result);
	echo '<tr>';
	echo '<td>' . $radar['id'] . '</td>';
	echo '<td>' . $radar['lat'] . '</td>';
	echo '<td>' . $radar['lon'] . '</td>';
	echo '<td>' . $radar['updated'] . '</td>';
	echo '<td>' . $radar['distance'] . '</td>';
	echo '</tr>';
}
echo '</table>';
?>
</body>
</html>

This isn’t a worst cast scenario – I’ve seen worse, but I would like to point out the PHP code block in the middle of the header and footer HTML. Notice all the application work I’m doing in lines 13-67 that is right in the middle of the HTML output. Looking further, you can see that I am using echo statements to output the table HTML and other code. This is bad. It makes it hard to change the HTML without messing with the PHP, and it makes it next to impossible for a designer to work with it.

Good Example

Here is a better example with most of the logic separated from the HTML.

Run This Example

<?php
/* replace with your own DB connection code */
require('../includes/database.php');
$db = db_connect();

/* get the IP address and make sure it is an unsigned integer */
$ip = sprintf('%u', ip2long($_SERVER['REMOTE_ADDR']));

/* fetch the location id */
$query = "SELECT locId FROM CityBlocks WHERE $ip BETWEEN startIpNum AND endIpNum LIMIT 1";
$result = mysql_query($query, $db) or die(mysql_error());
$row = mysql_fetch_assoc($result);

/* now fetch the location */
$locId = $row['locId'];
$query = "SELECT * FROM CityLocation WHERE locId = $locId LIMIT 1";
$result = mysql_query($query, $db) or die(mysql_error());
$location = mysql_fetch_assoc($result);

/* offset the coordinates by 3, and find the closest station */
$lat = $location['latitude'] + 3;
$lon = $location['longitude'] - 3;
$query = "SELECT *, SQRT(POW(69.1 * (lat - $lat), 2) + 
			POW(69.1 * ($lon - lon) * COS(lat / 57.3 ), 2 )) AS distance 
			FROM RadarSites ORDER BY distance ASC LIMIT 10";
$result = mysql_query($query, $db) or die(mysql_error());

for ($i = 0, $n = mysql_num_rows($result); $i < $n; $i++)
{
	$radars[] = mysql_fetch_assoc($result);
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>IP Geolocation Example</title>
<meta name="generator" content="Bluefish 1.0.7">
<meta name="author" content="Andrew Wells">
<meta name="date" content="2008-12-26T17:05:21-0600">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8">
</head>
<body>

<h2>Details on IP Location:</h2>
<b>Location ID:</b> <?=$location['locId']?><br />
<b>Country:</b> <?=$location['country']?><br />
<b>Region:</b> <?=$location['region']?><br />
<b>City:</b> <?=$location['city']?><br />
<b>Postal Code:</b> <?=$location['postalCode']?><br />
<b>Latitude:</b> <?=$location['latitude']?><br />
<b>Longitude:</b> <?=$location['longitude']?><br />
<b>Metro Code:</b> <?=$location['metroCode']?><br />
<b>Area Code:</b> <?=$location['areaCode']?><br />

<h2>Radar Site Details</h2><table width="800">
<tr>
	<th>Station ID</th>
	<th>Lat</th>
	<th>Lon</th>
	<th>Updated</th>
	<th>Distance</th>
</tr>
<?php foreach ($radars as $radar): ?>
<tr>
	<td><?=$radar['id']?></td>
	<td><?=$radar['lat']?></td>
	<td><?=$radar['lon']?></td>
	<td><?=$radar['updated']?></td>
	<td><?=$radar['distance']?></td>
</tr>
<?php endforeach; ?>

</table>
</body>
</html>

In lines 46-54, I am using PHP shorthand tags to output PHP variables in a cleaner way. The other thing you will notice is that there is no getting around the loop structure that is needed to output the 10 radar sites. We can do it without the curly braces though, and with neater “tags” in the HTML to control the loop.

Another thing to mention – I would even have the PHP block in a different file, but I combined them for the simplicity of the example.

PHP Shorthand Tags and Alternative Syntax

Since the presentation files are to be more focused on the HTML, and won’t be very PHP-intense, we can use simplified tags. To output PHP variables in HTML without the PHP opening/closing tags, we use the shorthand method:

<!-- old method -->
<html>
<?php
    echo $some_var;
?>
</html>

<!-- better method -->
<html>
<?=$some_var?>
</html>

If we need to have a control structure, such as an if statement or loop, we do it this way:

<html>
<?php if ($condition): ?>
<p>Some content here</p>
<?php endif; ?>
</html>

Here is a loop example:

<html>
<?php for ($i = 0; $i < 10; $i++): ?>
<p>Some content here with the current index of <?=$i?></p>
<?php endfor; ?>
</html>

So there you have it – a few tips for you to create more readable code. I have read that doing it this way with several PHP opening/closing tags can hurt performance by a hair, but I prefer losing a few CPU cycles over several hours debugging later down the road. The choice is yours. :)


Viewing all articles
Browse latest Browse all 10

Trending Articles