PointClickPress Alpha 5

Over the weekend I release the fifth alpha build of PointClickPress. Next stop: Beta.


The Kohana 3 Framework

For a year now I’ve been working on a hobby opensource PHP project (PointClickPress) using the Kohana framework.

After grappling with the beast that is the Zend Framework and others I eventually settled on Kohana because of its simplicity and speed. Kohana was originally a community developed branch of the popular CodeIgniter framework, but with the release of version 3 it has taken on a life of its own.

My previous framework experience has been with the two big Coldfusion frameworks Mach-II and ModelGlue; and while both of these frameworks are excellent at organizing large Coldfusion projects, the XML config file(s) in both frameworks have always been a pain point for me. It was great to work with a framework that doesn’t require endless tinkering with XML.

I’ve really enjoyed working with Kohana. It is unobtrusive in your code and provides a straightforward platform to build your application on. You can use as much or as little of the functionality it provides as you need. Its allowed me to focus on building the app logic and not creating low-level functionality.

If you are about to start building a new PHP app I recommend you give it a try.

Using Prepared Statements With Kohana 3

I just discovered this tonight. (It wasn’t hard, I just had to RTFM).
In Kohana 3 you can query using prepared statements very easily. Prepared statements are important to protect against SQL injection attacks.

Below is a simple example:

$q = 'SELECT * FROM myTable WHERE id = :someId';

$results = DB::query(Database::SELECT,$q,TRUE)
  1. The first step here is to set a string in the query that is a place holder for the value that will be passed in seperately. In this case the placeholder is “:someId”
  2. Next, when calling DB::query, the first argument must be the object that Kohana will use to hold the results. In this case that object is Database::SELECT
  3. Then you pass in the information to the query using “->param(‘:someId’,$MyId)” This says that the value for ‘:someId’ is $MyId.
  4. Finally you can execute the query.

For those of you who are familiar with Coldfusion this is exactly how cfqueryparam works behind the scenes; it creates placeholders and then passes the data in seperately. Cfquery then returns a cfquery object just like how Kohana is returning a DB::SELECT object.

php5apache2_2.dll missing from PHP 5.3 zip

Today I did a reinstall of Apache and PHP. I used the latest versions of both Apache and PHP.

I downloaded the VC6 5.3 zip file but came to a problem when trying to install PHP as there was no php5apache2_2.dll file included in the zip download. I had downloaded the non-thread-safe version of PHP5.3. Apache2.2 only works with the thread-safe version, but the PHP downloads page does not make this clear. The PHP download page says:

Which version do I choose?
If you are using PHP with Apache 1  or Apache2 from apache.org
you need to use the VC6 versions of PHP

So for anyone else having this problem, use the thread-safe version!

(and skip the installer: its useless)

PHP, multiple requests, and slow load times

Recently I did some major updating to a web application I wrote a few years ago. The web app was the usual LAMP stack and ran on 10-20 public kiosks.
The web app allowed an admin to run two kinds of reports on the data. The first report took a very long time to run, but the second report was much simpler and was usually quicker. After all the updates were done suddenly both reports took forever to run.

I had updated MySQL to the latest version and the database architecture had changed to support new features so I spent a lot of time re-examining how the db was set up and checked the indexes on the tables.

I then looked at the queries to see if any of them could be optimized. I added timers around queries that I thought might be slow, but everything seemed normal. Yet still the request times were abysmal.

I tried using xdebug to see if there were any processes that were being called that I was missing when reviewing the code, but everything was as expected there.

In the end I finally realized that the problem was with session. session_write_close(); was not being called in the reports scripts and so each request was locking the other out until it was done generating the report. This was a very simple thing that I overlooked.

When debugging its always best to start with the simple and move towards the complex. Checking that session was properly handled should have been one of the first things I checked. Long load times on concurrent request should’ve been a red flag, but so much had changed that I didn’t start at the beginning and instead dove into more complex areas that only muddied the issue. Its the sort of mistake that you tell yourself you’ll never do again, but somehow you end up repeating anyway.