You are previewing Real-World Solutions for Developing High-Quality PHP Frameworks and Applications.
O'Reilly logo
Real-World Solutions for Developing High-Quality PHP Frameworks and Applications

Book Description

Learn to develop high-quality applications and frameworks in PHP

Packed with in-depth information and step-by-step guidance, this book escorts you through the process of creating, maintaining and extending sustainable software of high quality with PHP. World-renowned PHP experts present real-world case studies for developing high-quality applications and frameworks in PHP that can easily be adapted to changing business requirements. . They offer different approaches to solving typical development and quality assurance problems that every developer needs to know and master.

  • Details the process for creating high-quality PHP frameworks and applications that can easily be adapted to changing business requirements

  • Covers the planning, execution, and automation of tests for the different layers and tiers of a Web application

  • Demonstrates how to establish a successful development process

  • Shares real-world case studies from well-known companies and their PHP experts

With this book, you'll learn to develop high-quality PHP frameworks and applications that can easily be maintained with reasonable cost and effort.

Table of Contents

  1. Copyright
  2. ABOUT THE AUTHORS
  3. CREDITS
  4. FOREWORD
  5. INTRODUCTION
    1. ABOUT THIS BOOK
      1. Is This a PHP Book?
      2. Structure of the Book
    2. ABOUT THE CASE STUDY AUTHORS
      1. Robert Lemke, TYPO3 Association, and Karsten Dambekalns, TYPO3 Association
      2. Benjamin Eberlei, direkt:effekt GmbH
      3. Matthew Weier O'Phinney, Zend Technologies Ltd.
      4. Tobias Schlitt
      5. Fabien Potencier, Sensio Labs
      6. Kore Nordmann
      7. Michael Lively Jr., Selling Source LLC
      8. Christiane Philipps, Rebate Networks GmbH, and Max Horváth, Vodafone GmbH
      9. Manuel Pichler, OnVista Media GmbH, and Sebastian Nohn, Ligatus GmbH
      10. Lars Jankowfsky, swoodoo AG
      11. Jens Grochtdreis
      12. Brian Shire
      13. Arne Blankerts, thePHP.cc
    3. ERRATA
    4. P2P.WROX.COM
  6. I. Foundations
    1. 1. Software Quality
      1. 1.1. EXTERNAL QUALITY
      2. 1.2. INTERNAL QUALITY
      3. 1.3. TECHNICAL DEBT
      4. 1.4. CONSTRUCTIVE QUALITY ASSURANCE
      5. 1.5. CLEAN CODE
        1. 1.5.1. Explicit and Minimal Dependencies
        2. 1.5.2. Clear Responsibilities
        3. 1.5.3. No Duplication
        4. 1.5.4. Short Methods with Few Execution Branches
      6. 1.6. SOFTWARE METRICS
        1. 1.6.1. Cyclomatic Complexity and npath Complexity
        2. 1.6.2. Change Risk Anti-Patterns (CRAP) Index
        3. 1.6.3. Non-Mockable Total Recursive Cyclomatic Complexity
        4. 1.6.4. Global Mutable State
        5. 1.6.5. Cohesion and Coupling
      7. 1.7. TOOLS
        1. 1.7.1. PHPUnit
        2. 1.7.2. phploc
        3. 1.7.3. PHP Copy-Paste-Detector (phpcpd)
        4. 1.7.4. PHP Dead Code Detector (phpdcd)
        5. 1.7.5. PHP_Depend (pdepend)
        6. 1.7.6. PHP Mess Detector (phpmd)
        7. 1.7.7. PHP_CodeSniffer (phpcs)
        8. 1.7.8. bytekit-cli
        9. 1.7.9. PHP_CodeBrowser (phpcb)
        10. 1.7.10. CruiseControl and phpUnderControl
        11. 1.7.11. Hudson
        12. 1.7.12. Arbit
      8. 1.8. CONCLUSION
    2. 2. Software Testing
      1. 2.1. BLACK BOX AND WHITE BOX TESTS
      2. 2.2. HOW MANY TESTS ARE NEEDED?
      3. 2.3. SYSTEM TESTS
        1. 2.3.1. Browser Testing
        2. 2.3.2. Automated Tests
        3. 2.3.3. Test Isolation
        4. 2.3.4. Acceptance Tests
        5. 2.3.5. Limits of System Tests
      4. 2.4. UNIT TESTS
        1. 2.4.1. Return Values
        2. 2.4.2. Dependencies
        3. 2.4.3. Side Effects
      5. 2.5. REAL-LIFE EXAMPLE
        1. 2.5.1. Analyzing the Code to Test
        2. 2.5.2. Setting Up a Test Environment
        3. 2.5.3. Avoid Global Dependencies
        4. 2.5.4. Test Independently from Data Sources
        5. 2.5.5. Testing Asynchronous Events
        6. 2.5.6. Storing Changes in the Database
        7. 2.5.7. Unpredictable Results
        8. 2.5.8. Encapsulating Input Data
        9. 2.5.9. Further Reflections
      6. 2.6. CONCLUSION
  7. II. Best Practices
    1. 3. TYPO3: The Agile Future of a Ponderous Project
      1. 3.1. INTRODUCTION
        1. 3.1.1. The History of TYPO3: Thirteen Years in Thirteen Paragraphs
        2. 3.1.2. Daring to Start Over!
        3. 3.1.3. Our Experience with Testing
      2. 3.2. POLICIES AND TECHNIQUES
        1. 3.2.1. Bittersweet Elephant Pieces
        2. 3.2.2. Test-Driven Development
        3. 3.2.3. Tests as Documentation
        4. 3.2.4. Continuous Integration
        5. 3.2.5. Clean Code
        6. 3.2.6. Refactoring
        7. 3.2.7. Programming Guidelines
        8. 3.2.8. Domain-Driven Design
      3. 3.3. COURSE OF ACTION IN DEVELOPMENT
        1. 3.3.1. Developing New Code
        2. 3.3.2. Extending and Modifying Code
        3. 3.3.3. Optimizing Code
          1. 3.3.3.1. Speed
          2. 3.3.3.2. Readability
        4. 3.3.4. Finding and Fixing Bugs
        5. 3.3.5. Disposing of Old Code
      4. 3.4. TEST RECIPES
        1. 3.4.1. Inadvertently Functional Unit Test
        2. 3.4.2. Access to the File System
        3. 3.4.3. Constructors in Interfaces
        4. 3.4.4. Testing Abstract Classes
        5. 3.4.5. Testing Protected Methods
        6. 3.4.6. Use of Callbacks
      5. 3.5. INTO THE FUTURE
    2. 4. Unit Testing Bad Practices
      1. 4.1. WHY TEST QUALITY MATTERS
      2. 4.2. BAD PRACTICES AND TEST SMELLS
        1. 4.2.1. Duplication in Test Code
        2. 4.2.2. Assertion Roulette and Eager Test
        3. 4.2.3. Fragile Test
        4. 4.2.4. Obscure Test
          1. 4.2.4.1. Problems with Global State
          2. 4.2.4.2. Indirect Testing
          3. 4.2.4.3. Obscure Test Names
        5. 4.2.5. Lying Test
        6. 4.2.6. Slow Test
        7. 4.2.7. Conditional Logic in Tests
        8. 4.2.8. Self-validating Tests
        9. 4.2.9. Web-surfing Tests
        10. 4.2.10. Mock Overkill
        11. 4.2.11. Skip Epidemic
      3. 4.3. CONCLUSION
    3. 5. Quality Assurance at Digg Inc.
      1. 5.1. PROBLEMS WE ARE FACING
        1. 5.1.1. Legacy Code Base
        2. 5.1.2. How Do We Solve These Problems?
          1. 5.1.2.1. Size Does Matter
          2. 5.1.2.2. Team Size
          3. 5.1.2.3. Project Size
          4. 5.1.2.4. Code Size
          5. 5.1.2.5. Unit Testing and You
        3. 5.1.3. Choosing a Testing Framework
        4. 5.1.4. Working with an Expert
          1. 5.1.4.1. One Week in a Room
      2. 5.2. TRAINING OUR TEAM
      3. 5.3. WRITING TESTABLE CODE
        1. 5.3.1. Avoid Static Methods
        2. 5.3.2. Dependency Injection
      4. 5.4. MOCK OBJECTS
        1. 5.4.1. Overview
        2. 5.4.2. Database
        3. 5.4.3. Loosely Coupled Dependencies
        4. 5.4.4. Subject/Observer for Testing Class Internals
        5. 5.4.5. Memcached
        6. 5.4.6. Mocking a Service-Oriented Architecture
          1. 5.4.6.1. Model
          2. 5.4.6.2. Service Query
          3. 5.4.6.3. Service Endpoint
          4. 5.4.6.4. The Base Classes
      5. 5.5. DIGG'S QUALITY ASSURANCE PROCESS
        1. 5.5.1. Testing
          1. 5.5.1.1. Planning the Testing Effort
          2. 5.5.1.2. Tasks
          3. 5.5.1.3. Automation
        2. 5.5.2. Benefits
          1. 5.5.2.1. Testing Early
          2. 5.5.2.2. Testing Often
          3. 5.5.2.3. Challenges
      6. 5.6. CONCLUSION
  8. III. Servers and Services
    1. 6. Testing Service-Oriented APIs
      1. 6.1. THE PROBLEMS
      2. 6.2. SOLUTIONS
        1. 6.2.1. API Credentials
        2. 6.2.2. API Limits
        3. 6.2.3. Offline Testing of Service Protocols
        4. 6.2.4. Offline Testing of Concrete Services
      3. 6.3. CONCLUSION
    2. 7. Testing a WebDAV Server
      1. 7.1. ABOUT THE eZ WEBDAV COMPONENT
        1. 7.1.1. WebDAV
        2. 7.1.2. Architecture
      2. 7.2. DEVELOPMENT CHALLENGES
        1. 7.2.1. Requirements Analysis
        2. 7.2.2. TDD after RFC
        3. 7.2.3. Testing a Server
      3. 7.3. AUTOMATED ACCEPTANCE TESTS WITH PHPUNIT
        1. 7.3.1. Capturing Test Trails
        2. 7.3.2. Test Recipe
        3. 7.3.3. Integration into PHPUnit
          1. 7.3.3.1. A Custom Test Case
          2. 7.3.3.2. The Acceptance Test Suite
          3. 7.3.3.3. Acceptance Tests by Example
      4. 7.4. CONCLUSION
  9. IV. Architecture
    1. 8. Testing symfony and symfony Projects
      1. 8.1. TESTING A FRAMEWORK
        1. 8.1.1. The symfony Release Management Process
          1. 8.1.1.1. Long-term Support
          2. 8.1.1.2. Code Coverage
        2. 8.1.2. Tests versus Real Code
        3. 8.1.3. Running the Test Suite
        4. 8.1.4. Main Lessons Learned
          1. 8.1.4.1. Never Use the Singleton Design Pattern in PHP
          2. 8.1.4.2. Decouple Your Code with Dependency Injection
          3. 8.1.4.3. Lower the Number of Dependencies between Objects with an Event Dispatcher
      2. 8.2. TESTING WEB APPLICATIONS
        1. 8.2.1. Lowering the Barrier of Entry of Testing
        2. 8.2.2. Unit Tests
          1. 8.2.2.1. Easy to Install
          2. 8.2.2.2. Easy to Learn
          3. 8.2.2.3. Fun to Use
        3. 8.2.3. Functional Tests
          1. 8.2.3.1. The Browser Simulator
          2. 8.2.3.2. The Fixtures
          3. 8.2.3.3. The CSS3 Selectors
          4. 8.2.3.4. Testing Forms
          5. 8.2.3.5. Debugging
      3. 8.3. CONCLUSION
    2. 9. Testing the ezcGraph Component
      1. 9.1. DEVELOPMENT PHILOSOPHY
      2. 9.2. GRAPH COMPONENT
        1. 9.2.1. Architecture
        2. 9.2.2. Test Requirements
      3. 9.3. DRIVER MOCKING
        1. 9.3.1. Mock the Driver
        2. 9.3.2. Multiple Assertions
        3. 9.3.3. Structs
        4. 9.3.4. Expectation Generation
        5. 9.3.5. Conclusion
      4. 9.4. TESTING BINARY DATA
        1. 9.4.1. The Drivers
        2. 9.4.2. Expectation Generation
        3. 9.4.3. SVG
          1. 9.4.3.1. XML Comparison
          2. 9.4.3.2. Floating-point Problems
        4. 9.4.4. Bitmap Creation
          1. 9.4.4.1. Bitmap Comparison
          2. 9.4.4.2. GD Version Differences
        5. 9.4.5. Flash
          1. 9.4.5.1. The Assertion
      5. 9.5. CONCLUSION
    3. 10. Testing Database Interaction
      1. 10.1. INTRODUCTION
      2. 10.2. REASONS NOT TO WRITE DATABASE TESTS
      3. 10.3. WHY WE SHOULD WRITE DATABASE TESTS
      4. 10.4. WHAT WE SHOULD TEST
      5. 10.5. WRITING TESTS: MOCKING DATABASE CONNECTIONS
      6. 10.6. WRITING TESTS: PHPUNIT DATABASE EXTENSION
        1. 10.6.1. The Database Test Case Class
        2. 10.6.2. Establishing the Test Database Connection
        3. 10.6.3. Creating Data Sets
          1. 10.6.3.1. XML Data Sets
          2. 10.6.3.2. Flat XML Data Sets
          3. 10.6.3.3. CSV Data Sets
          4. 10.6.3.4. YAML Data Sets
          5. 10.6.3.5. Database Data Sets
          6. 10.6.3.6. Data Set Decorators
            1. 10.6.3.6.1. Filter Decorator
            2. 10.6.3.6.2. Composite Decorator
            3. 10.6.3.6.3. Replacement Decorator
          7. 10.6.3.7. Generating Data Sets
        4. 10.6.4. Data Operations
        5. 10.6.5. Creating Tests
          1. 10.6.5.1. Testing the Loading of Data
          2. 10.6.5.2. Testing the Modification of Data
        6. 10.6.6. Using the Database Tester
      7. 10.7. APPLYING TEST-DRIVEN DESIGN TO DATABASE TESTING
      8. 10.8. USING DATABASE TESTS FOR REGRESSION TESTING
        1. 10.8.1. Testing Problems with Data
        2. 10.8.2. Testing Problems Revealed by Data
      9. 10.9. CONCLUSION
  10. V. Q&A in the Large
    1. 11. Quality Assurance at studiVZ
      1. 11.1. INTRODUCTION
        1. 11.1.1. About studiVZ
      2. 11.2. ACCEPTANCE TESTS
        1. 11.2.1. Acceptance Tests in Agile Environments
      3. 11.3. SELENIUM
        1. 11.3.1. The Selenium Extension of PHPUnit
      4. 11.4. THE TECHNICAL SETUP OF STUDIVZ
        1. 11.4.1. Development Environment
        2. 11.4.2. Test Environment
      5. 11.5. BEST PRACTICES
        1. 11.5.1. Sins of Our Youth
          1. 11.5.1.1. Monolithic Tests
          2. 11.5.1.2. Static Users
        2. 11.5.2. Strategy Change
          1. 11.5.2.1. Atomic Tests with Dynamic Test Data
          2. 11.5.2.2. Robust Selenium Tests
          3. 11.5.2.3. Test Scope Must Be Clear
          4. 11.5.2.4. Common Functionality or Browser Compatibility as Well?
          5. 11.5.2.5. Fix Tests Right Away!
          6. 11.5.2.6. Stabilize Locators, and Use IDs
          7. 11.5.2.7. Speed, the Sore Subject
          8. 11.5.2.8. Recipes for Last-Minute Features
          9. 11.5.2.9. Tests Are Software Too
          10. 11.5.2.10. Capture and Replay versus Programming Tests
          11. 11.5.2.11. The Team: a Good Mix
      6. 11.6. WE NEED A DSL
        1. 11.6.1. Internal DSL
        2. 11.6.2. Testing_SeleniumDSL 1.0
          1. 11.6.2.1. Problem: Context Sensitivity
        3. 11.6.3. Testing_SeleniumDSL 2.0—a Draft
        4. 11.6.4. State and Outlook on Version 2.0
      7. 11.7. CONCLUSION
    2. 12. Continuous Integration
      1. 12.1. INTRODUCTION
        1. 12.1.1. Continuous Integration
          1. 12.1.1.1. Configuration
          2. 12.1.1.2. Build Management and Automated Tests
          3. 12.1.1.3. Version Management
          4. 12.1.1.4. Continuous Integration
        2. 12.1.2. Static Analysis
          1. 12.1.2.1. Code Clones
          2. 12.1.2.2. Refactoring
          3. 12.1.2.3. Software Metrics
          4. 12.1.2.4. Classic Metrics
            1. 12.1.2.4.1. Lines of Code
            2. 12.1.2.4.2. Number of Classes, Methods, and Functions in a System
            3. 12.1.2.4.3. Cyclomatic Complexity
          5. 12.1.2.5. Object-Oriented Metrics
            1. 12.1.2.5.1. Instability, Abstraction, and Distance
            2. 12.1.2.5.2. Code Rank
            3. 12.1.2.5.3. Getting a Quick Overview
          6. 12.1.2.6. RATS
      2. 12.2. INSTALLATION
      3. 12.3. CONFIGURATION
        1. 12.3.1. Static Tests
          1. 12.3.1.1. Programming Conventions
          2. 12.3.1.2. Coding Guidelines
          3. 12.3.1.3. Gradual Introduction into Legacy Projects
          4. 12.3.1.4. Coding Standards in the Daily Work
          5. 12.3.1.5. Syntax Analysis
        2. 12.3.2. Dynamic Tests
        3. 12.3.3. Reporting
          1. 12.3.3.1. Notification in the Case of Errors
          2. 12.3.3.2. Statistics
          3. 12.3.3.3. PHP_CodeBrowser
        4. 12.3.4. Deliverables
      4. 12.4. OPERATIONS
      5. 12.5. ADVANCED TOPICS
        1. 12.5.1. Continuous Deployment
        2. 12.5.2. Using a Reverse Proxy
        3. 12.5.3. Continuous Integration and Agile Paradigms
      6. 12.6. CONCLUSION
    3. 13. swoodoo: A True Agile Story
      1. 13.1. INTRODUCTION
      2. 13.2. EVOLUTION: ONLY THE STRONG SURVIVE
        1. 13.2.1. How We Reached the eXtreme Side
      3. 13.3. AND WHILE WE ARE WORKING...
      4. 13.4. THE ART OF EVOLUTION
        1. 13.4.1. Lack of Experience
        2. 13.4.2. The Java-developer-coding-in-PHP Phenomenon
        3. 13.4.3. The Nobody-but-me-understands-my-code Developer
      5. 13.5. CONCLUSION
  11. VI. Non-Functional Aspects
    1. 14. Usability
      1. 14.1. ANYTHING GOES, BUT WHAT IS THE PRICE?
      2. 14.2. DESIGN ASPECTS
        1. 14.2.1. Accessibility
        2. 14.2.2. Readability
        3. 14.2.3. Labels for Form Elements
        4. 14.2.4. Navigating by Keyboard
        5. 14.2.5. Effective Contrast
        6. 14.2.6. Logo Links to Home Page
        7. 14.2.7. Alternative Texts for Images
        8. 14.2.8. Background Image in Background Color
        9. 14.2.9. Usable Print Version
        10. 14.2.10. Visible Links
        11. 14.2.11. Good Bookmarks
        12. 14.2.12. No Frames
        13. 14.2.13. Scalable Fonts
      3. 14.3. TECHNICAL ASPECTS
        1. 14.3.1. Performance
          1. 14.3.1.1. Semantic Code
          2. 14.3.1.2. Fewer Requests
          3. 14.3.1.3. CSS Sprites
          4. 14.3.1.4. JavaScript on Bottom, CSS on Top
          5. 14.3.1.5. Link CSS Instead of Importing
        2. 14.3.2. JavaScript
      4. 14.4. USER GUIDANCE
        1. 14.4.1. The "Fold" Myth
        2. 14.4.2. Feedback on Interaction
        3. 14.4.3. Navigation
        4. 14.4.4. Pop-ups and Other Annoyances
        5. 14.4.5. Habits and Expectations
        6. 14.4.6. Fault Tolerance and Feedback
      5. 14.5. TESTING USABILITY
      6. 14.6. CONCLUSION
    2. 15. Performance Testing
      1. 15.1. INTRODUCTION
        1. 15.1.1. Tools
        2. 15.1.2. Environmental Considerations
      2. 15.2. LOAD TESTING
        1. 15.2.1. Apache Bench
        2. 15.2.2. Pylot
        3. 15.2.3. Other Load Testing Tools
      3. 15.3. PROFILING
        1. 15.3.1. Callgrind
        2. 15.3.2. KCachegrind
        3. 15.3.3. APD
        4. 15.3.4. Xdebug
        5. 15.3.5. XHProf
        6. 15.3.6. OProfile
      4. 15.4. SYSTEM METRICS
        1. 15.4.1. strace
        2. 15.4.2. Sysstat
        3. 15.4.3. Custom Instrumentation
      5. 15.5. COMMON PITFALLS
        1. 15.5.1. Development versus Production Environments
        2. 15.5.2. CPU Time
        3. 15.5.3. Micro-Optimizations
        4. 15.5.4. PHP as the Glue
        5. 15.5.5. Priority of Optimization
      6. 15.6. CONCLUSION
    3. 16. Security
      1. 16.1. WHAT IS SECURITY?
      2. 16.2. SECURE BY DESIGN
        1. 16.2.1. Operations
        2. 16.2.2. Physical Access
        3. 16.2.3. Software Development
          1. 16.2.3.1. No Security by Obscurity
          2. 16.2.3.2. Separation of Concerns
          3. 16.2.3.3. A Matter of Rights
          4. 16.2.3.4. Error Handling
          5. 16.2.3.5. Basic Settings
      3. 16.3. WHAT DOES SECURITY COST?
      4. 16.4. THE MOST COMMON PROBLEMS
        1. 16.4.1. A10: Unvalidated Redirects and Forwards
        2. 16.4.2. A9: Insufficient Transport Layer Protection
        3. 16.4.3. A8: Failure to Restrict URL Access
        4. 16.4.4. A7: Insecure Cryptographic Storage
        5. 16.4.5. A6: Security Misconfiguration
        6. 16.4.6. A5: Cross-Site Request Forgery (CSRF/XSRF)
        7. 16.4.7. A4: Insecure Direct Object References
        8. 16.4.8. A3: Broken Authentication and Session Management
        9. 16.4.9. A2: Cross-Site Scripting (XSS)
        10. 16.4.10. A1: Injection
      5. 16.5. CONCLUSION
    4. 17. Conclusion
    5. BIBLIOGRAPHY