Blog moved!
June 26th, 2007I’ve been using a new blog for a while. This site will no longer be updated, please go to http://eirikhoem.wordpress.com/.
I’ve been using a new blog for a while. This site will no longer be updated, please go to http://eirikhoem.wordpress.com/.
The tutorial I’m working on has been moved to http://prado.eirikhoem.net/cm/. The site will be updated a few times a week I hope, and there will be a SVN repository with the code available free of charge. I’ve recently outlined the extension plans and I’ve decided to ship the system with a basic web shop module to show it off.
I’ve been working on a tutorial for intermediate Prado developers lately. It covers the popular topic of CP/CM systems such as Facebook, MySpace etc. The tutorial is not even close to being complete, but it already has some nifty tips and ideas to get you started. You can find the wiki page for it here.
A quick recap of requirements and functionality :
Requirements
Features
Things are starting to shape up over at the Prado lair, and 3.1 hit beta on April 9th. The goodies include active controls (ajax), web services, several new data access layers and controls, a bunch of new demos and lots of minor tweaks and bug-fixes. Go here to read the release notes.
I’m not dead, just bussy. I’ve spent most of my spare time doing Prado related work and looking for a new apartment. I plan on moving later this month if everything works out.
Recent Prado tutorials:
Oh btw, Seasick Steve is playing at Cafe Mono later this month. Event details here.
I’ve been hired as a Software Developer with Telio Telecom AS. I’ve been working there for 1.5 years now, doing support, documentation, curses for new employees, building various software etc. I welcome the change and I’m really excited about getting my hands dirty.
So, I’ve installed ubuntu on my development machine. It currently dual boots with XP since I’m using Visual Studio as well. The installation was pretty straight forward. The only problems I had was configuring Xorg to support DRI (direct rendering). I spent most of Friday and some hours on Saturday figuring this out. My card is a ATI Radeon Mobility 9600 (RV350). I’ve tried ati, radeon and fglrx drivers without any luck. I’ve hacked the xorg config to pieces without any luck. The ubuntu and xorg messageboards / mailinglists gave me a few pointers, but nothing that was really usefull.
Then I came across a forum post pointing me to http://dri.freedesktop.org/snapshots/. I can’t find the source for the post now, but it specified that I should use the common-20060325-linux.i386.tar.bz2 snapshot. I downloaded it, unpacked, killed X, ran install then startx. DRI was up and running.
I decided to give Beryl a try, and after some tweaking I got it up and running. If you’ve never heard of Beryl, check http://youtube.com/watch?v=gQ-cjKUowT0
We’ve started a Prado PHP extension project over at the prado forums. The idea is to port some of the core classes from Prado to a C extension in PHP. The goal is to get rid of some of the overhead that Prado produces. Please take a look at http://trac.pradosoft.com/extension if you are a C coder. I’m currently setting up a “how-to” for compiling the sources on Windows (both command line and VS.net). The first milestone is to port TComponent. Check this thread for more info.
All right, I’ve completed my first major Prado application!
(Prepare for a long read.)
It’s an application for managing logging of various things. I can’t really show it off or go into detail about certain things since it’s an internal business application, but I can talk a bit about it.
First, a bit background info. The solution I’ve built is v2, meaning a “new version” of a current tool. The previous solution was an ad-hoc system that was hacked together in a hurry to meet some basic / urgent demands. After reviewing the current code base, new requests and doing some concept spikes we decided that a total rewrite would be best for everyone involved.
I’ve been working against trunk all the way since I really needed active controls and various other features (web services for one). I know this is not an ideal way to go when developing (since changes often causes a bit of problems), but it’s been worth my while. The development process has been XP-ish. We plotted out the direction we wanted to go, and I started building a base for the project. Ideas were tested out as “proof of concepts”, and either discarded or implemented based on the feedback. It’s been a one-man show, but I’ve gotten key input on design etc from a two very helpful co-workers, and feature requests were served from a number of people.
Quite a few custom controls were created, and I came to refactor / merge / split them several times. At the end I’m quite pleased with the current state of things.
The project has taken a few months to complete, and it landed on about 10 000 lines of code.
I can’t go in to details about what kind of logging it handles, but I’d like to write a few lines on how the logging process works. I spent a great deal of time finding a solution that was extendable, flexible and was able to deliver statistics.
The logging forms are loaded from my database, which has the following structure:
Category
Subject
SubjectQuestion
Question
Answer
Subjects can share questions, but each question has its own set of answers. Reason for doing this is that most of the subjects has the same questions, and to be able to create statistics as well as not having to create questions several times this seemed like a good solution. The only “downside” is that I’m forced to do a few extra lookups when building the logging forms.
Each question has a data type (checkbox, dropdown, single / multiline text field, radio button atm) which determines how it should be displayed on the logging forms. The core component is a control I call “composer”. It has a ActiveDropDown list with all the categories, and once a category is selected another dropdown list gets populated with the available field subjects (on callback). Once a subject is selected I feed the subject ID to a SubjectForm control (that reloads on a callback), which basically holds a repeater of QuestionControls. The question control is responsible for building the actual TCheckBoxList, TDropDownList, TTextBox and TRadioButtonList etc components.
When I need to retrieve the values selected, I ask the SubjectComposer for all answers, which in turn asks the SubjectForm. SubjectForm iterates over the QuestionControls in the repeater and asks them to build their answers sets. Once the SubjectForm gets answers from all of the QuestionControls it merges and sends them along.
I do sanity checks on the data underway. Once I got all the answers I store them in the database. Since it’s basically a key / value thing this was really easy, and I can pull statistics based on category, subject, question and even answer.
Each category and subject holds a tip and a url that the SubjectComposer displays above the actual SubjectForm. This is used to help the users.
The main logging form uses active controls wherever possible. I’m a huge fan of instant gratification, and I dislike page reloads when a user is sitting there waiting for results / information. Active Panel has been very helpful, since it allows me to just stuff components inside, feed them data and then just render then again during a callback. Among other things I’m bringing up logging history (populating a repeater inside a custom control inside a active panel) during callbacks.
In some cases a single subject is all that a given form needs. The SubjectForm is built to work stand-alone as well as via the composer.
This design is very handy for administrators, since they can build completely new logging forms from inside the application.
Platform and tools
A bit on what was used to develop and test the solution.
Development:
Hardware: 2ghz Centrino / 1gb ram (laptop)
OS: Windows XP SP 2
Webserver: IIS 5.1
PHP: 5.1.4
DB: MySQL 5.0.11
Editor: Notepad++ (this is a kickass code editor btw)
Misc tools for DB: MySQL Administrator and MySQL Query Browser.
Production:
Not really able to comment on this.
Cache
Using APC to speed things up. I’m also caching a list for TAutoCompleter with around 2000 items (using apc_store / apc_fetch) among other things.
Database
Using MySQL 4.1.21 with a custom transaction manager to handle access to the database. I want to give away the source for that, but I’m not sure if I can. I can however show the general usage:
$newItem = new SomeItem(); $newItem->data['title'] = "this is the tile"; $newPerson = new SomePerson(); $newPerson->data['title'] = "name here"; $itemSelect = new SomeItem(); $ops[] = array($newItem,'insert'); $ops[] = array($newPerson,'insert'); $ops[] = array($itemSelect,'select'); $res = RunTransaction($ops); if (empty($res[2]) throw exception; $itemlist = $res[2]; $this->SomeRepeater->DataSource=$itemlist; $this->SomeRepeater->dataBind();
Inside the repeater in the page template:
<%# $this->DataItem->data[”tip”] %>
Each class inherits a super class that builds the SQL. If a class needs customized sql, it can just override the super class code. The classes also support conditions (for update, delete etc) with $itemUpdate->conditions[”id”] = 2211;
This was a bit messy when working with dropdown lists, since they didn’t swallow my classes. Easily solved by doing the following before binding:
foreach ($itemlist as $item){
$newItemList[] = $item->data;
}
I can’t really go into detail about what the application stores of information, but I’ve tested it with around 18 million rows of data to make sure all indices etc were working like they should. I really learned a lot from working with a database of that size. It gave me a different perspective of performance and how to tune things.
Web Services
The application exposes parts of the data via a web service.
I’m very happy with the result, and I would like to thank the guys over at the Prado forums for answering questions (even if they’ve been really stupid sometimes). I’ll be working on extending the application for a while, and plan on doing some really neat reporting features where administrators can order finished excel reports to their mailboxes.
I’ve made a profile module for Prado that lets you store user preferences etc in a database. I got the idea from the ASP.net Profile classes (visit) . At the moment the module uses SQLLite as storeage engine, but I plan on adding support for XML and SQL databases. The module overrides PHP’s “magic methods” __get and __set, which makes access to the keys really easy. I’ve submitted this to the Prado TRAC asking them to add it to the framework. The code could use some cleaning.
Useage:
$this->Profile->SomeSetting = “some value”; // creates the key SomeSetting for the current user ID with the value “some value”
$foo = $this->Profile->SomeSetting; // retrieves the value of SomeSetting for the current user ID
Download ProfileManager v1.0 - http://php.eirikhoem.net/ProfileManager.phps.