KEMBAR78
Organizing Your PHP Projects (2010 ConFoo) | PDF
Organizing Your
 PHP Projects
     Paul M. Jones
   ConFoo, Montréal
     10 Mar 2010

   http://joind.in/1289
Read These
• “Mythical Man-Month”, Brooks
• “Art of Project Management”, Berkun
• “Peopleware”, DeMarco and Lister




                    2
Project Planning
        in One Lesson
•   Examine real-world projects

•   The One Lesson for
    organizing your project

•   Elements of The One Lesson

•   The One Lesson in practice




                              3
About Me
•   Web Architect

•   PHP since 1999 (PHP 3)

•   Solar Framework (lead)

•   Savant Template System (lead)

•   Zend Framework (found. contrib.)

•   PEAR Group (2007-2008)

•   Web framework benchmarks

                                    4
About You
•   Project lead/manager?

•   Improve team consistency?

•   Want to share your code
    with others?

•   Want to use code from
    others?

•   Want to reduce recurring
    integration issues?

                                5
Goals for Organizing
•   Security

•   Integration and extension

•   Adaptable to change

•   Predictable and maintainable

•   Teamwork consistency

•   Re-use rules on multiple projects


                                    6
Project Research;
              or,
“Step 1: Study Underpinnings”



              7
Project Evolution Tracks
               One-Off
                Heap

              Standalone
                 App

  Library         ?
                           Modular App
 Collection

 Framework                    CMS

                  8
One-Off Heap
•   No discernible architecture

•   Browse directly to the scripts

•   Add to it piece by piece

•   Little to no separation of concerns

•   All variables are global

•   Unmanageable, difficult to extend


                                       9
Standalone Application
•   One-off heap ++

•   Series of separate page
    scripts and common includes

•   Installed in web root

•   Each responsible for global
    execution environment

•   Script variables still global


                                    10
Standalone Application:
   Typical Main Script
// Setup or bootstrapping
define('INCLUDE_PATH', dirname(__FILE__) . '/');
include_once INCLUDE_PATH . "inc/prepend.inc.php"
include_once INCLUDE_PATH . "lib/foo.class.php";
include_once INCLUDE_PATH . "lib/View.class.php";

// Actions (if we're lucky)
$foo = new Foo();
$data = $foo->getData();

// Display (if we're lucky)
$view = new View(INCLUDE_PATH . 'tpl/');
$view->assign($data);
echo $view->fetch('template.tpl');

// Teardown
include_once INCLUDE_PATH . "inc/append.inc.php";

                              11
Standalone Application:
  Typical Include File

// expects certain globals
if (! defined('APP_CONSTANT')) {
    die("Direct access not allowed.");
}




                   12
Standalone Application:
 Typical File Structure
 index.php               #   main pages
 page1.php               #
 page2.php               #
 page3.php               #
 sub/                    #   sub-section
      index.php          #
      zim.php            #
      gir.php            #
 inc/                    #   includes
      config.inc.php     #
      prepend.inc.php    #
 lib/                    #   libraries
      foo.class.php      #
      Bundle1/           #
      Bundle2/           #

                        13
Standalone Application:
   Support Structure
 bin/           #   command-line tools
 cache/         #   cache files
 css/           #   stylesheets
 docs/          #   documentation
 img/           #   images
 install/       #   installation scripts
 js/            #   javascript
 log/           #   log files
 sql/           #   schema migrations
 theme/         #   themes or skins
 tpl/           #   templates

 -- no standard naming or structure
 -- index.html file in each directory

                        14
Project Evolution Tracks
               One-Off
                Heap

              Standalone
                 App

  Library         ?
                           Modular App
 Collection

 Framework                    CMS

                  15
Modular Application
•   Standalone application ++

•   Same file structure and script style

•   One additional directory:
    “modules”, “plugins”, etc

•   Hooks in the “main” scripts for
    additional behaviors

•   Use global variables to coordinate
    between modules
                                16
CMS
•   Modular application ++

•   General-purpose application
    broker

•   All "main" scripts become
    sub-applications

•   Still in the web root, still
    using globals to coordinate



                                17
Application/CMS
             Projects
• Achievo         • Eventum     • PhpMyAdmin
• Code Igniter*   • Gallery     • Seagull*
• Coppermine      • Joomla/     • SugarCRM
                   Mambo
• DokuWiki                      • Vanilla
                  • MediaWiki
• Drupal                        • WordPress
                       18
Project Evolution Tracks
               One-Off
                Heap

              Standalone
                 App

  Library         ?
                           Modular App
 Collection

 Framework                    CMS

                  19
Library Collection
•   Specific, limited logic extracted
    from an app

•   Re-used directly in unrelated
    applications and other libraries

•   No global variables

•   Class-oriented

•   Can exist anywhere in the file
    system
                                       20
Library Project:
    Typical File Structure
Foo.php                 #    Foo
Foo/                    #
     Component.php      #    Foo_Component
     Component/         #
         Element1.php   #    Foo_Component_Element1
         Element2.php   #    Foo_Component_Element2
Bar.php                 #    Bar
Bar/                    #
     Task.php           #    Bar_Task
     Part/              #
         Part1.php      #    Bar_Task_Part1
         Part2.php      #    Bar_Task_Part2

                        21
Framework
•   Codebase

    •   Library collection

    •   Apps extend from it

•   Support structure

    •   Bootstrap file

    •   Public assets

    •   Protected assets

                              22
Library/Framework Projects
•   AdoDB            •   Lithium        •   Savant

•   Cake             •   Mojavi/Agavi   •   Seagull *

•   CgiApp           •   PAT            •   Smarty

•   Code Igniter *   •   PEAR           •   Solar

•   Doctrine         •   PHP Unit       •   SwiftMailer

•   EZ Components    •   Phing          •   Symfony

•   HtmlPurifier      •   Phly           •   WACT

•   Horde            •   Prado          •   Zend Framework

                                 23
Project Evolution Tracks
  class-       One-Off      include-
 oriented       Heap        oriented

              Standalone
                 App

  Library         ?
                           Modular App
 Collection

 Framework                    CMS

                  24
The One Lesson;
       or,
  “Step 2: ... ?”




        25
Organize your project
            as if
it is a library collection.
Elements of
        The One Lesson

• Stop using globals
• Namespace everything
• Class-to-file naming

                    27
1. Stop Using Globals

• Stop using
  register_globals

• Stop using $GLOBALS
• Stop using global

                        28
2. Namespace Everything

•   Automatic deconfliction of identifiers

    •   Classes (“vendor”)

    •   Functions, variables, constants

    •   Use with $_SESSION,
        $_COOKIE, etc. keys




                                    29
Choosing a Namespace

•   Project, client, brand, channel

•   A short word or acronym,
    not a letter (“Z”)

•   A unique name, not a generic
    name related to a task
    (Date, HTML, RSS, Table, User)




                                      30
PHP 5.2 “Namespaces”
// class User {}
class Vendor_User {}
$user = new Vendor_User();

// function get_info() {}
function vendor_get_info()

// $_SESSION["user_prefs"]
$_SESSION["Vendor_User"]["prefs"];
                31
PHP 5.3 Namespaces
namespace vendor;
class User {}

// relative namespace
namespace vendor;
$user = new User();

// absolute namespace
namespace other;
$user = new vendorUser();
                    32
3. Class-To-File Naming

• Class name maps directly to file name
 • Vendor_User    => Vendor/User.php

• Horde, PEAR, Solar, Zend, others
• Highly predictable file locations
• Lends itself to autoloading
                     33
Class-to-File Naming
 (PHP 5.2, Horde/PEAR)

// studly-caps needs preg_replace(), but:
VendorAuthOpenId => ...
    Vendor/Auth/Open/Id.php?
    Vendor/Auth/OpenId.php?

// underscores just need str_replace()
Vendor_Auth_OpenId => Vendor/Auth/OpenId.php




                      34
Class-to-File
          (PHP 5.3, PSR-0)

foo_barpkgMain     => /foo_bar/pkg/Main.php
foo_barpkgMain_Sub => /foo_bar/pkg/Main/Sub.php




      •   PEAR, Solar, Zend, Doctrine,
          Lithium, Symfony 2
                        35
The One Lesson In Practice;
           or,
     “Step 3: Profit!”




             36
Extended Effects of
             The One Lesson
•   Can be used anywhere
    (app, module, lib, CMS, framework)

•   Structure for refactoring and additions

•   Testing, profiling, and public files can
    parallel the same structure

•   Intuitive for new developers

•   No more include-path woes

                                      37
Mambo CMS
administrator/
components/
editor/
files/
help/
images/
includes/
    Vendor/
index.php
installation/
language/
mainbody.php
mambots/
media/
modules/
templates/
            38
Zend Framework
 project/
     application/
          bootstrap.php
          configs/
          controllers/
          models/
          views/
              helpers/
              scripts/
     library/
          Zend/
          Vendor/
     public
          index.php

              39
Lithium
app/
    config/
    controllers/
    extensions/
    index.php
    libraries/
    models/
    resources/
    tests/
    views/
    webroot/
libraries/
    lithium/
    vendor/

            40
Symfony 2
hello/
     config/
     console/
     HelloKernel.php
src/
     Application/
         HelloBundle/
              Bundle.php
              Controller/
              Resources/
     autoload.php
     vendor/
         symfony/
         zend/
         vendor/
web/
             41
Solar
system/
    config/
    config.php
    docroot/
         index.php
         public/
    include/
         Solar.php
         Solar/
         Vendor/
    script/
    source/
    sqlite/
    tmp/

             42
Solar Apps Are Libraries Too
          include/
            Solar/
            Vendor/
              App/
                Page.php
                Page/
                   Layout/
                   Locale/
                   Public/
                   View/
              Model/
                Gir.php
                Gir/
              Zim.php
              Zim/
                 43
Refactoring
• Move from existing include-based architecture
  to class-based architecture ...
  • ... by functionality
  • ... by script
• Then build scripts out of classes, not includes
• Then build apps out of classes, not scripts
• Leads to MVC / MVP / PAC architecture
                           44
Summary
The One Lesson

• Organize your project as if it will be part of
  a library collection
  • Avoid globals
  • Use namespaces for deconfliction
  • Use class-to-file naming convention

                         46
Goals for Organizing
•   Security

•   Integration and extension

•   Adaptable to change

•   Predictable and maintainable

•   Teamwork consistency

•   Re-use rules on multiple projects


                                   47
• Questions?
• Comments?
• Criticism?


               48
Thanks!

• <http://paul-m-jones.com>
• <http://solarphp.com>
• Solar Framework talk on Thursday
• <http://joind.in/1289>

                    49
Organizing Your PHP Projects (2010 ConFoo)

Organizing Your PHP Projects (2010 ConFoo)

  • 1.
    Organizing Your PHPProjects Paul M. Jones ConFoo, Montréal 10 Mar 2010 http://joind.in/1289
  • 2.
    Read These • “MythicalMan-Month”, Brooks • “Art of Project Management”, Berkun • “Peopleware”, DeMarco and Lister 2
  • 3.
    Project Planning in One Lesson • Examine real-world projects • The One Lesson for organizing your project • Elements of The One Lesson • The One Lesson in practice 3
  • 4.
    About Me • Web Architect • PHP since 1999 (PHP 3) • Solar Framework (lead) • Savant Template System (lead) • Zend Framework (found. contrib.) • PEAR Group (2007-2008) • Web framework benchmarks 4
  • 5.
    About You • Project lead/manager? • Improve team consistency? • Want to share your code with others? • Want to use code from others? • Want to reduce recurring integration issues? 5
  • 6.
    Goals for Organizing • Security • Integration and extension • Adaptable to change • Predictable and maintainable • Teamwork consistency • Re-use rules on multiple projects 6
  • 7.
    Project Research; or, “Step 1: Study Underpinnings” 7
  • 8.
    Project Evolution Tracks One-Off Heap Standalone App Library ? Modular App Collection Framework CMS 8
  • 9.
    One-Off Heap • No discernible architecture • Browse directly to the scripts • Add to it piece by piece • Little to no separation of concerns • All variables are global • Unmanageable, difficult to extend 9
  • 10.
    Standalone Application • One-off heap ++ • Series of separate page scripts and common includes • Installed in web root • Each responsible for global execution environment • Script variables still global 10
  • 11.
    Standalone Application: Typical Main Script // Setup or bootstrapping define('INCLUDE_PATH', dirname(__FILE__) . '/'); include_once INCLUDE_PATH . "inc/prepend.inc.php" include_once INCLUDE_PATH . "lib/foo.class.php"; include_once INCLUDE_PATH . "lib/View.class.php"; // Actions (if we're lucky) $foo = new Foo(); $data = $foo->getData(); // Display (if we're lucky) $view = new View(INCLUDE_PATH . 'tpl/'); $view->assign($data); echo $view->fetch('template.tpl'); // Teardown include_once INCLUDE_PATH . "inc/append.inc.php"; 11
  • 12.
    Standalone Application: Typical Include File // expects certain globals if (! defined('APP_CONSTANT')) {     die("Direct access not allowed."); } 12
  • 13.
    Standalone Application: TypicalFile Structure index.php # main pages page1.php # page2.php # page3.php # sub/ # sub-section index.php # zim.php # gir.php # inc/ # includes config.inc.php # prepend.inc.php # lib/ # libraries foo.class.php # Bundle1/ # Bundle2/ # 13
  • 14.
    Standalone Application: Support Structure bin/ # command-line tools cache/ # cache files css/ # stylesheets docs/ # documentation img/ # images install/ # installation scripts js/ # javascript log/ # log files sql/ # schema migrations theme/ # themes or skins tpl/ # templates -- no standard naming or structure -- index.html file in each directory 14
  • 15.
    Project Evolution Tracks One-Off Heap Standalone App Library ? Modular App Collection Framework CMS 15
  • 16.
    Modular Application • Standalone application ++ • Same file structure and script style • One additional directory: “modules”, “plugins”, etc • Hooks in the “main” scripts for additional behaviors • Use global variables to coordinate between modules 16
  • 17.
    CMS • Modular application ++ • General-purpose application broker • All "main" scripts become sub-applications • Still in the web root, still using globals to coordinate 17
  • 18.
    Application/CMS Projects • Achievo • Eventum • PhpMyAdmin • Code Igniter* • Gallery • Seagull* • Coppermine • Joomla/ • SugarCRM Mambo • DokuWiki • Vanilla • MediaWiki • Drupal • WordPress 18
  • 19.
    Project Evolution Tracks One-Off Heap Standalone App Library ? Modular App Collection Framework CMS 19
  • 20.
    Library Collection • Specific, limited logic extracted from an app • Re-used directly in unrelated applications and other libraries • No global variables • Class-oriented • Can exist anywhere in the file system 20
  • 21.
    Library Project: Typical File Structure Foo.php # Foo Foo/ # Component.php # Foo_Component Component/ # Element1.php # Foo_Component_Element1 Element2.php # Foo_Component_Element2 Bar.php # Bar Bar/ # Task.php # Bar_Task Part/ # Part1.php # Bar_Task_Part1 Part2.php # Bar_Task_Part2 21
  • 22.
    Framework • Codebase • Library collection • Apps extend from it • Support structure • Bootstrap file • Public assets • Protected assets 22
  • 23.
    Library/Framework Projects • AdoDB • Lithium • Savant • Cake • Mojavi/Agavi • Seagull * • CgiApp • PAT • Smarty • Code Igniter * • PEAR • Solar • Doctrine • PHP Unit • SwiftMailer • EZ Components • Phing • Symfony • HtmlPurifier • Phly • WACT • Horde • Prado • Zend Framework 23
  • 24.
    Project Evolution Tracks class- One-Off include- oriented Heap oriented Standalone App Library ? Modular App Collection Framework CMS 24
  • 25.
    The One Lesson; or, “Step 2: ... ?” 25
  • 26.
    Organize your project as if it is a library collection.
  • 27.
    Elements of The One Lesson • Stop using globals • Namespace everything • Class-to-file naming 27
  • 28.
    1. Stop UsingGlobals • Stop using register_globals • Stop using $GLOBALS • Stop using global 28
  • 29.
    2. Namespace Everything • Automatic deconfliction of identifiers • Classes (“vendor”) • Functions, variables, constants • Use with $_SESSION, $_COOKIE, etc. keys 29
  • 30.
    Choosing a Namespace • Project, client, brand, channel • A short word or acronym, not a letter (“Z”) • A unique name, not a generic name related to a task (Date, HTML, RSS, Table, User) 30
  • 31.
  • 32.
    PHP 5.3 Namespaces namespace vendor; class User {} // relativenamespace namespace vendor; $user = new User(); // absolute namespace namespace other; $user = new vendorUser(); 32
  • 33.
    3. Class-To-File Naming •Class name maps directly to file name • Vendor_User => Vendor/User.php • Horde, PEAR, Solar, Zend, others • Highly predictable file locations • Lends itself to autoloading 33
  • 34.
    Class-to-File Naming (PHP5.2, Horde/PEAR) // studly-caps needs preg_replace(), but: VendorAuthOpenId => ... Vendor/Auth/Open/Id.php? Vendor/Auth/OpenId.php? // underscores just need str_replace() Vendor_Auth_OpenId => Vendor/Auth/OpenId.php 34
  • 35.
    Class-to-File (PHP 5.3, PSR-0) foo_barpkgMain => /foo_bar/pkg/Main.php foo_barpkgMain_Sub => /foo_bar/pkg/Main/Sub.php • PEAR, Solar, Zend, Doctrine, Lithium, Symfony 2 35
  • 36.
    The One LessonIn Practice; or, “Step 3: Profit!” 36
  • 37.
    Extended Effects of The One Lesson • Can be used anywhere (app, module, lib, CMS, framework) • Structure for refactoring and additions • Testing, profiling, and public files can parallel the same structure • Intuitive for new developers • No more include-path woes 37
  • 38.
    Mambo CMS administrator/ components/ editor/ files/ help/ images/ includes/ Vendor/ index.php installation/ language/ mainbody.php mambots/ media/ modules/ templates/ 38
  • 39.
    Zend Framework project/ application/ bootstrap.php configs/ controllers/ models/ views/ helpers/ scripts/ library/ Zend/ Vendor/ public index.php 39
  • 40.
    Lithium app/ config/ controllers/ extensions/ index.php libraries/ models/ resources/ tests/ views/ webroot/ libraries/ lithium/ vendor/ 40
  • 41.
    Symfony 2 hello/ config/ console/ HelloKernel.php src/ Application/ HelloBundle/ Bundle.php Controller/ Resources/ autoload.php vendor/ symfony/ zend/ vendor/ web/ 41
  • 42.
    Solar system/ config/ config.php docroot/ index.php public/ include/ Solar.php Solar/ Vendor/ script/ source/ sqlite/ tmp/ 42
  • 43.
    Solar Apps AreLibraries Too include/ Solar/ Vendor/ App/ Page.php Page/ Layout/ Locale/ Public/ View/ Model/ Gir.php Gir/ Zim.php Zim/ 43
  • 44.
    Refactoring • Move fromexisting include-based architecture to class-based architecture ... • ... by functionality • ... by script • Then build scripts out of classes, not includes • Then build apps out of classes, not scripts • Leads to MVC / MVP / PAC architecture 44
  • 45.
  • 46.
    The One Lesson •Organize your project as if it will be part of a library collection • Avoid globals • Use namespaces for deconfliction • Use class-to-file naming convention 46
  • 47.
    Goals for Organizing • Security • Integration and extension • Adaptable to change • Predictable and maintainable • Teamwork consistency • Re-use rules on multiple projects 47
  • 48.
  • 49.
    Thanks! • <http://paul-m-jones.com> • <http://solarphp.com> •Solar Framework talk on Thursday • <http://joind.in/1289> 49