Background
Whats this all about - arent there half a dozen frameworks out
there already? or better know as a diatribe of disasters....
|
A long long time ago in the little land of net, there was a
few big php projects, things like phorum, imp and twig, where the early
starters....
Twig and Templating
I got involved in twig early on, it was a functional/procedural webmail
program. At the time this design and layout seemed like the best thing
since sliced cheese..
One thing however plagued the development, people constantly kept
poping up on the mailing list saying stuff like 'lets add javascript',
so it can do cool stuff like imp.... - but the core developers always
said NO - it was going to work on every browser, and be the only
webmail to do that!
What they didnt realize or deal with was that the design was flawed -
there was
no templating engine in there - all the output was
done using
for i = 0;$i<10;$i++ {
print "<some html>" .
htmlspecialchars($some var) ."<end html";
}
|
so to change the layout fully, would involve changing all the source
code - mmh, a slight problem there.....
one important lesson that was learnt with twig was the importance of
ensuring the applications had a 'single entry point' - eg. one file -
usually index.php was the only url used - this would initiallize all
the variables and redirect you to the correct part of the application.
|
Guideline : Single entry point
|
the alternative to this - used in things like mantis, phpbb, is to have
mulitiple entry points, and always include('some standard lib.php') in
the first line..
Nadmin & Templating V1
I was lead designer on the nadmin studio project, after working with
the midgard content management system for a while, I thought that
applying what we had learnt on the twig project to a user interface for
midgard would be a good idea. however one of the early sticking points
was templating.
Midgard has its own templating system, using tags like
<[include_block]> and &(echo_var); , however one of the early
problems we came across was that implementing an application where a
single url could display multiple views became very complex with the
basic templating system
Note however we should have done this!!! -
instead we went down the route of using FastTemplate
|
<?
mgd_eval("?>".mgd_template($template)."<?"); ?>
|
Fast Template
The solution we chose at the time was called FastTemplate [google
search], it was a simple search and replace templating system.
You created a new instance of it, then all the items you wanted to
display on the page, like title, you told it that 'title' was going to
be 'testing', then at the end of the 'application', it did a big string
replace on all tags and replaced them with the value of the variables.
- kind of like a brute force approach...
This worked quite well but had 2 serious drawbacks -
1. Performance - if there where alot of variables and blocks it would
be very slow. (not exactly fast)
2. Complex - doing complex block contructs (nested loops was very
difficult to do and debug)
Anyway - nadmin still has this and it's part of the learning
process..... - see the templating section for more discussion on
this.
|
Guideline : Never use FastTemplate!
|
OMPHP - crazy misadventures
Over time I always embark on crazy projects - converting Openmerchant
(perl) into PHP has to be one of the worst.. - given that there was
plenty of php shops starting up, and the conversion that was being done
on open merchant was really just another function/procedural mess....
As part of the vending project, I decided to merge omphp into
nadmin/midgard - it was a long and painfull task, but it became clear,
looking over the original translation that the midgard idea of using
objects to model each row of a table was very sensible, and by
extending that idea, I had the ideal place to put the logic of a lot of
the data manipulation. - inside the table object.
|
Guideline : Put the data manipulation in
clases tied to the tables
|
Object Orientation - conversion of the unwashed
For years I had known PHP had Object orientated programming, horde(imp)
used it, Fast Template was an object, Midgard used objects heavily. I
had been put off OO programming by Fast Template - it was klunky and
difficult to use, and even more confusing to modify.
(this
is more to do with the way it does templating than OO however)
What had happened with twig and nadmin, was that most of the code went
something like this.
do stuff....
include a few config files
set some variables
do stuff
print a header here
include another file
do some more stuff
print the body of the
application
print the footer here
do some stuff
|
If It was being clever - It might have added a few functions, to do
stuff that it repeated. These functions where put in files, in the lib
(library) directory, and given abutry names that sounded good at the
time. (like mail.php) - for all the mail stuff..
Result: what happened
very quickly was that most of the code ended up in the 'do some more
stuff' area, and everybody forgot which functions where in which
library file. - hence the functions never really go reused by anyone
other than the original author.
The more this happens the more you realize that there are a few
important rules in developing applications that you have to modify a
year after you wrote them "
where is the code that
needs changing/fixing" -
The guiding principle in later projects was to move to a situation
where all code was in an object, and each object had a specific role.
|
Guideline : Dont use functions, just use
classes & methods
|
PhpMole and Db_oo
About the time that all this was going on, I was working on a number of
projects - Vending Machine management systems for GSM modems, this
system grew out of the omphp ashes, and had it's own data object system
similar to that of midgard, (see data modelling - db_oo for full
details). initially the old way of procedural coding was merged slowly
with the data modelling concepts - so a hybrid of putting some data
logic into the data classes and then the output/page stuff was the old
standard way.... - this eventually has moved towards a total object
solution.
PhpMole was originally a port of Moleskine (Python) to php, Moleskine
was a totally object orientated application (as most desktop programs
should be), but I got very annoyed with python, partly due to it's lack
of variable identifiers (no $ sign), and mostly to do with the lack of
clarity in calling object instances and static instances of objects.
The Port to PHP, started defining some of the key rules of what later
has become the programming framework
|
Guideline : one class per file
|
now you know that if you a reading a program that uses this
object/class, it's going to be easy to find this code. - its going to
be in the
phpmole_transports_file.class
file (probably in
phpmole/transports/
directory!)
|
$array =
phpmole_transports_file::get_files($dir);
|
these static methods are not much different from 'functions' so even at
this level moving to classes will make a program easier to debug.
Phplib
one of the major projects I worked on, was helping build on an old
community website - something that had been put together over 2-3
years, and had grown slowly adding pages and features. This had used
the Phplib library to do things like page permissions and sessions, and
user preferences. - and like all systems that grow over time they
became less clean and more like a mishmash of problems waiting to
happen.
I had never looked deeply a phplib, and when I had glanced over it
before, It had never seemed that attractive. - Midgard and standard php
seemed to offer alot of what phplib had, and appeared to do it
better...., the site I was looking at had heavily used phplibs
database, sessions and authentication systems. It was the whole page
authentication system that struck me first as the most annoying.
Page Authentication
From the impementation that I saw, alot of things ran off the
auto_prepend_file.php - the one included using the php.ini setting, the
file did alot of things (include libraries, set up sessions, and run
pages !) - well theres a single entry point if I've ever seen one!!!!
Adding applications like phpbb to the site became very problematic,
partly due to this magic/nightmare prepend file, but also that the
prepend file actuall 'ran the applications', the model it used in the
prepend file was that each page that could be visited was listed in the
prepend file, along with it's permissions - like what type of user
could look at it.. - this basically meant to add anything involved
modifying this file (forgetting too meaning death and misery forever!)
It took a considerable amount of though and persuasion to work out a
better mechanism for this type of authentication, and in later
projects, the concepts of putting authenticaton onto the individual
page objects made conseraby more sense. - hence alowing a more
pluggable extendable system - add a page/application here /there, and
it can manage it's own authentication. The only thing the
authentication class did was say 'is anybody logged in', and 'who is
that person' - from then on you talk to the person object about group
memberships.
|
Guideline : Page classes are responsible
for who can look at them
|
Users and Groups
Almost every system I have worked on has had a different requrement for
user management, Midgard's User, Groups and memberships for the most
parts fits the basis of most requirements, however within a pure
midgard solution the only method to extend the user or group objects is
to add parameters, an extra domain/key/value table that could grow to
an enormous size, due to it's catch all nature.
In reality, the best solution is to custom make the Group/Person tables
per project, and allow them to grow/shrink as needed. - and any
unusual requirement can be delt with by extending the User objects. -
eg. at infinity email address etc.
Guideline : Dont try and fit square pegs
into round holes
Guideline : User/Group/Member databases
tend to be very specific
|
PHP Security
It was with much horror that I realized that this procedural step,by
step including method had so many potential security problems, PHP4.1.2
introduced the $_POST / $_GET etc. vars, as a result of far to
many
remote exploits being made posible by php's ability to automatically
convert ?xxx=yyy urls into $xxx. This was the key to making php
programming easy for everybody at the beginning, and was there to bite
everyone in the tail later.
PHP generally has a very nice variable scoping, all variables in
functions are local to that function - hence if you did everything
in
a function - even if these vars where available you would have to
explicitly use them by declaring - globals $xxx.
This was one of the major factors in deciding to move away from the
idea of outputting templates within a global scope, and rather
outputing the template from within a method, hence having total
controll over the variables being made available for display. - Along
with using $_GET/$_REQUEST etc. there is little need for global
variables.
Guideline : Dont use globals
Guideline : Output in controled Scope
|
A Framework from Scratch
I was lucky enough as part of my freelance work, to get involved in a
client who actually knew what they where doing, and how to go about it.
- Detailed, thought out specs (rather than 'we need a XXXX system, can
you build it, but I need it to do YYY and XXX, thats your spec..'). and
they had a sensible timescale (not 'we want it tommorow')...
The first task, being given these detail user requirements and
click
flow, was to look at the program structure, from the aspect of data
objects and key pages, the rest of this framework describes some of the
results of that project, both in terms of it success in design,
but
also yet more lessons that need to be learned to make it even better..
|
Guideline : Dont try create your own
framework - just borrow bits from everybody else!
|