Microserviço em PHP demonstrando os princípios SOLID e testes unitários, desenvolvido com CodeIgniter 4 (PHP Spark). Este projeto utiliza armazenamento em memória (sem banco de dados) sendo ideal para aprendizado e demonstração de conceitos.
- Pré-requisitos
- Instalação
- Executando o Microserviço
- Executando os Testes
- Endpoints da API
- Documentação Swagger
- Arquitetura e SOLID
- Testes Unitários
- Estrutura de Dados
- Validações e Regras de Negócio
- Exemplos de Uso
- Troubleshooting
- Componentes Implementados
- PHP: 8.1 ou superior
- Composer: Versão mais recente
- Extensões PHP:
mbstringjsonxmlcurl(para testes com curl)
No diretório do projeto, execute:
composer installIsso instalará:
- CodeIgniter 4 Framework
- PHPUnit (para testes)
Certifique-se de que o diretório writable tem permissões adequadas:
chmod -R 755 writablephp -S localhost:8080 -t publicO servidor estará disponível em: http://localhost:8080
php spark servecomposer testOu diretamente:
./vendor/bin/phpunitTeste da Entidade Account:
./vendor/bin/phpunit tests/Unit/Entities/AccountTest.phpTeste do Repository:
./vendor/bin/phpunit tests/Unit/Repositories/InMemoryAccountRepositoryTest.phpTeste do Service:
./vendor/bin/phpunit tests/Unit/Services/AccountServiceTest.php./vendor/bin/phpunit --coverage-html coverageGET /api/accounts
Exemplo:
curl http://localhost:8080/api/accountsResposta:
[
{
"id": 1,
"account_number": "12345-6",
"holder_name": "João Silva",
"balance": 1000.50,
"account_type": "checking",
"created_at": "2024-01-01 10:00:00",
"updated_at": "2024-01-01 10:00:00"
}
]GET /api/accounts/{id}
Exemplo:
curl http://localhost:8080/api/accounts/1Resposta:
{
"id": 1,
"account_number": "12345-6",
"holder_name": "João Silva",
"balance": 1000.50,
"account_type": "checking",
"created_at": "2024-01-01 10:00:00",
"updated_at": "2024-01-01 10:00:00"
}POST /api/accounts
Exemplo:
curl -X POST http://localhost:8080/api/accounts \
-H "Content-Type: application/json" \
-d '{
"account_number": "12345-6",
"holder_name": "João Silva",
"balance": 1000.50,
"account_type": "checking"
}'Campos obrigatórios:
account_number(string)holder_name(string)
Campos opcionais:
balance(float, padrão: 0.0)account_type(string: "checking" ou "savings", padrão: "checking")
Resposta (201 Created):
{
"id": 1,
"account_number": "12345-6",
"holder_name": "João Silva",
"balance": 1000.50,
"account_type": "checking",
"created_at": "2024-01-01 10:00:00",
"updated_at": null
}PUT /api/accounts/{id}
Exemplo:
curl -X PUT http://localhost:8080/api/accounts/1 \
-H "Content-Type: application/json" \
-d '{
"holder_name": "João Silva Santos",
"balance": 1500.00
}'Resposta (200 OK):
{
"id": 1,
"account_number": "12345-6",
"holder_name": "João Silva Santos",
"balance": 1500.00,
"account_type": "checking",
"created_at": "2024-01-01 10:00:00",
"updated_at": "2024-01-01 11:00:00"
}DELETE /api/accounts/{id}
Exemplo:
curl -X DELETE http://localhost:8080/api/accounts/1Resposta (200 OK):
{
"message": "Conta deletada com sucesso"
}Abra no navegador:
http://localhost:8080/swagger
http://localhost:8080/swagger.json
A interface Swagger permite:
- Visualizar todos os endpoints
- Testar requisições diretamente no navegador
- Ver exemplos de requisições e respostas
- Entender a estrutura dos dados
app/
├── Config/ # Configurações do CodeIgniter
├── Controllers/ # Controladores HTTP
├── Entities/ # Entidades de domínio (Account)
├── Repositories/ # Repositórios (In-Memory)
├── Services/ # Camada de serviços
└── Views/ # Views (Swagger)
tests/
└── Unit/ # Testes unitários
├── Entities/
├── Repositories/
└── Services/
- Cada classe tem uma única responsabilidade
Account: Responsável apenas por representar uma conta bancáriaAccountService: Gerencia apenas as regras de negócioInMemoryAccountRepository: Gerencia apenas o armazenamentoAccountController: Responsável apenas por receber requisições HTTP
AccountRepositoryInterface: Permite extensão através de novas implementações (ex: DatabaseRepository) sem modificar o código existente- As classes estão abertas para extensão, fechadas para modificação
- Qualquer implementação de
AccountRepositoryInterfacepode substituirInMemoryAccountRepositorysem quebrar o código
AccountRepositoryInterfacecontém apenas métodos essenciais para operações de conta- Interfaces específicas e focadas
AccountServicedepende deAccountRepositoryInterface(abstração), não de implementações concretasAccountControllerdepende deAccountService(abstração)
- ✅ AccountTest: 7 testes - Testa a entidade Account (depósito, saque, validações)
- ✅ InMemoryAccountRepositoryTest: 8 testes - Testa operações CRUD do repositório
- ✅ AccountServiceTest: 9 testes - Testa regras de negócio e validações
- Total: 24 testes unitários
// Teste de depósito
$account = new Account(null, '12345-6', 'João Silva', 1000.0);
$account->deposit(500.0);
$this->assertEquals(1500.0, $account->getBalance());
// Teste de saque com saldo insuficiente
$account = new Account(null, '12345-6', 'João Silva', 1000.0);
$this->expectException(\RuntimeException::class);
$account->withdraw(2000.0);{
"id": 1,
"account_number": "12345-6",
"holder_name": "João Silva",
"balance": 1000.50,
"account_type": "checking",
"created_at": "2024-01-01 10:00:00",
"updated_at": "2024-01-01 11:00:00"
}Campos:
id: ID único da conta (gerado automaticamente)account_number: Número da conta bancáriaholder_name: Nome do titular da contabalance: Saldo atual (float)account_type: Tipo de conta ("checking" ou "savings")created_at: Data de criaçãoupdated_at: Data de última atualização
- ✅ Número da conta é obrigatório
- ✅ Nome do titular é obrigatório
- ✅ Saldo não pode ser negativo
- ✅ Tipo de conta deve ser "checking" ou "savings"
- ✅ Depósito deve ser maior que zero
- ✅ Saque deve ser maior que zero
- ✅ Saque não pode exceder o saldo disponível
Este projeto utiliza armazenamento em memória (In-Memory) para fins didáticos. Os dados são perdidos quando o servidor é reiniciado.
Para produção, você pode criar uma nova implementação de AccountRepositoryInterface que utilize banco de dados.
# 1. Criar conta
curl -X POST http://localhost:8080/api/accounts \
-H "Content-Type: application/json" \
-d '{"account_number": "12345-6", "holder_name": "João Silva", "balance": 1000.0}'
# 2. Listar todas as contas
curl http://localhost:8080/api/accounts
# 3. Buscar conta específica
curl http://localhost:8080/api/accounts/1
# 4. Atualizar conta
curl -X PUT http://localhost:8080/api/accounts/1 \
-H "Content-Type: application/json" \
-d '{"balance": 1500.0}'
# 5. Deletar conta
curl -X DELETE http://localhost:8080/api/accounts/1curl -X POST http://localhost:8080/api/accounts \
-H "Content-Type: application/json" \
-d '{
"account_number": "12345-6",
"holder_name": "João Silva",
"balance": 1000.50,
"account_type": "checking"
}'curl http://localhost:8080/api/accountscurl http://localhost:8080/api/accounts/1curl -X PUT http://localhost:8080/api/accounts/1 \
-H "Content-Type: application/json" \
-d '{
"holder_name": "João Silva Santos",
"balance": 1500.00
}'curl -X DELETE http://localhost:8080/api/accounts/1Solução: Execute composer dump-autoload
Solução: chmod -R 755 writable
Solução: Use outra porta: php -S localhost:8081 -t public
Solução: Verifique se PHPUnit está instalado: composer install --dev
- ✅ CodeIgniter 4 Framework
- ✅ PHP 8.1+
- ✅ Composer para gerenciamento de dependências
- ✅ Estrutura de diretórios organizada
- ✅
Account.php- Entidade de Conta Bancária- Métodos: deposit(), withdraw()
- Validações de negócio
- Transformação para array
- ✅
AccountRepositoryInterface.php- Interface (abstração) - ✅
InMemoryAccountRepository.php- Implementação em memória- CRUD completo
- Armazenamento temporário (sem banco de dados)
- ✅
AccountService.php- Regras de negócio- Validações de dados
- Orquestração de operações
- Tratamento de erros
- ✅
AccountController.php- CRUD RESTful- GET /api/accounts - Listar
- GET /api/accounts/{id} - Buscar
- POST /api/accounts - Criar
- PUT /api/accounts/{id} - Atualizar
- DELETE /api/accounts/{id} - Deletar
- ✅
SwaggerController.php- Interface Swagger - ✅
SwaggerJsonController.php- JSON OpenAPI
- ✅
AccountTest.php- Testes da entidade- Criação de conta
- Depósito e saque
- Validações
- ✅
InMemoryAccountRepositoryTest.php- Testes do repositório- CRUD completo
- Casos de erro
- ✅
AccountServiceTest.php- Testes do serviço- Regras de negócio
- Validações
- Tratamento de erros
- ✅ Swagger/OpenAPI integrado
- ✅ README.md completo
- CodeIgniter 4: Framework PHP
- PHPUnit: Framework de testes
Este projeto foi desenvolvido para demonstrar:
- ✅ Aplicação dos princípios SOLID
- ✅ Arquitetura em camadas (Controller → Service → Repository)
- ✅ Testes unitários abrangentes
- ✅ Documentação Swagger/OpenAPI
- ✅ Padrões de design (Repository, Service)
- ✅ Injeção de dependências
- ✅ Separação de responsabilidades
- Armazenamento em Memória: Os dados são perdidos quando o servidor é reiniciado
- Sem Banco de Dados: Este projeto é didático e não utiliza banco de dados
- Ambiente de Desenvolvimento: Configurado para desenvolvimento, não para produção
Este é um projeto educacional para fins de demonstração.
Desenvolvido para fins educacionais e demonstração de conceitos SOLID e Testes Unitários em PHP