Tuesday, 22 Jul 2008 18:20 EST
Michael Thompson over at
Ars Technica published a story yesterday on a North Carolina public library that is
offering summer workshops in game design. Kids get an opportunity to design 2D platforming games (think NES side-scrollers) in small groups over the course of 4 days. Utilizing a drag-and-drop application and pre-built graphics libraries, the kids are able to design a working title over the course of a week.
Kudos to the library for giving kids this opportunity. It's a great way to get kids engaged in not only video game design, but programming in general. Who knows, some of these kids might end up at the forefront of the next video game revolution.
Tuesday, 17 Jun 2008 7:12PM EST
It's been way too long since I've updated the site, and I wouldn't exactly say I'm coming back with a bang, but I've got a nice little function that I thought many of you could use. My latest project has a file share built in where users can store up to 100MB of files right in the web app. Very often, a user doesn't want to take the time to think up a name for the share; especially one that will only be around for one or two uses. To make their lives just that much easier, I built a function to generate a random string of characters, then check to see if that string is already in use. If it is, I simply run through the loop a second time, generating a new random string. That may not sound like the most efficient way of doing it, but being that there's over 250,000,000 10-character permutations of the 36 letters and numbers (and my site is just not that popular), I don't expect to run through that loop too many times.
The first thing we want to do is create a do-while loop inside our
randString function. this loop will execute the code to build a random string of length=
$length then check to see if the string is unique using a custom
isUnique function. If the string is already in use, the loop will execute again. The do-while to execute at least once and as many times as necessary to generate a unique string.
function randString ($length) {
do {
// Generate random string
} while (!isUnique($name));
return $name;
}
Moving on to the actual string generation, we first specify an empty variable,
$name, to hold our string and a string of all possible characters to be used in our string generation. We then define a while loop that will execute
$length number of times. Each pass through the loop tacks another random character onto
$name. Since I only want to use each character once, we have an
if statement that only adds the new character and increments the counter if that character is not already in the string.
function randString ($length) {
do {
$name = "";
$charlist = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$i = 0;
while ($i<$length) {
$char = substr($charlist, mt_rand(0, strlen($charlist)-1), 1);
if (!strstr($name, $char)) {
$name .= $char;
$i++;
}
}
} while (!isUnique($name));
return $name;
}
The last piece we need to bring this all together is the
isUnique function which will check to see if the directory name generated is already in use. For this, we first scan the directory or directories where are file shares live (in my case, everything is in the "fileshares" directory). We then have a basic foreach loop that goes through the directory listing and checks to see if the specified string is equal to any existing directory names. If so, the function returns
false, if not, the foreach loop finishes out and the function returns
true.
function isUnique($string) {
$allFiles = scandir("files");
foreach($allFiles as $key => $value) {
if($string == $value) { return false; }
}
return true;
}
And there you have it. A simple php function to generate and random but unique directory name. As always, if you have a technique that you think is better or a tweak that improves on this code, please share it in the comments. If you have a tip, a trick or an idea for my next post, please don't hesitate to
contact me.
Tuesday, 16 Jun 2008 6:10PM EST
Mozilla is set to release the highly anticipated
Firefox 3 tomorrow, June 17th. The latest version of the worlds second most popular web browser features an enhanced user experience, better performance, tighter security and even more customization. All this combine to create what Mozilla call the "fastest, smartest, most powerful browser" they've released to date.
With the release of Firefox 3, Mozilla is attempting to break the Guinness world record for downloads in a 24 hour period in what they've dubbed
"Download Day". You can help Mozilla reach its goal by downloading Firefox 3 by 17:00 UTC on June 18, 2008 (1pm EDT, 10AM PDT)
Wednesday, 27 Feb 2008 4:32PM EST
When working with
XML-based applications you'll often find the need to append elements to your document or even build new XML documents on the fly. PHP's DOM API can be used to dynamically generate well-formed XML documents as well as editing existing files. In this tutorial we will construct a basic XML document used to store information on pending repairs at an auto repair shop, using the DOM API.
Creating a New DocumentLet's start by creating a new file. We will pass the value "1.0" to the
DOMDocument function which will create a new XML file using XML version 1.0.
$xdoc = new DOMDocument("1.0");
XML requires that a single root element exists and that all other elements exist within the root element. All of our root and child elements will be created using the
createElement() function, the data is then created with
createTextNode() and then the text is appended to the element and the element appended to the node or document with
appendChild. Let's go ahead and create our root and a child element; then append them to the document.
// Create root element and append to $xdoc
$root = $xdoc->createElement('pendingRepairs');
$xdoc->appendChild($root);
// Create a new child and text node for child
$repair1 = $xdoc->createElement('repair');
$root->appendChild($repair1);
Our current XML document looks like this:
<?xml version="1.0"?>
<pendingRepairs>
<repair>
</repair>
</pendingRepairs>
OK, so now we have an XML document with a single repair, but no information on that repair. Now we need to create child elements of
$repair1 to store some data.
// Create child elements and text nodes, append text to elements
$customer = $xdoc->createElement('customer');
$customerData = $xdoc->createTextNode('Bob Smith');
$customer->appendChild($customerData);
$car = $xdoc->createElement('car');
$carData = $xdoc->createTextNode('Ford Pinto');
$car->appendChild($carData);
$repairtype = $xdoc->createElement('repairtype');
$repairtypeData = $xdoc->createTextNode('rebuild transmission');
$repairtype->appendChild($repairtypeData);
// Append child elements to repair element
$repair1->appendChild($customer);
$repair1->appendChild($car);
$repair1->appendChild($repairtype);
// Save the updated file
$xdoc->save("pendingRepairs.xml");
And our current XML document now looks like this:
<?xml version="1.0"?>
<pendingRepairs>
<repair>
<customer>Bob Smith</customer>
<car>Ford Pinto</car>
<repairtype>rebuild transmission</repairtype>
</repair>
</pendingRepairs>
Adding Elements to an Existing DocumentThis functionality wouldn't do much good if all you could do was create new documents. Next, let's reopen
pendingRepairs.xml and enter a new repair. First we'll create a new DOM document and load our existing xml into that document. Then we'll create a new child, append it and resave the file.
// Load the file
$xdoc = new DomDocument;
$xdoc->Load('pendingRepairs.xml');
$root = $xdoc->getElementsByTagName('pendingRepairs')->item(0);
// Create and append a new repair
$repair2 = $xdoc->createElement("repair");
$root->appendChild($repair2);
// Create child elements and text nodes, append text to elements
$customer = $xdoc->createElement('customer');
$customerData = $xdoc->createTextNode('Joe Schmo');
$customer->appendChild($customerData);
$car = $xdoc->createElement('car');
$carData = $xdoc->createTextNode('Chevy Chevelle');
$car->appendChild($carData);
$repairtype = $xdoc->createElement('repairtype');
$repairtypeData = $xdoc->createTextNode('oil change');
$repairtype->appendChild($repairtypeData);
// Append child elements to repair element
$repair2->appendChild($customer);
$repair2->appendChild($car);
$repair2->appendChild($repairtype);
// Save the updated file
$xdoc->save("pendingRepairs.xml");
The updated XML document now looks like this:
<?xml version="1.0"?>
<pendingRepairs>
<repair>
<customer>Bob Smith</customer>
<car>Ford Pinto</car>
<repairtype>rebuild transmission</repairtype>
</repair>
<repair>
<customer>Joe Schmo</customer>
<car>Chevy Chevelle</car>
<repairtype>oil change</repairtype>
</repair>
</pendingRepairs>
Deleting Elements From an Existing DocumentFinally, we'll delete an item from this list by searching the file for a node with a matching customer name and repair type. First, we'll load the XML file using the DOM API, then we'll load the file again, this time using
simplexml_load_file (covered in my
Jan 1st post). By doing this, we can easily traverse the data loaded using simplexml to find the position of the node we're looking for, then use that position to delete the node using the DOM API. In this case we'll be searching for and removing Bob Smith's transmission rebuild.
// Load DOM file
$xdoc = new DomDocument;
$xdoc->Load('pendingRepairs.xml');
// Load simplexml file
$sdoc = simplexml_load_file('pendingRepairs.xml');
$pos = 0;
foreach($sdoc->repair as $repair) {
if( ($repair->customer == 'Bob Smith') && ($repair->repairtype == 'rebuild transmission') ) {
$node = $xdoc->getElementsByTagName('repair')->item($pos);
$node->parentNode->removeChild($node);
}
$pos++;
}
// Save the updated file
$xdoc->save("pendingRepairs.xml");
And there you have a simple introduction to the PHP DOM API. As always, if you have a technique that you think is better or a tweak that improves on this code, please share it in the comments. If you have a tip, trick or an idea for my next post, please don't hesitate to
contact me.
Wednesday, 13 Feb 2008 7:02PM EST
A recursive function, simply put, is a function that calls itself. Certain functional languages, such as LISP and Scheme, are designed with recursion in mind; and recursive functions are often required to complete a program. PHP, on the other hand, focuses on iteration. Recursion is often very costly in PHP and not usually your best option. In the case of traversing a file system, though, recursion is the best and most efficient option.
The basic idea behind this code is that you have a single function which scans a given directory and stores the name of each file in an array. The function will call itself each time a sub directory is found, passing the name of that sub directory to the function. This will put the first function call on hold while the second function call is evaluated. The second function call will scan the sub directory, putting each filename into a sub array. The function will call itself again if a third level directory is found, and so on. This will continue on until all directories have been scanned. Assuming the following directory structure:
root/html
root/html/index.php
root/html/about.php
root/html/archives.php
root/html/images/logo.png
root/html/images/photo.png
root/html/images/icons/arrow.png
root/html/images/icons/pencil.png
root/html/images/icons/paper.png
root/html/style/style.css
Then calling
scanFilesystem() as follows:
$dir = "root/html";
$dirStructure = scanFilesystem($dir);
print_r($dirStructure);
Will give this output:
Array
(
[0] => about.php
[1] => archives.php
[2] => index.php
[images] => Array
(
[0] => logo.png
[1] => photo.png
[icons] => Array
(
[0] => arrow.png
[1] => pencil.png
[2] => paper.png
)
)
[style] => Array
(
[0] => style.css
)
)
We can accomplish this by creating a
scanFilesystem function, which takes a single parameter;
$dir. The directory,
$dir, is scanned using
scandir() and the result is stored in
itemArray[]. Item array only contains the names of files and folders in the specified directory;
scandir() does not scan sub directories. We then iterate through the array with a
for loop (here I initiate
$i to 2 because the first two items in each directory of my filesystem are evaluated as "." and "..". You should test this value on your server before implementing). We then check each item in the array with
is_dir() to see if it is a directory. If not, we add the filename to
$tempArray[]. If it is a directory, then let the recursion begin.
We call
scanFilesystem() again, from within the function itself, passing it the path of the sub directory that we've found and storing the result in
$tempArray[$item]; where
$item is the name of the sub directory. This process will continue until a directory with no sub directories is reached. In that case, the function goes back to the next higher directory and continues that scan, and so on until every directory has been scanned. After each directory scan has finished, we sort the files and sub directories in the resulting array with
asort(). Each function call returns
$tempArray[], which is now a sorted array of all files and directories (including those contained in sub directories) within a particular directory.
function scanFilesystem($dir) {
$itemArray = scandir($dir);
for($i=2; $i<count($itemArray); $i++) {
$item = $itemArray[$i];
$newDir = $dir . "/" . $item;
if(is_dir($newDir)) {
$tempArray[$item] = scanFilesystem($newDir);
asort($tempArray);
}
else {
$tempArray[] = $item;
}
}
return $tempArray;
}
Still not quite getting the concept of recursion? Don't worry, we've all been there. Check out
Wikipedia for a much better explanation of the concept.
As always, if you have a technique that you think is better or a tweak that improves on this code, please share it in the comments. If you have a tip, trick or an idea for my next post, please don't hesitate to
contact me.
Friday, 08 Feb 2008 6:04PM EST
PHP's
associative arrays are very powerful in that they allow you to create arbitrary key values, rather than using the simple 0,1,2,3... that most programming languages force on you. For example, if you wanted to create a simple PHP array containing just 2 columns of information, an associative array would be perfect. Take the following 1 dimensional table of data about a pet:
| Type |
Name |
Breed |
| Dog |
Lassie |
Collie |
To represent this with an associative array:
$pets = array("Type"=>"Dog", "Name"=>"Lassie", "Breed"=>"Collie");
But what if you need to store the following table of data in an array?
| Animal |
Name |
Breed |
| Dog |
Lassie |
Collie |
| Fish |
Nemo |
Clown Fish |
| Cat |
Garfield |
Orange Tabby |
You could, of course, create 3 separate arrays; one for each animal. That method is very inefficient, though, and becomes impractical as the table grows. To creat a 2 dimensional array you simply create an array of arrays:
$pets = array( array("Type"=>"Dog", "Name"=>"Lassie", "Breed"=>"Collie"),
array("Type"=>"Fish", "Name"=>"Nemo", "Breed"=>"Clown Fish"),
array("Type"=>"Cat", "Name"=>"Garfield", "Breed"=>"Orange Tabby"),
);
There are two different ways of accessing and displaying the data stored in a 2D array. The first is the manual (and sometimes painful) way:
echo "I have a ".$pets[0]["Type"]." named ".$pets[0]["Name"].". It is a ".$pets[0]["Breed"].".
";
echo "I have a ".$pets[1]["Type"]." named ".$pets[1]["Name"].". It is a ".$pets[1]["Breed"].".
";
echo "I have a ".$pets[2]["Type"]." named ".$pets[2]["Name"].". It is a ".$pets[2]["Breed"].".
";
The second way of accessing the data is to use a for loop (or nested for loops for a non-associative array):
for($i=0; $i<count($pets); $i++) {
echo "I have a ".$pets[$i]["Type"]." named ".$pets[$i]["Name"].". It is a ".$pets[$i]["Breed"].".
";
}
If we needed to add some more data and further categorize the table, we could just as easily create a 3 dimensional array of data; in this case, organized by animal type:
$pets = array( array( array("Type"=>"Dog", "Name"=>"Lassie", "Breed"=>"Collie"),
array("Type"=>"Dog", "Name"=>"Pluto", "Breed"=>"Bloodhound"),
),
array( array("Type"=>"Fish", "Name"=>"Nemo", "Breed"=>"Clown Fish")
),
array( array("Type"=>"Cat", "Name"=>"Garfield", "Breed"=>"Orange Tabby"),
array("Type"=>"Cat", "Name"=>"Tom", "Breed"=>"Russian Blue")
),
);
And we could access and display this data with 3 nested for loops (or there's always the manual and painful way):
for($i=0; $i<count($pets); $i++) {
for($j=0; $j<count($pets[$i]; $i++) {
echo "I have a ".$pets[$i][$j]["Type"]." named ".$pets[$i][$j]["Name"].". It is a ".$pets[$i][$j]["Breed"].".
";
}
}
And that's all you need to know to get started using multi-dimensional arrays in PHP. Of course, there are countless variations of this code and uses for it, so take the code, play with it and put it to good use. As always, if you have a technique that you think is better or a tweak that improves on this code, please share it in the comments. If you have a tip, a trick or an idea for my next post, please don't hesitate to
contact me.
Thursday, 31 Jan 2008 7:55AM EST
If you’re building a web application with user accounts, profile pages or any type of customized pages, you'll probably want to offer your users the option of changing their theme. The simplest way to accomplish this is to build multiple CSS files and allow your users to change their preferred style with the click of a button. All you need is a button that will swap the CSS files with a single click. Of course you'll want to get a bit more involved and store the users preferred theme in a database or a cookie. In this tutorial, I'll be showing you how to do the latter.
The HTML is very simple. All you need is a link or button which calls the
swapCSS function for each style option and a call to
loadCSS in the
body onload property of your page.
<body onload="javascript:loadCSS();">
<input type="button" value="Black on Gray" onclick="javascript:swapCSS('bog');" />
<input type="button" value="Green on Black" onclick="javascript:swapCSS('gob');" />
</body>
The
swapCSS function takes a single parameter;
choice. This is an arbitrary value to distinguish between the style choices. In this example, I use "gob" to stand for green text on a black background, and "bog" to stand for black text on a gray background. The function first gets your style element, in this case "globalStyle", sets
href value of that element to change the current CSS, and stores the name of the preferred stylesheet in a cookie.
function swapCSS(choice) {
var styleId = document.getElementById("globalStyle");
if(choice == "gob") {
styleId.href = "black_with_green.css";
setCookie('style','black_with_green.css',90);
} else if(choice == "bog") {
styleId.href = "gray_with_black.css";
setCookie('style','gray_with_black.css',90);
}
}
The
loadCSS function, called when the page is first loaded, checks to see if a cookie has previously been set with the users preferred style. If so, that current stylesheet is set to the value of that cookie.
function loadCSS() {
var styleId = document.getElementById("globalStyle");
if(cookieValue('style')) {
styleId.href = cookieValue('style');
}
}
Finally, we have the cookie functions;
setCookie and
cookieValue.
setCookie takes 3 parameters;
name, a string that will be used to identify the cookies,
value, the name of the stylesheet, and
days, the number of days before your cookie will expire. The function checks to see if
days has been specified and uses
document.cookies to create the cookie.
function setCookie(name,value,days) {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expire = "; expires=" + date.toGMTString();
}
else var expire = "";
document.cookie = name + "=" + value + expire + "; path=/";
}
cookieValue checks to see if a specified cookies exists, and if so, it returns to value of that cookie.
function cookieValue(name) {
var name = name + "=";
var allcookies = document.cookie.split(';');
for(var i=0;i < allcookies.length;i++) {
var cookie = allcookies[i];
while (cookie.charAt(0)==' ') cookie = cookie.substring(1,cookie.length);
if (cookie.indexOf(name) == 0) return cookie.substring(name.length,cookie.length);
}
return null;
}
View a live demo »
That's all there is to it. A simple javascript function to swap CSS files and store the users preference in a cookie. As always, if you have a technique that you think is better or a tweak that improves on this code, please share it in the comments. If you have a tip, a trick or an idea for my next post, please don't hesitate to
contact me.
Friday, 25 Jan 2008 7:49PM EST
Early in 2007,
Digg.com introduced its
API which allows developers to access all of Digg's data back to 2004. Requests are sent to the Digg servers with a simple call to http://services.digg.com and responses are sent back in an XML, JSON, JavaScript or PHP type. For this tutorial, we're going to focus on PHP responses.
I'm going to ignore the
Services_Digg Pear package for now, since it has not yet been accepted as an official Pear package. That said, the best way to access the API in PHP is through the
cURL library and since I've always been a fan of the wheel and I see no reason to reinvent it, I'm going to use
JasLab's PHP Digg
toolkit. The toolkit is class that you'll need to unzip and upload to your server. Then simply add it as an include in the PHP file you'll be working in and your ready to go. The toolkit will handle connecting to the Digg server with
curl_setopt, building the request and parsing the response. It will return a nice, clean array of arrays containing all of the diggs and/or comments you've requested. Let's get started.
The first thing we're going to do is create a new instance of
diggclass; the main class in the digg toolkit. Then, to get all diggs from a single user, just call the
getUserDiggs function on your class instance and store the result in a new array.
getUserDiggs takes several optional parameters, but the main values that you'll want to pass are
$user,
$count and
$offset; where
$count is the number of diggs to return and
$offset is the starting point for which to get diggs (0 means start with the most recent digg). You can also pass start and ending time values; check out the toolkit documentation for more information.
include("diggclass.php");
$diggobj = new diggclass();
$user = "jspegele";
$diggArray = $diggobj->getUserDiggs($user,$count=10,$offset=0);
The
getUserDiggs function will return an array containing individual arrays for each digg retrieved. The inidivual arrays contain the date of submission, story id, story number, username of the submitter, the popular or upcoming status. Story id (returned as
id) can be used to retreive further story information from the
getStories function. Simply pass the id to the function and an array of arrays will be returned with the story link, Digg story link, number of comments, status, title, description, submitter, submitter's icon, topic and diggs. Of course, since you sent a story id to the function, only a single array will be in the returned array. Here's how you would get all of the diggs data and the stories data and merge them into all of that data into a single array containing one array for each digg:
function latestDiggs($user,$limit) {
$diggs = "";
for($i=0; $i<$limit; $i++) {
$tempArray = $diggArray[$i];
$storyId = $tempArray[story]; // Story id - used to get story title,link,etc.
$date = $tempArray[date]; // Date and time of digg
// Get the story information based on storyId
$storiesArray = $diggobj->getStories("",$storyId,"","","","");
// getStories also returns an array of arrays. There should only be 1 element returned.
$storyArray = $storiesArray[0];
$title = $storyArray[title];
$digg_link = $storyArray[digg_link];
$diggs[$i] = array("date"=>$date, "title"=>$title, "digg_link"=>$digg_link, "content"=>"");
}
}
And here's all of the code you would need to get a single array containing all comments, with the accompanying story data from a single user:
function latestDiggComments($user,$limit) {
// Create a new instance of diggclass()
$diggobj = new diggclass();
// Get the last $limit comments from $user starting with the latest
// getUserComments will return an array of arrays. Each sub array
// describes a comment.
$commentArray = $diggobj->getUserComments($user,$count=$limit,$offset=0);
$comments = "";
for($i=0; $i<$limit; $i++) {
$tempArray = $commentArray[$i];
$storyId = $tempArray[story]; // Story id - used to get story title,link,etc.
$date = $tempArray[date]; // Date and time of digg
$comment = $tempArray[content]; // Text of the comment
// Get the story information based on storyId
$storiesArray = $diggobj->getStories("",$storyId,"","","","");
// getStories also returns an array of arrays. There should only be 1 element returned.
$storyArray = $storiesArray[0];
$title = $storyArray[title];
$digg_link = $storyArray[digg_link];
$comments[$i] = array("date"=>$date, "title"=>$title, "digg_link"=>$digg_link, "content"=>$comment);
}
}
And finally we can bring it all together with a function that will call each of the above functions, merge the two arrays that are returned, order them based on a date comparison function (see the code linked below for
cmp()) and prints all of the activity in the array in chronological order, starting with the most recent digg or comment.
function printDiggFeed($user,$limit) {
$diggs = latestDiggs($user,$limit); // Get the latest diggs
$comments = latestDiggComments($user,$limit); // Get the latest comments
$diggsAndComments = array_merge($diggs,$comments); // Combine into 1 array
usort($diggsAndComments,"cmp"); // Sort based on the cmp() function
for($i=0; $i<10; $i++) {
$tempArray = $diggsAndComments[$i]; // Since diggsAndComments is an array of arrays...
$date = $tempArray[date];
$digg_link = $tempArray[digg_link];
$title = $tempArray[title];
$content = $tempArray[content];
echo "$title";
// if this is a comment...
if($content != "") {echo"
"$content"";}
echo "
";
}
}
View all of the code to get Digg activity for a single user »
View a live demo »
And there you have the basics of utilizing the PHP Digg toolkit to access digg data and display it on your site or in your widget. As always, if you have a technique that you think is better or a tweak that improves on this code, please share it in the comments. If you have a tip, a trick or an idea for my next post, please don't hesitate to
contact me.
Wednesday, 23 Jan 2008 6:20PM EST
Yesterday, the
W3C published two documents that are very important to the future of web development. They released technical reports on
HTML 5 and
HTML 5 differences from HTML 4. This draft represents a major leap forward for HTML which has not seen an update since HTML 4 was adopted in December of 1999.
The new elements and attributes that have been added into version 5 focus entirely on semantics and structure. In fact, the
<font> element as well as all presentational attributes, such as
align,
width,
height,
background and
style, have been removed in HTML 5. It is clear that by the time this draft is accepted as a standard, CSS will not only be the norm, but will be required.
Besides removing presentational elements and attributes, HTML 5 is also focusing on structure with the additions of several key elements. Most notably,
<section>,
<article>,
<aside>,
<header>,
<footer> and
<nav>. These new elements will be used for easily defining your page structure, rather than having to use
<div id="nav"> or
<div id="header">. This standardizes what are already the most common designations for these sections of a web page, making both the HTML and CSS code easier to code and read. Other notable elements with a great deal of potential include
<dialog> and its child elements
<dt> and
<dd>, which can be used to mark up a conversation,
<figure>, which can associate a caption with some embedded content,
<audio> and
<video>, for multimedia content,
<meter>, for representing measurements, and
<datagrid>, which represents and interactive tree list or tabular data.
Form validation will get much easier, as well, with the introduction of 10 new input types; datetime, datetime-local, date, month, week, time, number, range, email and url. These new types mean that the
text input type will no longer be a catch-all for any kind of input and browsers will now be able to do the field limiting and validation for you.
There are some notable new attributes as well. The
ping attribute in
<a> and
<area> elements allow for a list of URIs to be pinged when a link is followed.
<a> and
<area> will also now have the
media attribute.
value is no longer deprecated for
<li> and
autofocus can now be specified on an
<input> element.
The HTML version 5 specification is exciting news for web developers everywhere as the markup language is set to take its first steps in nearly a decade. Which attributes and elements are you most excited to see? What new tricks do you think you'll be able to pull of with them?
Friday, 18 Jan 2008 7:00PM EST
From time to time in your PHP class adventures you may need to declare a variable as static or define a constant value. If you've ever used these objects in a language similar in syntax (i.e. C++), this should all be familiar, but if not, this tutorial will give you all the information to begin employing these important concepts. Those of you who are true PHP newbs, might want to check out the first 2 parts of this series;
The Basics of PHP Classes and
The Basics of PHP Abstract Classes.
Let's start by defining
static varibles and
constants. A constant is a value that you define in your class which must be equal to a constant expression. This means that you constant can be set to any string or number, but not to the value of a variable, the result of a function call or the result of a mathematical expression. The constant will be inherited by any and all instances of that class which you create. The static keyword, on the other hand, can be applied to any member or method of a class. These members and methods are no different than any other, except that they can be accessed without creating an instance of that class.
Defining a constant is simple. You precede the name of your constant with the
const keyword and set it equal to whatever your constant value is. To access the value of your constant, you'll need to use the
scope resolution operator (::) preceded by either
self (from within the class) or the name of the class (from outside of the class).
<?php
class MyClass {
const someconstant = 'value of my constant';
public function printConst() {
echo self::someconstant;
}
}
// Print constant value without a class instance
echo MyClass::someconstant;
/*** In PHP5.3+ ***/
//Print constant value without a class instance while
//storing the class name in a variable
$className = "MyClass";
echo $className->printConst();
//Print constant value through an instance of the class
$classInstance = new MyClass();
$classInstance->printConst();
//or
echo $classInstance::someconstant;
?>
Static methods and members are different from constants in that the value of a static method or member does not have to remain static. In PHP, you are able to declare a static member which will be inherited by all instances of that class, but you are able to access and change that variable without an instance. Static methods work much the same way as static members, but methods can be accessed with or without an instantiated object. To declare a member or method as static, add the
static keyword after the
visibility keyword and before the member or method name. Much like constants, you will need to use the scope resolution operator (::) preceded by either
self or the class name in order to access the member or method. You can also use the scope resolution operator preceded by
parent to access the static member or method of a parent class.
<?php
class ParentClass {
public static $staticVar = 'some value';
public function returnStaticVal() {
return self::$staticVar;
}
}
class ChildClass extends ParentClass {
public function returnStaticFromChild() {
return parent::$staticVar;
}
}
// Print static value without a class instance
print ParentClass::$my_static;
// Print static value with a class instance
$classInstance = new ParentClass();
print $classInstance->returnStaticVal();
//Print static value without a class instance while
//storing the class name in a variable
$className = 'ParentClass';
print $className::$staticVar;
// Print static value from a child class instance
print Childclass::$staticVar;
$childInstance = new ChildClass();
print $childInstance->returnStaticFromChild();
?>
That's all you'll need to get started using class constants and static class members and methods. As always, if you have a technique that you think is better or a tweak that improves on this code, please share it in the comments. If you have a tip, a trick or an idea for my next post, please don't hesitate to
contact me.