Directory Structure

A well-organized directory structure is the foundation of any PHP project. Here’s a recommended structure:

/my-php-project
├── /app
│   ├── /Controllers
│   ├── /Models
│   ├── /Views
│   └── /Services
├── /config
├── /public
│   └── index.php
├── /resources
│   ├── /views
│   └── /assets
├── /tests
└── composer.json

Explanation of Directories

DirectoryPurpose
/appContains the core application logic, including controllers, models, and views.
/configStores configuration files for different environments (development, production).
/publicThe document root for the web server; contains the entry point (index.php).
/resourcesHolds view templates and static assets (CSS, JavaScript, images).
/testsContains unit and integration tests to ensure code quality.
composer.jsonManages dependencies and autoloading configurations.

Example of a Controller

namespace App\Controllers;

use App\Models\User;

class UserController
{
    public function show($id)
    {
        $user = User::find($id);
        include_once __DIR__ . '/../Views/user.php';
    }
}

Naming Conventions

Consistent naming conventions enhance code readability and maintainability. Here are some best practices:

  1. Class Names: Use PascalCase for class names.
  • Example: UserController, ProductModel
  1. Method Names: Use camelCase for method names.
  • Example: getUserById(), saveProduct()
  1. Variable Names: Use descriptive names in camelCase.
  • Example: $userId, $productList
  1. File Names: Match file names with class names, using PascalCase.
  • Example: UserController.php, ProductModel.php

Autoloading

Utilizing an autoloader simplifies class loading and enhances performance. Composer provides a robust autoloading mechanism that adheres to PSR-4 standards.

Setting Up Autoloading with Composer

  1. Create a composer.json file in your project root:
{
    "autoload": {
        "psr-4": {
            "App\\": "app/"
        }
    }
}
  1. Run the following command to generate the autoload files:
composer dump-autoload
  1. Include the autoload file in your public/index.php:
require_once '../vendor/autoload.php';

use App\Controllers\UserController;

$controller = new UserController();
$controller->show(1);

Separation of Concerns

Following the Separation of Concerns (SoC) principle helps in creating a modular architecture. Each component of your application should have a specific responsibility:

  • Models: Handle data manipulation and business logic.
  • Controllers: Manage user input and application flow.
  • Views: Present data to the user.

Example of a Model

namespace App\Models;

use PDO;

class User
{
    private $db;

    public function __construct(PDO $db)
    {
        $this->db = $db;
    }

    public function find($id)
    {
        $stmt = $this->db->prepare('SELECT * FROM users WHERE id = :id');
        $stmt->execute(['id' => $id]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
}

Testing Your Code

Implementing tests is vital for maintaining code quality. Use PHPUnit for unit testing your PHP applications.

Example of a Simple Test

  1. Install PHPUnit via Composer:
composer require --dev phpunit/phpunit
  1. Create a test file in the /tests directory:
namespace Tests;

use PHPUnit\Framework\TestCase;
use App\Models\User;

class UserTest extends TestCase
{
    public function testFindUser()
    {
        $user = new User($this->createMock(PDO::class));
        $result = $user->find(1);
        $this->assertNotNull($result);
    }
}
  1. Run your tests:
vendor/bin/phpunit tests

Conclusion

By adhering to these best practices for PHP code organization, you can create a project that is not only easy to navigate but also scalable and maintainable. A well-structured codebase leads to higher productivity and reduces the risk of errors, making it easier for teams to collaborate effectively.


Learn more with useful resources