PHP Best Practices and Coding Standards
phpcoding standardsbest practicessecurityperformance
Description
This rule provides guidelines for PHP coding best practices, covering code structure, security, performance, and testing to improve code quality and maintainability.
Globs
**/*.php
---
description: This rule provides guidelines for PHP coding best practices, covering code structure, security, performance, and testing to improve code quality and maintainability.
globs: **/*.php
---
# PHP Best Practices and Coding Standards
This document outlines best practices and coding standards for PHP development to ensure code quality, maintainability, security, and performance.
## 1. Code Organization and Structure
### 1.1. Directory Structure Best Practices
* **`src/`:** Contains the core source code of your application or library.
* **`public/`:** The document root of your application, containing publicly accessible files like `index.php`, CSS, JavaScript, and images. All requests should be routed through this directory.
* **`config/`:** Stores configuration files for different environments (development, testing, production).
* **`tests/`:** Contains unit, integration, and functional tests.
* **`vendor/`:** Managed by Composer, containing third-party libraries and dependencies. Do not modify contents manually.
* **`cache/`:** Directory used for caching data.
* **`logs/`:** Directory for storing application logs. Use descriptive names for log files.
* **`data/`:** Stores data files (e.g., SQLite databases).
* **`resources/`:** Contains view templates, language files, and other resources.
* **`migrations/`:** Database migration files for version control of your database schema.
project/
├── src/
│ ├── Controller/
│ │ └── UserController.php
│ ├── Model/
│ │ └── User.php
│ └── ...
├── public/
│ └── index.php
├── config/
│ └── config.php
├── tests/
│ ├── Unit/
│ │ └── UserTest.php
│ └── ...
├── vendor/
│ └── ...
├── cache/
│ └── ...
├── logs/
│ └── app.log
├── data/
│ └── database.sqlite
├── resources/
│ ├── views/
│ │ └── user.php
│ └── lang/
│ └── en.php
└── migrations/
└── 2024_01_01_create_users_table.php
### 1.2. File Naming Conventions
* **Classes:** Use PascalCase (e.g., `UserController.php`). The filename should match the class name.
* **Functions and methods:** Use camelCase (e.g., `getUserById()`).
* **Variables:** Use camelCase (e.g., `$userName`).
* **Constants:** Use UPPER_SNAKE_CASE (e.g., `MAX_USER_AGE`).
* **Configuration files:** Use lowercase with underscores (e.g., `database_config.php`).
* **View files:** Use lowercase with hyphens (e.g., `user-profile.php`).
### 1.3. Module Organization
* **Separate concerns:** Organize code into modules based on functionality (e.g., authentication, user management, payment processing).
* **Use namespaces:** Group related classes and interfaces within namespaces to avoid naming conflicts and improve code organization (e.g., `namespace App\Controllers;`). Follow PSR-4 autoloading standards.
* **Dependency Injection:** Use dependency injection to decouple modules and make them easier to test and maintain.
* **Interfaces and Abstract Classes:** Define interfaces for modules to ensure loose coupling and allow for different implementations.
### 1.4. Component Architecture
* **Components:** Independent, reusable pieces of functionality that can be composed to build larger applications.
* **Thin Controllers:** Keep controllers light, delegate business logic to service classes or model layer.
* **Repositories:** Abstract data access logic from the rest of the application. This allows you to easily switch between different data sources (e.g., databases, APIs) without modifying the core application code.
* **Services:** Encapsulate complex business logic.
### 1.5. Code Splitting
* **Lazy loading:** Load modules or components only when they are needed to improve initial load time.
* **Composer autoloading:** Composer efficiently handles autoloading of classes based on namespaces, splitting code into separate files.
## 2. Common Patterns and Anti-patterns
### 2.1. Design Patterns
* **Singleton:** Ensures that a class has only one instance and provides a global point of access to it. Use sparingly, as overuse can lead to tight coupling and make testing difficult.
* **Factory:** Creates objects without specifying the exact class to create. Useful for abstracting object creation.
* **Observer:** Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. Useful for event handling.
* **Strategy:** Defines a family of algorithms, encapsulates each one, and makes them interchangeable. Lets the algorithm vary independently from clients that use it.
* **Model-View-Controller (MVC):** Separates application logic (Model), user interface (View), and input handling (Controller). Most PHP frameworks are based on MVC.
* **Repository Pattern:** Abstract data access logic. Useful when you want to be able to easily switch data sources or when your data access logic is complex.
### 2.2. Recommended Approaches
* **Database interactions:** Use prepared statements with parameterized queries to prevent SQL injection.
* **Templating:** Use a templating engine like Twig or Blade to separate presentation logic from PHP code. Helps to maintain code clean and readable.
* **Routing:** Use a routing component to map URLs to controllers and actions. Simplifies URL handling.
* **Error handling:** Implement a consistent error handling strategy using exceptions and logging.
* **Dependency Injection:** Use a dependency injection container to manage dependencies and promote loose coupling. Frameworks often include DI containers.
### 2.3. Anti-patterns and Code Smells
* **Global state:** Avoid using global variables as they can lead to unpredictable behavior and make code difficult to test.
* **Tight coupling:** Minimize dependencies between classes and modules to improve reusability and maintainability.
* **Long methods/functions:** Break down large methods into smaller, more focused functions.
* **Copy-pasted code:** Extract common functionality into reusable functions or classes.
* **Ignoring errors:** Always handle exceptions and log errors appropriately.
* **Over-use of static methods:** Limit the use of static methods, which can make testing more difficult.
* **Code duplication:** Follow the DRY (Don't Repeat Yourself) principle.
### 2.4. State Management
* **Sessions:** Use PHP sessions for managing user authentication and temporary data. Configure session security settings (e.g., `session.cookie_httponly`, `session.cookie_secure`).
* **Cookies:** Use cookies for storing small amounts of data on the client-side. Be mindful of cookie size limits and security.
* **Caching:** Use caching mechanisms (e.g., Memcached, Redis, file-based caching) to improve performance by storing frequently accessed data.
* **Database:** Store persistent data in a database. Use appropriate data types and indexes for optimal performance.
* **Statelessness:** Design APIs to be stateless whenever possible to improve scalability.
### 2.5. Error Handling
* **Exceptions:** Use exceptions to handle errors and exceptional situations. Throw exceptions when something goes wrong.
* **Try-catch blocks:** Wrap code that might throw an exception in try-catch blocks to handle errors gracefully.
* **Custom exception classes:** Create custom exception classes to represent specific error conditions in your application.
* **Logging:** Log errors, warnings, and informational messages using a logging library (e.g., Monolog). Configure logging levels.
* **Error reporting:** Configure PHP error reporting settings (`error_reporting`, `display_errors`) appropriately for different environments. Disable displaying errors in production.
* **Global Exception Handler:** Set a global exception handler to catch uncaught exceptions and log them.
## 3. Performance Considerations
### 3.1. Optimization Techniques
* **Opcode caching:** Use an opcode cache like OPcache (built into PHP) to store compiled PHP code in memory, reducing the need to recompile code on each request.
* **Caching:** Implement caching strategies at different levels (e.g., database caching, object caching, page caching).
* **Database optimization:** Optimize database queries, use indexes, and avoid N+1 query problems.
* **Code profiling:** Use a profiler (e.g., Xdebug) to identify performance bottlenecks in your code.
* **Minimize file I/O:** Reduce the number of file read/write operations.
* **Use appropriate data structures:** Choose the right data structures for your needs (e.g., arrays, linked lists, hash tables).
* **Avoid resource-intensive operations:** Minimize the use of functions that consume a lot of resources (e.g., regular expressions).
* **Use PHP 7.x/8.x features:** Take advantage of performance improvements in newer versions of PHP.
### 3.2. Memory Management
* **Unset variables:** Unset variables that are no longer needed to free up memory.
* **Avoid large arrays:** Avoid storing large amounts of data in arrays. Use iterators or generators if possible.
* **Garbage collection:** PHP automatically manages memory using garbage collection. Ensure that your code doesn't create memory leaks (e.g., circular references).
* **Limit session size:** Be mindful of the amount of data stored in sessions, as large sessions can consume a lot of memory.
### 3.3. Rendering Optimization
* **Minimize HTTP requests:** Reduce the number of HTTP requests by combining CSS and JavaScript files, using CSS sprites, and inlining small images.
* **Optimize images:** Compress images and use appropriate image formats (e.g., JPEG, PNG, WebP).
* **Use browser caching:** Configure browser caching to store static assets (e.g., CSS, JavaScript, images) in the browser cache.
* **Content Delivery Network (CDN):** Use a CDN to serve static assets from geographically distributed servers.
* **Gzip compression:** Enable Gzip compression to reduce the size of HTTP responses.
* **Minify HTML, CSS, and JavaScript:** Remove unnecessary characters from HTML, CSS, and JavaScript files.
### 3.4. Bundle Size Optimization (Less relevant for traditional PHP, but important for frontend assets)
* **Code splitting:** Split frontend code into smaller chunks that can be loaded on demand. (Relevant if using a frontend framework like React, Vue, or Angular alongside PHP).
* **Tree shaking:** Remove unused code from your JavaScript bundles. (Relevant if using a frontend framework).
### 3.5. Lazy Loading
* **Lazy-load images:** Load images only when they are visible in the viewport.
* **Lazy-load modules:** Load modules or components only when they are needed.
## 4. Security Best Practices
### 4.1. Common Vulnerabilities
* **SQL injection:** Occurs when untrusted data is used to construct SQL queries. Prevent by using prepared statements with parameterized queries.
* **Cross-Site Scripting (XSS):** Occurs when malicious scripts are injected into a website. Prevent by sanitizing user input and escaping output.
* **Cross-Site Request Forgery (CSRF):** Occurs when a malicious website tricks a user into performing unwanted actions on another website. Prevent by using CSRF tokens.
* **Remote Code Execution (RCE):** Occurs when an attacker can execute arbitrary code on the server. Prevent by avoiding dangerous functions (e.g., `eval()`, `system()`) and carefully validating user input.
* **File Inclusion:** Occurs when an attacker can include arbitrary files on the server. Prevent by carefully validating user input and restricting file access.
* **Session Hijacking:** Occurs when an attacker steals a user's session ID. Prevent by using secure session management practices.
* **Denial of Service (DoS):** Occurs when an attacker overwhelms a server with requests, making it unavailable to legitimate users. Prevent by implementing rate limiting and other security measures.
### 4.2. Input Validation
* **Sanitize user input:** Remove or encode potentially dangerous characters from user input.
* **Validate user input:** Verify that user input conforms to expected formats and values.
* **Use whitelisting:** Allow only known good values for user input. Avoid blacklisting, which can be easily bypassed.
* **Escape output:** Escape output to prevent XSS attacks.
### 4.3. Authentication and Authorization
* **Use strong passwords:** Enforce strong password policies and use a secure password hashing algorithm (e.g., bcrypt, Argon2).
* **Salt passwords:** Add a unique salt to each password before hashing it.
* **Store passwords securely:** Store password hashes in a secure database.
* **Implement access control:** Restrict access to resources based on user roles and permissions.
* **Use multi-factor authentication (MFA):** Add an extra layer of security by requiring users to provide multiple forms of authentication.
* **Secure cookies:** Set the `HttpOnly` and `Secure` flags on cookies to prevent XSS and man-in-the-middle attacks.
* **Use HTTPS:** Encrypt all communication between the client and server using HTTPS.
### 4.4. Data Protection
* **Encrypt sensitive data:** Encrypt sensitive data at rest and in transit.
* **Use encryption keys securely:** Store encryption keys in a secure location and rotate them regularly.
* **Comply with data privacy regulations:** Comply with data privacy regulations like GDPR and CCPA.
* **Implement data masking:** Mask sensitive data when it is not needed for processing.
* **Regularly back up data:** Regularly back up data to protect against data loss.
### 4.5. Secure API Communication
* **Use HTTPS:** Enforce HTTPS for all API endpoints.
* **Authenticate API requests:** Use API keys, OAuth 2.0, or other authentication mechanisms to verify the identity of API clients.
* **Authorize API requests:** Restrict access to API endpoints based on user roles and permissions.
* **Rate limit API requests:** Implement rate limiting to prevent abuse.
* **Validate API input:** Validate all API input to prevent injection attacks.
* **Sanitize API output:** Sanitize all API output to prevent XSS attacks.
* **Log API requests:** Log all API requests for auditing and security monitoring.
## 5. Testing Approaches
### 5.1. Unit Testing
* **Test individual units of code:** Focus on testing individual functions, methods, or classes in isolation.
* **Use a testing framework:** Use a unit testing framework like PHPUnit or Codeception.
* **Write testable code:** Design code to be easily testable (e.g., use dependency injection).
* **Follow the Arrange-Act-Assert pattern:** Arrange the test data, act on the code being tested, and assert the expected results.
* **Test edge cases:** Test edge cases and boundary conditions to ensure that code handles unexpected input correctly.
### 5.2. Integration Testing
* **Test interactions between components:** Focus on testing how different components of the application interact with each other.
* **Use a testing framework:** Use an integration testing framework like PHPUnit or Codeception.
* **Test database interactions:** Test database interactions to ensure that data is stored and retrieved correctly.
* **Test API integrations:** Test API integrations to ensure that data is exchanged correctly.
### 5.3. End-to-End Testing
* **Test the entire application flow:** Focus on testing the entire application flow from start to finish.
* **Use a testing framework:** Use an end-to-end testing framework like Selenium or Cypress.
* **Automate tests:** Automate end-to-end tests to ensure that the application continues to work correctly as it evolves.
### 5.4. Test Organization
* **Create a `tests/` directory:** Store all test files in a `tests/` directory.
* **Mirror the source code structure:** Organize test files to mirror the source code structure (e.g., `tests/Unit/UserControllerTest.php`).
* **Use namespaces:** Use namespaces to organize test classes.
* **Use descriptive test names:** Use descriptive test names that clearly indicate what is being tested.
### 5.5. Mocking and Stubbing
* **Use mocks to isolate units of code:** Use mocks to replace dependencies with controlled test doubles.
* **Use stubs to provide canned responses:** Use stubs to provide canned responses from dependencies.
* **Use a mocking framework:** Use a mocking framework like Mockery or Prophecy.
## 6. Common Pitfalls and Gotchas
### 6.1. Frequent Mistakes
* **Not escaping output:** Failing to escape output, leading to XSS vulnerabilities.
* **Using `mysql_*` functions:** Using deprecated `mysql_*` functions instead of `mysqli_*` or PDO.
* **Not using prepared statements:** Not using prepared statements with parameterized queries, leading to SQL injection vulnerabilities.
* **Ignoring errors:** Ignoring errors and warnings, making it difficult to debug problems.
* **Not using namespaces:** Not using namespaces, leading to naming conflicts.
* **Over-complicating code:** Writing overly complex code that is difficult to understand and maintain.
* **Not following coding standards:** Not following coding standards, leading to inconsistent code.
### 6.2. Edge Cases
* **Handling different character encodings:** Handling different character encodings correctly.
* **Dealing with time zones:** Dealing with time zones correctly.
* **Handling large file uploads:** Handling large file uploads without running out of memory.
* **Dealing with concurrency:** Handling concurrency correctly in multi-threaded applications (less common in typical web applications).
### 6.3. Version-Specific Issues
* **Deprecated features:** Being aware of deprecated features and replacing them with their recommended alternatives.
* **Compatibility issues:** Ensuring that code is compatible with different versions of PHP.
### 6.4. Compatibility Concerns
* **Database drivers:** Ensuring that the correct database drivers are installed and configured.
* **Web server configuration:** Configuring the web server (e.g., Apache, Nginx) correctly to serve PHP applications.
* **Operating system compatibility:** Ensuring that the application works correctly on different operating systems.
### 6.5. Debugging Strategies
* **Use a debugger:** Use a debugger (e.g., Xdebug) to step through code and inspect variables.
* **Log messages:** Insert log messages to track the execution flow and identify problems.
* **Use `var_dump()` or `print_r()`:** Use `var_dump()` or `print_r()` to inspect variables and data structures (use with caution in production).
* **Read error messages:** Carefully read error messages and warnings to understand the cause of problems.
* **Use a linter:** Use a linter to identify potential errors and code style violations.
## 7. Tooling and Environment
### 7.1. Recommended Development Tools
* **IDE:** PhpStorm, VS Code with PHP extensions.
* **Debugger:** Xdebug.
* **Package manager:** Composer.
* **Database client:** Dbeaver, phpMyAdmin.
* **Version control:** Git.
* **Virtualization:** Docker, Vagrant.
* **Profiler:** Xdebug, Blackfire.io
### 7.2. Build Configuration
* **Use Composer:** Use Composer to manage dependencies.
* **Define dependencies in `composer.json`:** List all dependencies in the `composer.json` file.
* **Use semantic versioning:** Use semantic versioning to specify dependency versions.
* **Use a `composer.lock` file:** Commit the `composer.lock` file to version control to ensure that everyone is using the same versions of dependencies.
* **Configure autoloading:** Configure autoloading to automatically load classes.
### 7.3. Linting and Formatting
* **Use a linter:** Use a linter (e.g., PHPStan, Psalm) to identify potential errors and code style violations.
* **Use a code formatter:** Use a code formatter (e.g., PHP CS Fixer) to automatically format code according to coding standards.
* **Configure linting and formatting rules:** Configure linting and formatting rules to enforce coding standards.
* **Integrate linting and formatting into the development workflow:** Integrate linting and formatting into the development workflow to automatically check code for errors and style violations.
### 7.4. Deployment
* **Use version control:** Use version control to track changes to code.
* **Automate deployments:** Automate deployments using a deployment tool (e.g., Deployer, Capistrano).
* **Use environment variables:** Use environment variables to configure application settings for different environments.
* **Separate code and configuration:** Separate code and configuration to make it easier to deploy applications to different environments.
* **Use a build process:** Use a build process to prepare code for deployment (e.g., run linters, formatters, and tests).
* **Test deployments:** Test deployments in a staging environment before deploying to production.
### 7.5. CI/CD
* **Use a CI/CD platform:** Use a CI/CD platform (e.g., Jenkins, Travis CI, CircleCI, GitHub Actions) to automate the build, test, and deployment process.
* **Configure CI/CD pipelines:** Configure CI/CD pipelines to run tests, linters, and formatters automatically on every commit.
* **Automate deployments:** Automate deployments using CI/CD pipelines.
* **Use infrastructure as code:** Use infrastructure as code (e.g., Terraform, Ansible) to manage infrastructure.
This document aims to provide a comprehensive overview of PHP best practices and coding standards. By following these guidelines, developers can create high-quality, maintainable, secure, and performant PHP applications.