Monday, July 20, 2009

The Hypogeum PHP Framework

I finally finished the one to many workings of the PHP Framework (Hypogeum) I am building. The framework is geared to be simple yet efficent. Each object has a database definition that links it to one or many tables in a database (ie: a user has user info in the "user" table, and the users avatar resides in the "avatar" table). Once defining your user with one simple array, the class autolads your data and gives you all kinds of ways to manpulate that user, including ways to extend your own functions (like a login function) off of the class. Here are a few quick examples as to things you could do with Hypogeum:

// get user with the unique_id of 1 from the database
$me = $c->user(1);

// echo out the users name
echo $me->attr('username');

// write a new user name to memory
$me->attr('username', 'MyNewName');

// save the users new name
$me->save();

Now the neat part is, all of the tables are bound to the same object, so lets say you want to change the users avatar image title, but thats not in the user table! no fear. You have already told the user class that we have multiple tables.

//set new avatar title
$me->attr('avatarTtitle','This is my new title');

//save the avatar title
$me->save();

The class knows that the 'avatarTitle' field exisist in the 'avatar' table, so it writes accordingly. If you have multiple fields with the same name, its as easy as:

$me->attr('avatar.avatarTitle','This is my new title');

The framework knows to look for a period, and try to use that as a table name. If it cannot, it throws an exception. And i know what you're thinking; "what if i put $me->attr('avatar',"x'; Drop Table users;")"? Well, a few things. If you wanna break your own database, go for it. However you wont be able to use my framework. Everything that interacts with the database is made safe via php filtering, but before that it has ot match the Regex that you define for each field.

So far i bet youre saying "big deal. so you can get one user from a table". Heres a few more options:

$us = $c->user->search('Jim');
foreach($us as $key => $val){
echo $us->attr('displayname');
}

This will allow you to search the user table (on the field or fields you have mapped for string seraching) for users with name 'Jim'. Lets say you want to find all users that have the letters "er" in their last name.

$us = $c->user->search('er',true,'lastName');

The second argument in the search method tells the function to perform a SQL Like search. The third binds the search to a custom field (any field mapped to the table).

If you want to find all of the users that are between the age of 18 and 25, you simply:

$us = $c->user->searchBetween(18,25,'age');

if you want to get all of your users:

$us = $c->user->getAll();

Now heres where i get to the awesome part. You can map objects (oe to many) together. Lets say you have a table of user attributes such as "happy, sad, flaky, duck-like, etc..." and you want to map these attributes to a user. With one line of code in the user class:

// table, id to map from, id to map to
map( 'user_attrib', 'user_id', 'user_id' );

you will automaticly map those attributes when you get your user info. so now, when you get your user info, the mapped data comes with it.

$me = $c->user(1);
echo $me->attr('username')." is:\n";
foreach($me->getMapChildren() as $key => $val ){
echo $val->attr('attributeName')."\n";
}

This would output something like this:
Tendrid is:
happy
duck-like
etc...

It only outputs the attributes that match the current users user_id in the attributes table. And yes, it scales. Even if you get all of the users in the database (say you have 1000), that only requires one sql statment. Once it retrieves all of the users, it then performs a second SQL statment based on a list of all of the ids. So even with 1000 users, all having 50 unique attributes, you only have 2 sql statments. Also, if the attribute already exisist in memory (based on the unique id of the class. In this case being attrib_id) then the framework does not include that in the SQL query, instead it just maps a reference to the attribute already existing in memory. This type of read-check occures on all objects. ie:

$c->user(1);
$c->user(1);

Would only result in one SQL statment.

On top of all this sweet stuff, the framework also has an extended layout class which has a template system based on sprintf expressions. Once you define the objects html template, you can simply do this:

$us = $c->user->getAll();
foreach( $us as $key => $val ){
$val->draw();
}

This will pass the objects current parameters into the template, and output the object formatted in the HTML directly to the browser. The draw method even supports custom sub templates (such as different sizes) all of which are indavidaly set.

$us = $c->user->getAll();
foreach( $us as $key => $val ){
$val->draw(SMALL);
$val->draw(MEDIUM);
$val->draw(LARGE);
}

There are a lot more features to this framework, and i will go over them in detail in the future. The framework will eventually live at hypogeum.net but there isn't much there now :)

No comments:

Post a Comment