--- 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.