What are some best practices for structuring PHP classes and handling object instantiation in complex projects?

When working on complex PHP projects, it's important to follow best practices for structuring classes and handling object instantiation to ensure maintainability and scalability. One common approach is to use namespaces to organize classes, follow the SOLID principles for class design, and utilize dependency injection to manage object dependencies.

// Example of structuring PHP classes with namespaces and dependency injection

// Define namespace for classes
namespace MyProject;

// Define class interfaces
interface LoggerInterface {
    public function log($message);
}

// Define class implementations
class FileLogger implements LoggerInterface {
    public function log($message) {
        // Log message to file
    }
}

class DatabaseLogger implements LoggerInterface {
    public function log($message) {
        // Log message to database
    }
}

// Example of dependency injection
class UserManager {
    private $logger;

    public function __construct(LoggerInterface $logger) {
        $this->logger = $logger;
    }

    public function createUser($username) {
        // Create user logic
        $this->logger->log('User created: ' . $username);
    }
}

// Instantiate objects with dependencies
$fileLogger = new FileLogger();
$userManager = new UserManager($fileLogger);
$userManager->createUser('john_doe');