Archive for the 'PHP' Category

Function output caching with PHP

Monday, December 10th, 2007

I've been working on optimizing of a system written in PHP, which started to perform slowly, and I had to implement content caching so I could, say, calculate access stats once a day and then just output cached content to the user, or have top page regenerated every 15 minutes.. Stuff like that.

I thought I'd share my approach (which may not be the best around, but is a working one and can save somebody some time). So here goes….

First, we need to create a table to store cached information (I store cached information as well as system-wide settings in that table)

CREATE TABLE `settings` (
`key` varchar(250) NOT NULL default ",
`data` text NOT NULL,
PRIMARY KEY (`key`)
)

Next, we need accessors to the data in the settings table (just put these functions somewhere accessible by your code):

function settingsGet($key)
{
$key = addslashes($key);
$qstring = "select * from settings where `key`='$key'";
$result = queryDB($qstring);
$stuff = mysql_fetch_array($result);
return $stuff[data];
}
function settingsSet($key, $value)
{
$key = addslashes($key);
$value = addslashes($value);

$qstring = "select * from settings where `key`='$key'";
$result = queryDB($qstring);
if (mysql_num_rows($result)>0) {
//updating
$qstring = "update settings set data='$value' where `key`='$key'";
} else {
//inserting new
$qstring = "insert into settings (`key`, data) values ('$key', '$value')";
}
queryDB($qstring);
}

Next, we'll setup function to get and set cached data, which in turn use settings table accessors we created above. Again, just place them anywhere accessible by your code.

function get_cachedData($data_id, $expireSeconds = 3600) {
//expiring every hour by default

$data = unserialize(settingsGet("data_cache_{$data_id}"));

$lag = time() - $data["ts"];

if ($lag > $expireSeconds) {
return false;
}
return $data[value];
}
function set_cachedData($data_id, $value) {
$ts = time();
$data = array();
$data["ts"] = $ts;
$data["value"] = $value;
settingsSet("data_cache_{$data_id}", serialize($data));
}

Basically, we just use (hard-coded) prefix "data_cache_" to store data in the settings table (useful if you store something else in the settings table as well), as well as "data_id" variable by which you identify the "name" or id of data you wish to cache.

We will also need some nice wrappers:

function startCaching($data_id) {
if ($data = get_cachedData($data_id)) {
echo $data; return true;
}
ob_start();
return false;
}

function endCaching($data_id) {
$data = ob_get_contents();
ob_end_clean();
set_cachedData($data_id, $data);
echo $data;
}

Usage example:

Before caching:

function print_access_rating() {
/*
some code which requires a lot of time to get generated
*/
}

After caching was added:

function print_access_rating() {
if (startCaching("xxxxxxxx)) return;
/*
some code which requires a lot of time to get generated
*/
endCaching("xxxxxxxx");
}

The "xxxxxxxx" would identify the chunk of data you wish to cache. Say, you want to cache latest news section on your top page. For the forementioned usage example you can use print_access_rating as the data_id parameter. Or you can just pass the __FUNCTION__ php 's variable which is always set to the name of current function, if you want.

That's basically all. Please notice that you can use optional second argument of get_cachedData function to set number of seconds for which to cache a particular chunk of data.

Don't know how usable it will be for anyone except for myself, but here it is.. :) Modify to suit your needs.

Using PHP inside Rails structure on Apache

Friday, June 29th, 2007

I do alot of development in Rails recently, and it all goes fine and nice, and Rails is fast and easy to use, but sometimes I'm better off using already existing PHP scripts. Just place them into Rails project, and they just work (think of PHP-based web forms etc).

How do you setup your Apache & Mongrel cluster based Rails project to support execution of PHP scripts inside the Rails project structure? Very easy, actually. (more…)

Easy SWF Plugin 1.1

Monday, March 5th, 2007

The new version of my Easy SWF Plugin for WordPress is out today!

There were lots of requests to add background and included Flash size settings. And this update adds just that :) Continue reading! (more…)

Automated sites backup script

Wednesday, February 14th, 2007

Today I have been restoring automatic backup system for the company I work at. The idea is to take backups of our clients' web sites (both web/html files and database snapshots). So I have decided why not to share? This script was dutifully working for me for almost a year and though it might be not the best way to do stuff, it proven itself pretty robust and problem-free.

Before pasting the script code here, here's how it works.

The script logs into remote server and takes backup of remote html files and database files. One important thing is to notice that database files backup is takes "as is", as I have found out not in the most pleasant way that taking backups of databases via mysqldump command can lead to problems in case tables in the SQL database use different encodings - so binary dump is much safer.

One more thing to notice is that you need to generate an ssh key-pair in order to be able to log into a remote server without entering a password (that's why there is no mention of passwords in the script's settings). You can read about logging into SSH without using passwords here.

Since I use rsync to fetch files from server, only files which were changes between backup sessions are being transferred - which makes backups much faster in case of successive backups.

Usage: php backup.php <backup_type>

you can specify type of backup, so it will be placed into a separate directory. Default is "nightly". Files will be backed up into directories inside the $backupDir you specified, in form of: "<sitename>_<backup_type>_<web or db>".

Once the script is deployed and configured, you might want to specify cron jobs which would make nightly, weekly and monthly backups for you. This way you will have at least 3 versions to choose from in case something shitty happens :)

And of course I would like to notice that the script goes "as-is" without any warranties that it won't destroy your data and nullify you hard disk (although if configured sanely, it would only save you from problems of loosing data).

Have fun with the script, modify it if you want. Hopefully it'll save you some nerve cells if ever a problem occurs on your remote servers.

The script follows:

(more…)

Easy Inline SWF plugin updated to version 1.0.2

Sunday, October 1st, 2006

The new version fixes problems with resolving local path to .swf in situations when WordPress is not installed at site's root (ie: http://mydomain.com/wordpress, etc)

Get the info and download the new version at this link.

Inline Google Maps plugin updated to version 1.1

Friday, September 15th, 2006

I have updated my Inline Google Maps plugin to version 1.1 today. The hightlight of the new version is much improved handling of HTML inside the marker description field. You can now basically use any HTML you want for description, unless it contains single quotes :)

Have fun with your maps! :)

Easy Inline SWF 1.0 Plugin for WordPress

Wednesday, September 13th, 2006

There are several plugins to display Flash content for WordPress, but they don't make it easy for a user to insert Flash. They ask you to put some weird tags into your post, set Flash dimensions.. Well… NO MORE OF THIS PAIN! :) (cool CM huh ;) (more…)

WordPress: how to hide other users' posts in admin panel

Monday, September 11th, 2006

I am working on another WordPress-based system currently, and have faced a problem when I have many users who can log into WordPress admin panel to post their blog entries. But doing so, they all can see each others posts, even though not being able to edit any post but their own's.

From users  point of view, it is not the best thing in the world to look for your own posts in the list, especially if there are lots of users in the system.

So, here's a simple solution for the problem - after logging into the system, non-admin users will be able to only see their own posts in the Admin -> Manage panel. The only thing is that I seems no plugin solultion is possible so you have to add 3 lines to one file.

The file you have to add these lines is located in /wp-admin/edit.php file in your WordPress installation. You have to go to line 150 (or near it, where it says:

if ($posts) {
$bgcolor = '';
foreach ($posts as $post)…..

..etc

Now, just add the following code ABOVE the one mentioned above:

if ($userdata->user_level<10) {
    $posts = query_posts("author=".$userdata->ID);
}

So, in the end you will get something like that:

<?php

if ($userdata->user_level<10) {
    $posts = query_posts("author=".$userdata->ID);
}

if ($posts) {
$bgcolor = '';
foreach ($posts as $post) { start_wp();
$class = ('alternate' == $class) ? '' : 'alternate';

You're done! Now all non-admin users will see only their own posts :) Simple and easy. Have fun. 

Inline Google Maps for WordPress

Friday, September 8th, 2006

There are several WordPress plugins for showing Google maps on blog pages exist, but unfortunately, they are all kind of do "too much" :) Like displaying your posts on a Google map, or something like that. What I needed is just a simple plugin which would allow me to embed a Google map into my WordPress blog pages, anywhere I want, preferrably with a single line of simple code. There was nothing like that so I have wrote my own plugin. It's easy to use and install, and works fine so.. here we go :)

(more…)

Integration of Spry and PHP/MySQL

Wednesday, July 5th, 2006

Adobe have recently released its Spry Ajax framework for public beta-test by developers and I've been playing with this baby for a while. And here's some kind of report of what I have learned.

(more…)