Monday Oct 8 2007 10:57 am by Smokinn

Ok, some of you know that when I started my new job back in may, I was basically told we want new everything from scratch.

So we hunkered down and came up with a decent way of doing web development in PHP (there are many others but many more are horrible). We basically made a cross between Rails and J2EE, taking the parts we liked from each and making some up on the fly.

I obviously didn't re-implement everything we did because a) I'm too lazy and b) I didn't need it all. So the following is a description of all the stuff I didn't implement and at the end of the post there's a link to a zip containing the source code to this year's hockey pool app I wrote based largely off the ideas we use at work. The two second summary of the zip contents are: extremely simple MVC with a very basic ORM layer.

We have a "Framework" that automatically loads "Modules" if they're properly configured. There are only 3 configurations you need to do. You need a config.ini which tells the framework what mode to run in (local for development off our dev drives or live when deployed so that it negotiates connections with Strongbox, our security software) and gives the database connection string, a module.ini which gives 3 or 4 parameters and a navigation.xml which builds the menu on the left of the cms and also manages permissions.

The navigation.xml looks something like:

<action>

<name>polls</name>

<action>

<name>add</name>

</action>

<action>

<name>manage</name>

</action>

<name>edit</name>

</action>

</action>

<action>

<name>view</name>

</action>

</action>

It's not quite like that but this should give a good idea of how it works. The navigation menu will look something like:

POLLS (a header)

add (a link to action=polls/add)

manage (a link to action=polls/manage)

view (a link to action=polls/view)

Only the top-level of each category is drawn in the navigation. To access edit we need to go to action=polls/manage/edit and generally the manage page will show a list of all polls and they will have links to edit. We also manage permissions like this. We can give permissions to polls/add or polls/view without giving permissions to polls/manage/edit. It also gives us very basic logging capability. (And we can add more fine-grained logging through calls to the framework's logger.)

We also use Savant3 as our template engine which I'm not using for the hockey app. We have special functionality for ajax requests (if you pass guimode=ajax in the querystring it'll handle it as an ajax request) and we also get static page generation pretty much for free. We just need to add generate=true to the querystring and it'll generate a new page. Otherwise it'll serve a static page if one exists on any page defined as being static. Of course there are some parts of pages you want to stay dynamic (such as choosing a random poll on each page load instead of always the same one and ajax requests in general although that's a trickier issue) so you can put a special html comment we defined around any part of a template you want to keep as dynamic and it'll keep the php in the static page instead of the generated html.

So, as promised, here's a link to the source of the hockey app. None of it is commented but it's extremely straight-forward (I think). At work everything is commented with a specific style @description blah blah etc. It's useful because our editor (PhpED, a really great php editor) will give you the information in the comments if things are properly commented when you're looking for which function to call. Quite useful sometimes. So while the commenting is an exception, the rest of the coding style is pretty much what our entire codebase at work looks like.

One of the things you might notice when looking at the source code is that the ORM layer is nearly useless since I pretty much use the database field names directly in the classes. We solved this problem by having a method mapFields in the mappers that map db field names to the names we want. So when we first designed the db we also used the names in the classes as private members (since we liked the names and find keeping very short strings as names for db columns useless when you have an ORM layer, it just makes things harder to understand when looking at only the db without saving typing) but whenever we make a change to the db structure, we just need to add an entry to mapFields to keep everything working.

For example, let's say you have a db column called site_short_name in the sites table. It really pisses someone off because he finds the site_ prefix redundant. So he does into the db and renames the field. He also goes through the entire application and changes site_short_name to short_name. (He's very pedantic.) But he only did it for one project! He forgot all the others that also use the same classes. Now normally everything would crash in on itself (or at least the short names of all sites would be blank everywhere) but by adding an entry to the hash we store, in mapFields ('site_short_name' => 'short_name'), everything kept working because the fields are passed through the map and either can be used. It keeps things a little safer when multiple teams working on multiple projects use the same classes/mappers/tdgs.

I didn't implement the mapFields method because I'm alone working on the app and because the db structure isn't going to change but basically you just call mapFields with your result set as the first action in the load method, passing it your row and it passes it back properly mapped.

The ORM layer I implemented isn't exactly like what we use at work but it's fairly close.

Comments
Tuesday 16 2007 9:16 pm by Iouri Goussev

Yep, yep, good good.

One comment, I would not recommend doing this in the view:

// Only count the stats of the top 12 forwards

$defence_total = 0;

for($i=0; $i

Tuesday 16 2007 9:16 pm by Iouri Goussev

6; $i++)

{

$defence_total += $category_total[$i];

}

Calculations belongs to the model. Controller should push it to the view. I think your view is doing to much.

As a side benefit you can unit-test it (btw you forgot to include them).

Tuesday 16 2007 9:17 pm by Iouri Goussev

FIX YOU INPUT FORMS

Tuesday 16 2007 9:32 pm by Iouri Goussev

Btw do you want to go to the hockey game?

"Since 1988 the Concordia Stingers have faced off annually for the

prestigious Corey Cup, emblematic of men's university hockey supremacy

in Montreal."

http://athletics.concordia.ca/intercollegiate/mhockey/mhockey_coreycup.html

Alexandr Lebedev, his girlfriend and three of my friends you don't know and are going.

Wednesday 17 2007 7:37 am by Smokinn

You're right - I was being lazy and I'm doing too much in the view.

I sometimes have to get people to fix that at work since here I'm pretty adamant about doing no work in the template, only in the controller. For this app I got lazy.

About the hockey game - I might be going, not sure yet.

Post a comment
Name:
Email (optional):
URL (optional):
(Allowed tags: <a> <p> <strong> <em>)

Sorry, but due to spambots, to post I'll need you to prove you're human.

Of the six following animals, just select the two that are not fluffy

About the Site:

I might update. Don't hold your breath though.

About Me:

Name: Guillaume Theoret

Age: 804667657 seconds

Job: Mostly web dev

Some Friends:
Search:

RSS Feeds:

RSS