Enums in PHP

Thursday, August 14th, 2008

I’ve been working on a project lately where I’m rolling my own basic role-based access control (RBAC) system. In experimenting with different ways to handle the role definitions, I realized that it’d be pretty nice to have a basic enum() function or construct, as a quick, convenient way to define a set of constants. There’s this option:

1
2
3
4
5
<?php
    define('ADMIN', 0);
    define('MODERATOR', 1);
    define('EDITOR', 2);
?>

but that isn’t exactly succinct. I’d rather have something like this:

1
2
3
4
5
<?php
    enum('ADMIN', 'MODERATOR', 'EDITOR');
    // ADMIN == 0 (true)
    // MODERATOR == 1 (true), etc.
?>

You can kind of mimic the enumerated values with arrays like so:
(more…)

Clean URLs: basic mod_rewrite rules

Thursday, July 3rd, 2008

I’ve been using Comb with a few more projects recently. The main point of Comb is to structure the code in such a way that the request handlers get accessed directly via Apache, as opposed to rewriting the entire URL, and making PHP dynamically include or instantiate a request handling class (i.e. Action, Command, etc).

For example, you might have a registration form that is accessed like this (pseudo-HTTP):

1
2
3
4
5
# display the registration page...
GET  /register.php
 
# registration form submits to...
POST /proc_register.php

I personally hate that naming convention because it reminds me of how I wrote code 5 years ago, and it’s just plain ugly.

Here’s a cleaner, friendlier approach that I’d rather use:

1
2
3
4
5
# display the registration page...
GET  /register
 
# registration form submits to...
POST /register

(more…)

Pagination with MySQL and FOUND_ROWS()

Tuesday, July 1st, 2008

Jody clued me into a convenient method of paginating a result set from MySQL. Since he hasn’t blogged about it yet, I will >:-)

In the past, I’d issue two queries back to back, similar to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?php
    $page = isset($_GET['page']) ? (int) $_GET['page']: 1;
    $size = 10;
    $offset = ($page - 1) * $size;
 
    $db = new mysqli("localhost", "drew", "mypass", "db");
 
    $sql = "SELECT username FROM user LIMIT $offset, $size;"
         . "SELECT COUNT(*) FROM user";
 
    $users = array();
    $total = 0;
 
    if ($db->multi_query($sql) && $res = $db->store_result())
    {
        // fetch this page of user records
        while (list($name) = $res->fetch_row())
        {
            $users[] = $name;
        }
 
        // fetch the TOTAL number of users
        $db->next_result();
        list($total) = $db->store_result()->fetch_row();
    }
 
    $pages = ceil($total/$size);
 
    echo "Total Users: $total<br>";
    echo "Total Pages: $pages<br>";
    echo "Current Page: $page<br><br>";
 
    foreach ($users as $u) echo "$u<br>";
 
    if ($page > 1) 
        echo '<a href="?page=', $page-1, '">&laquo; Prev</a>';
 
    if ($page > 1 && $page < $pages) 
        echo " | ";
 
    if ($page < $pages) 
        echo '<a href="?page=', $page+1, '">Next &raquo;</a>';
?>

Take note of Line #8. The first query grabs the specified page of results, the second simply does a full count of all rows so I could calculate the total number of pages.

What sucks, however, is if the query is more complex, especially if the various parts of it have to be dynamically generated, e.g., table joins, conditions in the where clause, etc. In such a case you’d have to change the second query to get rid of the column list SELECT column1, column 2... and make it SELECT COUNT(*). Also, you’d have to toss out any ORDER BY and LIMIT clauses.

MySQL allows you to simplify this extremely common scenario by using the FOUND_ROWS() function. In the above code, you can simply modify the query itself:

1
2
3
4
5
6
7
8
9
<?php
    // ... change this:
    $sql = "SELECT username FROM user LIMIT $offset, $size;"
         . "SELECT COUNT(*) FROM user";
 
    // ... to this:
    $sql = "SELECT SQL_CALC_FOUND_ROWS username FROM user LIMIT $offset, $size;"
         . "SELECT FOUND_ROWS()";
?>

The rest of the code remains the same and will give you the exact same results.

The speed of this approach can vary depending on how you have your table(s) indexed, and the complexity of the query itself. In other words, in some circumstances it may be faster to actually run the LIMITed query followed by the appropriate SELECT COUNT(*) FROM ... query as in the first example, but the primary benefit is in the simplification of the query itself.

Comb: auto_prepend_file, output buffering, and mod_rewrite

Friday, May 9th, 2008

I’ve decided to give a name to this barebones framework that I’ve been playing with for the past couple of months. I’m calling it Comb. Unfortunately it takes a long time to fully explain the thinking behind the name. Similar to Camber, however, the jist of it is simplicity; think “get the tangles out of my code”. Plus comb is a lot faster to say and type than MVCish-framework-based-on-autoprependfile-and-output-buffering.
(more…)

Object-oriented controllers bug me

Tuesday, March 11th, 2008

I thought I might take a little step back here from my previous entry regarding my simplistic, not-all-that-original MVC using auto_prepend_file. I realized that I didn’t really explain why I occasionally get in that “there’s-got-to-be-a-simpler-way” frame of mind.

As I was building Camber, I made it a point to stick with an object-oriented design as closely as possible. The bootstrap script (i.e., index.php) simply sets up the basic environment, creates the main objects that are needed for the application, and starts things flowing. To re-cap, the whole life-cycle for a request in a Camber application is:

  1. Create the Application object
  2. Create the Controller object by passing in the Application
  3. Call $controller->getResource() which returns a Resource object
  4. Call $resource->run(), which returns the Response object
  5. Call $response->send() to send the response back

(more…)

Poor man’s MVC: PHP, auto_prepend_file, and mod_rewrite

Wednesday, March 5th, 2008

I often get the impression that there’s too much unnecessary complexity in the approaches to MVC that are currently in use in PHP, primarily with regard to request handlers and controllers. I’m even guilty of it myself with my ironic attempt at object-oriented simplicity, Camber. So when the mood strikes me, I’ll poke around in forums and articles and look for novel approaches to these problems.

A few years ago, Harry Fuecks posted an entry on his wiki-in-progress regarding PHP and the Front Controller design pattern. I’ve stumbled across this entry a few times before, but I always left it for dead, thinking it was just too simplistic. But recently I decided to try picking up where he left off at the end of his entry to see for myself how far the technique could be taken.

It’s nothing new really. The idea is to use auto_prepend_file and auto_append_file to control the global aspects of your application. For those who are unaware, these two directives allow you to specify scripts that you want to run just before and just after every requested PHP script, either on a per-directory basis, or throughout your entire virtualhost. For example, assume you’ve got a simple personal web site with a page called contact.php that looks like this:
(more…)

Camber - a minimalist LAMP framework

Friday, June 8th, 2007

Over the past few months I’ve been adding code to this previously unnamed LAMP framework, but I’ve honestly been reluctant to call it a framework. That’s what it is though, so instead of constantly referring to it as “my little minimalist pseudo-framework”, I decided to give the thing a name. I’ve been mulling it over for several months now, and finally settled on Camber as the name. I wanted to be sure that it was easy enough to remember, but also meaningful to the overall goal of the project. According to Google:

Camber: The curvature of a structural member for the purpose of offsetting the deflection when loads are applied.

Camber is not a complex idea, nor is it difficult to implement where it’s needed. It’s used in many everyday load-bearing applications; the wheels of a car, the shape of skis and snowboards, the bottom of a bridge, the shape of a wing. The performance of each of these is greatly enhanced - if not utterly dependent - on something as simple as the underlying negative curvature.

Sounds like a pretty good description of a web application framework, eh?

Unfortunately, I’ve been really slack about keeping this here blog up to date with the actual code I’ve been writing. I have a tendency to drone on and on about each concept of the system, so I think I need to take smaller bites. One post per day maybe, with no more than 2 or 3 snippets of code.

Evolving Framework, Step 4: Handle requests with a request handler

Sunday, April 29th, 2007

So, picking up from where I left off in Step 3, cleaning up the server-side, we’ve now got a simple HTML form that sends a clean request into the server, and a nice little Request class to make the incoming data easy to work with. To jog your memory, the form looks like:
(more…)

Evolving Framework, Step 3: Cleaning up the server-side

Tuesday, January 30th, 2007

Once I had my virtual host set up to route all requests into a single script, I then had to figure out what to do with each request. I knew that the essential request information was available in the $_SERVER autoglobal, but I wanted a cleaner way of dealing with the request. So I put together a very simple Request class, which I saved in the document root as Request.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php 
class Request 
{ 
    public $method; 
    public $url; 
    public $parameters = array();  
    public function __construct() 
    { 
        $this->method = $_SERVER['REQUEST_METHOD']; 
        $this->url = $_SERVER['SCRIPT_URI']; 
        $this->parameters = $_REQUEST; 
    } 
} 
?>

I then altered index.php to contain the following:

1
2
3
4
5
6
7
8
9
10
<?php
    include 'Request.php';
 
    $req = new Request();   
 
    echo "Method: {$req->method} <br />";
    echo "URL: {$req->url} <br />";
    echo "Parameters: <code>" . print_r($req->parameters, true) . "</code>";
 
?>

(more…)

Evolving Framework, Step 2: Make PHP understand the clean URL

Sunday, January 28th, 2007

So why am I bothering with “clean” URLs? For several reasons really. For one thing, they look nicer than un-clean URLs. I would much rather get rid of something like, this:

http://www.example.com/forumDisplay.php?fid=17

and instead use something like this:

http://www.example.com/forum/general

But aesthetics aside, why should I bother? My reason is inspired by Roy Fielding’s REST. I won’t try to get into the guts of it here, partly because there’s alot to it, and partly because my grasp of it is far from complete. Regardless, what I’ve taken from my brief introduction to it is a resolution to build applications from a resource-centric point of view, as opposed to a functional, process-centric point of view. Instead of building a collection of scripts that expect data to be passed in so that they can spit data out, I decided to try to build a system of resources that can be manipulated.
(more…)