When writing more advanced PHP based online applications the need to improve performance is often desirable. By caching arrays of data that have been queried from a database such as MYSQL you can save substantial CPU cycles, particularly with data that is needed frequently but seldom changes.
Instead of querying the database each time a page is called, we can read the file contents and have the data at our fingertips. For simple queries this will only be necessary in high traffic websites but in more complicated queries using full text index and multiple table joins, caching data can drastically reduce load with even a medium volume of traffic.
Below is a PHP data caching class I wrote that caches variables using file handle read and write to cache data with or without an expiration time. I used file_get_contents() rather than fread to speed up the application even further. Rather than run a query each time the data is needed, the default is to cache it for 3600 seconds or an hour.
Configurations you may wish to change:
You can download the ObjectCache.class.php PHP5 cache here.
<?php /** * Caches manipulated variables into files for future use * @author Charles Weiss < c w e i s s [ a t ] f t w m a r k e t i n g . c o m > * @copyright Copyright (C) Fetch The Web 2006-2008 * @version 0.1 */ class ObjectCache { private $data; private $ext = '_ObjectCache.php'; // The group of the cache file ( appended to end of filename ) private $path = '/tmp/'; // The FULL path to the cached file function __construct() { $this->data = array(); } /** * Fetches variable from the cache if cache exists and data has not expired * @param $id The id of that variable for use in the filename * @param $lock Optional parameter instructing the class to lock the file. * @return the cache contents OR false on error */ function get($id) { if (isset($this->data[$id])) return $this->data[$id]; // Already set, return to sender $path = $this->path.base64_encode($id).$this->ext; if (file_exists($path) && is_readable($path)) { // Check if the cache file exists include $path; if (isset($expires) && $expires <= time()) { $this->clear($id); return false; } else { $cache = file_get_contents($path); } } else { return false; } } /** * Sets variable into the cache * @param $id The id of that variable for use in the filename * @param $cache The data to be stored * @param $lifetime The expiration time (in seconds) from file creation * @return the cache contents OR false on error */ function put($id, $cache, $lifetime = 0) { $this->data[$id] = $cache; if (is_resource($cache)) return "Can't cache resource."; $path = $this->path.base64_encode($id).$this->ext; $fp = @fopen($path, 'w'); if (!$fp) echo 'Unable to open file for writing.'.$path; @flock($fp, LOCK_EX); @fwrite($fp, '<?php $cache='.var_export($data, true).';'); if ($lifetime > 0) @fwrite($fp, '$expires='.(time()+$lifetime).';'); @fwrite($fp, ' ?>'); @flock($fp, LOCK_UN); @fclose($fp); if (file_exists($path)) chmod($path, 666); else return false; return true; } /** * Deletes the cache file * @param $id The id of that variable for use in the filename * @param $lock Optional parameter instructing the class to lock the file. * @return the true or descriptive string on error */ function clear($id) { if (isset($this->data[$id])) unset($this->data[$id]); $pretty_id = base64_encode($id); $path = $this->path.$pretty_id.$this->ext; if (file_exists($path) && unlink($path)) return true; else return 'Cache could not be cleared.'; } } ?> |
Example usage:
include './ObjectCache.class.php'; $data = array('a','b','c','d','e','f','g'); $distinct_name = 'lala'; $cache = new ObjectCache(); // Cache will last 3600 seconds or 1 hr $cache->put($distinct_name, $data, 3600); $data2 = $cache->get($distinct_name); // Forcibly clear the cache (on data update via admin perhaps //$cache->clear($distinct_name); print_r($data2); unset($cache); |
I would like to have run this example live but unfortunately the server this site is hosted on is php4 at the moment so you will have to run it on your own box.
Hope this helps some of you. Feel free to give credit or not; whatever makes your socks go up and down! ![]()
A few weeks ago, I started a simple tutorial on how to cascade JavaScript check boxes from one row to the next in order to simplify the manipulation of large forms. This week, I’ll take it a step further by adding the same ability to both drop downs and text fields.
I’ve created a small example to help illustrate the functionality of the cascade. Once you load the cascade example page and click the down arrow next to a text field. It should change all the values in the text fields below to the same value as appears in the text box you clicked. The same can be done in the active column. Change one of the values in the active column to True and then click the down arrow next to it and all the rows below will change to True.
Without further discussion, here’s the Javascript code:
function cascSelect(theElement) {
var theForm = theElement.form;
var startBox = theElement.name;
for(z=0; z
Hope this helps some of you out, like I said before it may have saved me a few hours of work had I known it existed previously. It can be cleaned up quite a bit and I know all three functions could be lumped together into a more dynamic function if you like, but I’m not going to trouble with that here.
Cheers! Charles ![]()
Recently I had a project where I was aked to add visual styls to Openads in an effort to create text that were similar in style to Google’s Adsense ads. Openads is an ads server or an extended banner rotator which allows for stats and all kinds of other features. I won’t get into it, if you need an adserver or want to know more, visit the Openads site directly.
Setting up the text ad is fairly simple. Click on Inventory, Advertisers, Choose the advertiser, Choose or Create a new campaign and then click on add a new banner. I’m hoping you know how to get to that point, otherwise give me a shout and I’ll be happy walk you through it.
Choose “Text Ad” from the dropdown box and you the page will look something like this:
Ok, so now in the big trextarea, lets insert the following:
<font color="blue"><strong>How To Kill Bed Bugs</strong></font>
Kill Bed Bugs with Strei-Fab Spray Buy Now from Nixalite.com
<font color="green">www.nixalite.com/bedbugs.asp</font>
This should end up looking like this when all is said and done:
How To Kill Bed Bugs
Kill Bed Bugs with Strei-Fab Spray Buy Now from Nixalite.com
www.nixalite.com/bedbugs.asp
Now when we publish the text link, just place it in 200px div and voila, you have a sudo adsense text advertisement.
First off, I’d like to wish a happy new year to all of you. I hope that this year is even better than last, and I must admit that last was very good for me!
Alrighty, so one of my clients took my advice and asked me to implement the new ga.js tracking cookie on his site. I didn’t pay much attention to what had changed, and just uploaded the new code without thinking about it. Google offers upgrade, they must insure backwards compatibility right?!?! Naw, that would be way too simple, instead they decide to take Microsoft’s lead and nerf backwards compatibility.
Ok, great, it doesn’t work so how do we fix it? Well, in this case, my client re-directs links to other sites. These redirects are driven via database driven backend and tend to change often enough that they shouldn’t be (and aren’t) hardcoded. To capture these clicks in analytics (which we compare to our own tracking system and notice a less than 5% difference) we used the following in our links:
onClick="javascript:urchinTracker('/outgoing/uniqueID_or_Title');"
and then changed it to
onClick="javascript:pageTracker._trackPageview('/outgoing/uniqueID_or_Title');"
So how will it work out? Hopefully all will be fine and our data will once again be tracked by analytics… if not I’ll let you guys know. BTW: You can find the information on google here: (for both versions of the tracking code)
GA Tracker (new)
Urchin Tracker (old)
Charles
Merry Christmas and Happy Holidays to all!
In the ten years that I’ve been doing online programming, I’ve spent at least half of that time working on the backends or administrative portions of content management systems. Content Management Systems or CMS as they’re often called are dynamically driven websites. Great, but what the hell does that mean? A CMS is an online tool that allows users to build very large websites without needing knowledge of the workings behind the text.
Take WordPress for instance, it’s a blog publishing tool (and happens to be the tool I chose to publish this blog entry). It’s also a variation of a CMS. It allows users to enter text in a similar way to writing in Microsoft Word and have it appear on a website following a specific template. Once the CMS templates are setup, the display will have the same formatting even though the content is different. The user just writes the content and chooses when to display it. The programming behind the scenes decides how to display it and how to manage all the rest of the workings.
One of my clients wanted a way to edit multiple entries at a time which is fairly simple, you output the listings into a grid display in a table; I won’t bore you with how to do that. The complex part was finding a solution to choose multiple blocks of entries to edit, kind of like a select all but not quite, more of a select some but faster than selecting them one by one.
Either he or one of his programmers decided top create a cascading tool that would allow users to select a row, click on the submit button in that row and each of the rows below that one selected. By contrast, deselecting the row further down the page and hitting that row’s submit button would deselect all the rows below that one.
Here’s an example and below is the Javscript I created to do this:
// JavaScript Document
function cascSelect(theElement) {
var theForm = theElement.form;
var startBox = theElement.name;
for(z=0; z<theForm.length;z++){
if(theForm[z].type == 'checkbox' && theForm[z].name != 'checkall'){
var checkNames = theForm[z].name;
if(checkNames == startBox.replace(/pos/, 'chk')) {
var startValue = (theForm[z].checked);
var startKey = z;
}
if (z > startKey) {
theForm[z].checked = startValue;
}
}
}
}
You might be wondering what the usefulness of the cascade might be. Think about having 200 rows on the page instead of the six I placed on the examples. What if you wanted to change the values for twenty of those rows without having to select each one individually. This will facilitate that goal.
I’ve used similar solutions which were stored in session cookies and selected via submit rather than javascript functions however using javascript will allow us to cascade values as I will show in my next entry. I hope this is helpful to someone, I might have saved a bunch of hours had I known this solution existed.
Charles
Alrighty then, where to begin? Well, as some of you reading this may know, my name is Charles and I’m currently working as a Programming and Marketing consultant from my home in Montreal. In February, it’s likely that I will take on a full time position with a fairly large review site. I guess all the writings around me is contagious as I feel compelled to write my own musings now. So without further a due, welcome to the Fetch the Web blog where I might post things from time to time of programming, marketing or just the general BS variety. I’m not so foolish as to commit myself to writing here often hehe.
Thanks for stopping by
-Charles