PHP code example of andydefer / php-services

1. Go to this page and download the library: Download andydefer/php-services library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

andydefer / php-services example snippets


// ✅ Un service = un conteneur de méthodes qui partagent un même domaine
class OrderCalculatorService
{
    // ✅ Des dépendances injectées dans le constructeur
    public function __construct(
        private readonly TaxService $taxService,
        private readonly OrderConfig $config,
    ) {}
    
    // ✅ Des méthodes qui reçoivent leurs données en paramètres
    public function calculateTotal(OrderRecord $order): float
    {
        $subtotal = $this->calculateSubtotal($order);
        $tax = $this->taxService->calculate($subtotal);
        
        return $subtotal + $tax;
    }
    
    // ✅ Pas d'état interne, pas de mémoire entre les appels
    private function calculateSubtotal(OrderRecord $order): float
    {
        return array_reduce($order->items, fn($c, $i) => $c + ($i->price * $i->quantity), 0);
    }
}

// ❌ Un trait : impossible à tester isolément
trait FileCreator
{
    private Filesystem $files;
    
    public function createFile(string $path, string $content): bool
    {
        $this->files = new Filesystem();  // Dépendance cachée
        return $this->files->put($path, $content);
    }
}

class TaskDirective extends AbstractDirective
{
    use FileCreator;  // ❌ Couplage implicite, test impossible
}

// ✅ Un service : testable, injectable, découplé
class FileCreatorService
{
    public function __construct(
        private readonly Filesystem $files,  // ✅ Injection explicite
    ) {}
    
    public function createFile(string $path, string $content): bool
    {
        return $this->files->put($path, $content);
    }
}

class TaskDirective extends AbstractDirective
{
    public function __construct(
        private readonly FileCreatorService $fileCreator,  // ✅ Dépendance claire
    ) {}
}

// Le service
class UserService
{
    public function __construct(
        private readonly UserRepository $repository,
        private readonly LoggerInterface $logger,
    ) {}
    
    public function findActiveUser(int $id): ?User
    {
        $this->logger->info('Searching for active user', ['id' => $id]);
        
        $user = $this->repository->findActive($id);
        
        if (!$user) {
            $this->logger->warning('Active user not found', ['id' => $id]);
            return null;
        }
        
        return $user;
    }
}

// Le test
class UserServiceTest extends TestCase
{
    public function test_findActiveUser_returns_user_when_exists(): void
    {
        // ✅ Toutes les dépendances sont mockables
        $repository = $this->createMock(UserRepository::class);
        $repository->method('findActive')->willReturn($user);
        
        $logger = $this->createMock(LoggerInterface::class);
        $logger->expects($this->once())->method('info');
        
        $service = new UserService($repository, $logger);
        $result = $service->findActiveUser(1);
        
        $this->assertSame($user, $result);
        
        // ✅ Aucune base de données réelle
        // ✅ Aucun fichier log réel
        // ✅ Test rapide, isolé, fiable
    }
}
bash
composer