July 29, 2006

Approximating Master Pages in PHP

Most sites on the Internet have common design elements that do not change from page to page. Usually, only content or minor navigational cues vary. To handle the unchanging aspects, developers have often relied on server-side includes - dividing regions like headers, side navigations and footers into separate files.

But now with the advent of ASP.NET 2.0 Master Pages offer a more complete templating alternative. With Master Pages an entire template common to the site is stored in one file with a .master extension. Developers add a ContentPlaceHolder control inside a Master Page to indicate where they would like their page specific content to appear. Then one or more Web Forms may be set up to automatically dress themselves with the shared visual components defined in the Master Page.

So is it possible to make PHP emulate this behavior? To some degree, yes, with output buffering and one server-side include file that represents the "Master Page." Lets say we are aiming to create our HTML by combining this template file and a content file (we'll call these master.php and index.php, respectfully). Our simplified example will aim to achieve the following end result:



The template that will act as our "Master Page" will need to contain all aspects of the design labeled "Template Specific." Since no such control like the ContentPlaceHolder exists, we will use PHP variables to indicate where we would like our page specific content to appear.

master.php
<html>
<head>
<title><?php echo $pagetitle; ?></title>
</head>
<body style="margin-top:20px;margin-left:20px;margin-right:20px;">
<table width="100%" border="0" cellpadding="10" cellspacing="0"border="0">
<tr bgcolor="#33FFFF">
<td colspan="5"><h2>Template Specific Header</h2></td>
</tr>
<tr bgcolor="#EEEEEE">
<td nowrap><a href=#">Navigation Link 1</a></td>
<td nowrap><a href="#">Navigation Link 2</a></td>
<td nowrap><a href="#">Navigation Link 3</a></td>
<td nowrap><a href="#">Navigation Link 4</a></td>
<td width="100%">&nbsp;</td>
</tr>
</table>
<br />
<table width="100%" cellpadding="10" cellspacing="0" border="0">
<tr>
<td width="30%" valign="top" bgcolor="#EEEEEE"><strong>Template Specific
Navigation</strong><br /><br />
<a href="#">Link 1</a><br />
<a href="#">Link 2</a><br />
<a href="#">Link 3</a><br />
</td>
<td width="70%" valign="top"><?php
echo $pagemaincontent;
?></td>
</tr>
</table>
<br />
<table width="100%" cellspacing="0" cellpadding="10" border="0">
<tr>
<td colspan="2" bgcolor="#33FFFF">Template Specific Footer</td>
</tr>
</table>
</body>
</html>

Now any pages that we would like to have adhere to the template only need to define the page specific variables and include our master.php file.

index.php
<?php
//Buffer larger content areas like the main page content
ob_start();
?>
<em>Page Specific Content Text</em><br />
Lorem ipsum dolor sit amet, consectetuer adipiscing
elit, sed nonummy nibh euismod tincidunt ut laoreet
dolore magna aliat volutpat. Ut wisi enim ad minim
veniam, quis nostrud exercita ullamcorper
suscipit lobortis nisl ut aliquip ex consequat.
<br /><br />
Duis autem vel eum iriure dolor in hendrerit in
vulputate velit molestie consequat, vel illum
dolore eu feugiat nulla facilisis ats eros et
accumsan et iusto odio dignissim qui blandit
prasent up zzril delenit augue duis dolore te
feugait nulla facilisi. Lorem euismod tincidunt
erat volutpat.
<?php
//Assign all Page Specific variables
$pagemaincontent = ob_get_contents();
ob_end_clean();
$pagetitle = "Page Specific Title Text";
//Apply the template
include("master.php");
?>

Even though it's not perfectly aligned with ASP.NET's Master Page feature set, the technique described above allows us to consolidate what might otherwise be numerous server-side include files.

July 21, 2006

Control Designer Gotcha

This week I've been programming a custom web server control. It required some specific behavior while being manipulated in the design view of Visual Studio 2005. To achieve this I decided to extend a ContainerControlDesigner to suit my needs. In order to test my new control as I worked on it, I added my efforts to a web project.

However, despite importing the ContainerControlDesigner's namespace (System.Web.UI.Design), the class definition could not be found and as a result it wouldn't compile. I discovered that the classes in the System.Web.UI.Design namespace belong to the System.Design.dll assembly which is not referenced by default in a Visual Studio 2005 web project. I had mistakenly assumed this class was already a part of the referenced System.Web.dll. After adding a reference to System.Design.dll (see image below) my custom control designer compiled flawlessly.

July 08, 2006

MacBook Pro 10.4.7 Kernel Panic Issue

I encountered an issue with my MacBook Pro today that was somewhat troublesome to fix. After months of flawless operation my Mac suddenly started experiencing kernel panics on every boot occuring less than a minute after arriving at the login screen. Since Boot Camp is installed I feared the worst, especially after catching wind of some horror stories on Apple's support forums.

After further research I was relieved to find a simple solution. It turns out that two versions of Apple's 10.4.7 upgrade were released on the same day. I was able to boot into OS X's "Safe Mode" by restarting the computer and holding down the Shift key. Once booted I checked my version of the OS by clicking the "Apple Menu -> About This Mac" option, clicking the "More Info" button and highlighting the "Software" header in the left navigation area. Software update had installed build 8J2135, the first version of the 10.4.7 upgrade that happened to be missing some key files. I downloaded and installed the fixed upgrade (build 8J2135a) from here and encountered no further problems.