Slashdot Mirror


Elegant PHP Architectures?

akweboa164 asks: "I work as a lone developer creating small to medium scale PHP/MySQL websites for different clients. I have been doing this for about two years now, and have tried different things as far as website layout/architecture goes. With sites that use the fusebox architecture, front controller (thanks J2EE), N-tier, to having a simple 'include(config.php);' line at the top of every file, I am left with the feeling that all of the sites I have created are 50% elegance, and 50% nasty kludge. I am left with a sinking feeling because I know that they could be better, but I lack to expertise and experience to make them that way. I am looking for overall architecture that is open and fits within the constraints of PHP (ie. relying little on OO) and separates logic, makes updates easy, etc. I wanted to ask Slashdot's crowd of web developers what their most elegant code layout/design web solutions were, and what advice would you dish out to new developers, as well as seasoned professionals."

12 of 118 comments (clear)

  1. web apps just aren't there yet by MikeRepass · · Score: 5, Informative

    I feel ya.

    Personally, I deal with different technologies, using ASP.NET (the horror!) to craft a rather random assortment of inhouse management tools for an IT organization, but many of the issues we face are the same. From ye olde days of ASP 3.0 with the ugliness of "includes" to a modular, n-tier approach, I'm always left with an unshakeable feeling that things could have been done better. The kludge that is modern web application interface (that is to say, HTML, J(ava)Script, etc) are too scattered and poorly supported to make anything approaching an "elegant" web application. (Btw, I'd love to be proved wrong here ...).

    Here are the few suggestions I have which I can confidently say have improved my productivity. There probably the same things that everyone has come across, but maybe if I throw them out here I can invite some discussion.

    Separate the task-at-hand and its implementation logic from the presentation layer. For instance, I normally write all of my business logic and database code as if it were just going to be an entirely separate library, and not particularly targetted towards web dev. This not only enforces solid library design principles, but allows me to debug and test using simple command line interfaces to the library. Approaching your code from a new direction (in this case simple user apps) frequently opens up entirely new ideas and perspectives. Once you've done this, the majority of your "behind-the-scenes" web code can just be a wrapper for this library, and then all you have left is the presentation logic. This has helped me immensely in the areas of scalability/integration and portability.

    Second, never ever do any cosmetic presentation work until you're absolutely sure you have a beta (or better) quality base of business logic you're prepared to stand by. Adding the presentation logic to a web app too early is sort of like munging in command line options to a good ole console app: if done improperly, things quickly get out of hand and you have to code in more global scope hacks than you'd like to admit. Personally, after many bad experiences with this problem, I do *all* my testing on blatantly ugly hand-crafted html pages until I'm sure I've got things right.

    Third, don't focus on a "page" as a discrete, targeted development object. Rather, the actual pages should be afterthoughts. Try to engineer solid "user-interface" components, and then plan on the final web pages as simple composites of these components. I estimate that, when I sketch out my initial concept of the pages and interface layer of a web app, more than 50% of the various tasks presented to the user will change drastically in scope before I'm even done developing. You realize that certain tasks just aren't needed, certain things are inconvenient, etc and using a component model to the presentation layer helps reconfiguring immensely. One of the biggest frustrations with web application is that, when different ideas are flying through your mind, its difficult to figure out all that must be coded in order to test them out. You think, "hmm this might work!" and find yourself having to chase down random bugs and make changes in five different files just to get a prototype working. Using a component model helps quite a bit in this department.

    In terms of architecture, the only vaguely successful model I've come across is (once you've got a solid library backing you up...) model your application as a set of distinct user tasks. Allow each task to develop independently, and the step back and look at where the overlap is and what components are a good candidate for integration. Taking things on a task-by-task basis at the beginning helps immensely in bug detection also, because you're only focusing on one coherent progression of logic at a time.

    I realize that most of this is probably old news to any qualified web dev, but this is the stuff I have to continually force myself to do after two years in the biz, so perhaps it is of some use. Any comments, suggestions, rebuttals, etc I'd be glad to hear.

    Mike

  2. Some suggestions by Alpha27 · · Score: 5, Informative

    I like PHP alot for web development. I found it easier and less to code when compared to perl (I've done both for 3 years each). You've made a good choice with it. I haven't tried python, but i do hear good things about it.

    One important advice I would give is.... learn from your repetition. Meaning.. if you see that you code very similar functions or code segments that very ever so slightly, maybe there's a new function in there, that could emcompass them all.

    For example:

    • writing tables: I wrote a class to take an array of array, and spit out a table structure. Beats having to write echo statements with td tags, mixed with variables.
    • simple dababase functions: I've knocked out a number of lines using simple code that does the same 3 steps into one function.
    • object oriented code: definitely helps out.
    • apply theory/concepts to work: I've seen the Model/view/controller example applied to non java languages. As well you can use cool things like XML/XSLT to handle data/presentation, there by allowing for multiple display formats.

    some times the elegance is in the hack. I rewrote an art project at the company I work for, using our product for the front end, and php for the backend within 6 hours. He originally wrote his from concept to product in a year. Not bragging, just saying. =)

    Look into some of the templating engines, like smarty.php.net, it's srecommended at a number of sites (I haven't used it yet), but it will allow for cleaner code, and that's what is important. Accessing code you can easily fix, and change the presentation when needed.

  3. My PHP tips by Imperator · · Score: 4, Informative

    I don't claim to be an expert PHP developer, but I have spent a fair amount of time with it. Here's what I've found works:

    • Every file includes base.inc.
    • base.inc includes a config file based on the hostname and port--this is to allow you to use the same code to run both testing and production servers. These config files are where you keep stuff like the directories in which to store files, the database config, and so on.
    • Use PEAR as much as you can. In particular, use PEAR::DB. Since you probably use the DB in every request, open it up in base.inc and store it in a global. Also, you never know when you'll switch to a different RDBMS, and if you have to modify every single call...
    • On that note, use PHP OO to abstract away the DB. Do it logically, not "one class per table". This way, when you change the database or even just the schema, only the library files need to change. If it's a big multi-user project, write regression tests.
    • If you're using the Zend Optimizer or a similar bytecode cache, go ahead and include all the library files from base.inc so you never have to worry about doing that.
    • Use CVS. Even if it's just you.
    • Use a good template system like Smarty. Just because PHP lets you mix code with HTML doesn't mean it's a good idea.
    • Write your own classes to handle any common task, even for something as simple as getCgiVar().
    • Keep the DB schema in one file so it's easy to read and modify.
    --

    Gates' Law: Every 18 months, the speed of software halves.
    1. Re:My PHP tips by Blaze74 · · Score: 3, Informative

      Take what the above poster said, but use base.php instead of base.inc. Using .inc files is asking for trouble when you deploy it on a server that does not restrict access to files with a .inc extension and someone decides to look at database_passwords.inc

    2. Re:My PHP tips by damien_kane · · Score: 2, Informative

      use base.php instead of base.inc

      Not only that, but in case you have some code in base.php that is not called as a function (for example your DB link), put something like this at the top of base.php:

      if (!isset($somekeyvar)) die();

      Then make sure you set $somekeyvar in everypage. This will make sure that code isn't accidentally run when some (non-)malicious user goes looking around.
      Alternatively, include base.php from a path which the webserver does not serve, but still has access to. For example, create a path /htdoc-includes, give the $webserver read access to the files inside it, and put base.php in there.In this way there is no whay that a user could call it from a browser independant of your main page(s).

  4. what I do... by Anonymous Coward · · Score: 1, Informative

    I use classes extensively in PHP, as well as PEAR whenever possible. It's slow sometimes and doesn't feel as elegant as Perl's add-on modules (yes I just used "elegant" and "Perl" in a sentence, I've done some nice stuff with mod_perl and XML) but it makes your code a lot cleaner.

    Separating code and presentation: well we all should realize 100% separation is impossible, but you should try as much as possible. I've been having good luck with Smarty. Basically you write a bunch of PHP code that computes all the parts of your page, then you send all that off to template code that generates your final page. This is a good system, even if you don't use Smarty (it could just be two different PHP scripts, one is a model, the other a view/controller).

    Basically you write your code, then you do the presentation, then you go back and adjust the code, then you adjust the presentation, after a few iterations it stabilizes nicely.

    Another interesting thing about Smarty: the author(s) of Smarty inadvertantly created a new programming language inside Smarty using Smarty tags, which isn't PHP, so you have this weird feeling of programming in two different languages... and it turns out to be a great way to keep the two realms separate (at least for me).

    I would recommend trying this approach, if you don't use Smarty, you could use PHP and XSLT: PHP code that generates very basic XML containing the data you want to display, and then a Perl or PHP or whatever script that just applies XSLT and then sends the HTML to the browser.

    I think this "two-stage, two-languages" approach has helped me keep everything separate in my mind, give it a go.

    And PLEASE, use PHP objects. Someday PHP will be a "good" programming language with good OO features, get used to what it has now.

  5. Re:Relying little on OO...? by thebatlab · · Score: 2, Informative

    Actually the following:

    object.person.bart_simpson.say("Bite Me!");

    wouldn't need to be dereferenced by hand.

    However, this would:

    object->person()->bart_simpson()->say("Bi te Me!");

    Method calls that return an object can't be immediately dereferenced in the same statement. Those would have to be dereferenced one by one.

    But I know what you mean though. It sucks that you have to do that :)

  6. Re:Relying little on OO...? by rempelos · · Score: 3, Informative

    PHP5 promises great features, but PHP4 still lacks lots of OO concepts.

    • No private/protected/public
    • No static class attributes
    • No abstract classes nor interfaces
    • No function overloading
    • Still experimental aggregation/composition

    ok PHP hasn't the great OO features that other languages have (like java), but most of the PHP programs are written by one programmer and for producing HTML code which isn't the same thing as developing huge projects in an enterprise logic.

    You can do OO-like stuff without the points above but at the expense of no encapsulation and ugly hacks.

    OO is all about encapsulating and ugly hacks are made because of ugly designs. There is a tremendous advantage when using the OO features of PHP, for example you can create a class that encapsulates the database connection and all operations to it.

    A very good example that demonstrates what you can do with the OO features of PHP is PHPlib, it has everything the original poster asks except it's based on OOP.

  7. Re:Java View/Model/Controller by amorico · · Score: 4, Informative

    This makes so little sense that I can only assume that Ms. Coulter is laughing her butt off at the moderators.

    There is no Java MVC for the web. You either roll your own or use Struts or Webwork or Maverick et al. MVC is a design pattern, which was correctly stated.

    That, however, was the extent of any correctness. The Model is the data, which in her case would be the MySQL held data. The view would be a generated html page, JSP, Velocity Template, XML/XSLT pipeline, or whatever display technology you would use. The controller would be something that receives requests from a web browser and then decides what action to take (pull data from a database, massage it, return it, and show a results page). Accessing the data is handled by Data access objects or delegates.

    If you don't know what in tarnation someone is talking about, don't moderate it down or up, just leave it.

    I am going to start using that line at work though. "If we use java this way we will be akin to apple!"

    --
    "The plural of anecdote is not data." -- Roger Brinner
  8. Re:Bite the bullet... by mrami · · Score: 2, Informative
    The common lisp part is probably a bit trollish, yes :) but the truth is there. Architectures like J2EE and PHP are very concerned about the mechanics of building the page (very important), but I don't see much structure regarding encapsulating user flow (also very important). True, there are wonderful things such as Struts that move far closer to that goal, but even so you end up managing multiple views, and maybe multiple controllers, when all you really want to say is something like
    user =
    readPersistent(User.newForm(username, password; username == $.username && password == $.password),
    "Please enter your username and password");
    doStuff(user);
    ...
    Ah, well...

    As for PHP, I use:

    • every file includes a common.php that defines your common functions, including one that generates a templated page.
    • use front controller when I can
    • data access objects and transfer objects (form and persist), with a nice generic renderer functor s to HTMLize your transfer objects.
    • data-intensive classes (like transfer objects) usually end up being arrays with type signatures as opposed to actual classes. If you're using your nice generic renderers, adding a column to a result set can boil down to a change in one place. I still call the classes, though, because to me they still are (I do dispatch based on their "type").
    I usually use this architecture. DB side: I have a DAO for each table used in a single-table query, along with a specialized DAO for each distinct join situation. These usually pass back a class that knows 1) the data and 2) whether it's a singular or tabular result (whether it was intended to ever bring back multiple rows). I then have a generic result renderer that will render anything, plus any specialized renderers. UI side: I have a generic form class that has a list of labels and references to the fields in the model they represent (or temp field definitions if the fields are not persistent). Then, of course, a generic form renderer + specialized. The rest is usually cookie-cutter.

    The caveat here, of course, is that I write mainly business apps, so consistency is the key. The genericity you find all over the place is a win for my kind of app.

  9. Re:Template Systems by dismayed · · Score: 2, Informative

    As a counter to this...

    If you have to hand off your code to another person who will be doing primarily design, for instance customizing the "look and feel" then using separate templates is really valuable. You will drastically cut down on "bugs" caused by changes in the logic introduced by a designer changing code accidentally.

    Even if PHP is the templating engine, separating the logic is important.

  10. Re:Oh, the pain of Zope by Anonymous Coward · · Score: 1, Informative

    I've used Zope and PHP, and they both have their strengths and weaknesses.

    Zope's documentation is painfully, hopelessly bad. That makes difficult to move to more challenging projects.

    I love PHP's online manual. The inline comments left by other users frequently help me figure out some odd error I'm having.

    I'd go on and on here, but I'm really supposed to be paying attention to my lecture here :)

    Froggie!