---
name: php-dev
description: Desenvolvimento PHP moderno com Laravel, Symfony e APIs RESTful — autenticação (JWT, OAuth, Sanctum), service classes e refactorização de código legacy seguindo padrões PSR.
allowed-tools: Read, Write, Edit, Bash, mcp__memory-supabase__search_memories, mcp__context7__get-library-docs, mcp__notebooklm__notebook_query, mcp__dify-kb__dify_kb_retrieve_segments
---

# PHP Fullstack Engineer

Skill para desenvolvimento PHP moderno seguindo padrões Descomplicar®.

## Contexto NotebookLM

ANTES de executar, consultar notebooks para contexto especializado:

| Notebook | ID | Consultar quando |
|----------|-----|-----------------|
| Programação | 24947ffa-0019-448a-a340-2f4a275d2eb1 | Para padrões gerais |
| Dev PerfexCRM | 80606de8-2783-4d36-b08d-5825e6f9a8da | Para contexto Perfex/CodeIgniter |

```
mcp__notebooklm__notebook_query({
  notebook_id: "24947ffa-0019-448a-a340-2f4a275d2eb1",
  query: "<adaptar ao contexto do pedido do utilizador>"
})
```

```
mcp__notebooklm__notebook_query({
  notebook_id: "80606de8-2783-4d36-b08d-5825e6f9a8da",
  query: "<adaptar ao contexto Perfex/CodeIgniter>"
})
```

Integrar insights do NotebookLM nas recomendações e decisões.

> **Regra #48:** Projectos PHP/Laravel/Symfony devem ser desenvolvidos no **container dev** (`server:"dev"`, path `/root/Dev/<projecto>`). Sincroniza automaticamente com o PC local via Syncthing.

## Quando Usar

- Criar APIs RESTful
- Implementar autenticação (JWT, OAuth, Sanctum)
- Desenvolver service classes
- Refactorizar código legacy
- Integrar com APIs externas

## Protocolo Obrigatório

### 1. Pesquisa Inicial
```
mcp__memory-supabase__search_memories "[keywords php/laravel]"
mcp__wikijs__search_pages "[framework] best practices"
mcp__context7__get-library-docs para documentação actualizada
```

### 2. Quality Gate 70+
- Funções < 50 linhas
- Classes < 500 linhas
- Cyclomatic complexity < 10
- PHPDoc em todas as funções públicas
- Type hints em parâmetros e retornos

### 3. Assinatura Obrigatória
```php
<?php
/**
 * [Nome do Ficheiro/Classe]
 *
 * @author Descomplicar® Crescimento Digital
 * @link https://descomplicar.pt
 * @copyright 2025 Descomplicar®
 */
```

## Padrões de Código

### PHP 8.1+ Features
```php
// Typed properties
private readonly string $name;

// Constructor promotion
public function __construct(
    private readonly ProductService $service
) {}

// Enums
enum Status: string {
    case Active = 'active';
    case Inactive = 'inactive';
}

// Match expression
$result = match($status) {
    Status::Active => 'Activo',
    Status::Inactive => 'Inactivo',
};

// Named arguments
$this->service->create(
    name: $name,
    price: $price
);
```

### PSR Standards
- **PSR-1**: Basic Coding Standard
- **PSR-4**: Autoloading
- **PSR-12**: Extended Coding Style
- **PSR-7**: HTTP Message Interface
- **PSR-15**: HTTP Handlers

## Segurança (OBRIGATÓRIO)

```php
// SQL - SEMPRE prepared statements
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);

// Input validation
$email = filter_var($input, FILTER_VALIDATE_EMAIL);

// Output escaping
echo htmlspecialchars($output, ENT_QUOTES, 'UTF-8');

// Password hashing
$hash = password_hash($password, PASSWORD_ARGON2ID);

// CSRF em forms
<input type="hidden" name="_token" value="<?= csrf_token() ?>">
```

## Padrão Laravel

### Controller
```php
<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Requests\StoreProductRequest;
use App\Http\Resources\ProductResource;
use App\Services\ProductService;
use Illuminate\Http\JsonResponse;

/**
 * ProductController - API de Produtos
 *
 * @author Descomplicar® Crescimento Digital
 * @link https://descomplicar.pt
 * @copyright 2025 Descomplicar®
 */
class ProductController extends Controller
{
    public function __construct(
        private readonly ProductService $productService
    ) {}

    public function index(): JsonResponse
    {
        $products = $this->productService->paginate();
        return ProductResource::collection($products)->response();
    }

    public function store(StoreProductRequest $request): JsonResponse
    {
        $product = $this->productService->create($request->validated());
        return (new ProductResource($product))
            ->response()
            ->setStatusCode(201);
    }
}
```

### Service
```php
<?php

namespace App\Services;

use App\Models\Product;
use App\Repositories\ProductRepository;
use Illuminate\Pagination\LengthAwarePaginator;

/**
 * ProductService - Lógica de negócio Produtos
 *
 * @author Descomplicar® Crescimento Digital
 * @link https://descomplicar.pt
 * @copyright 2025 Descomplicar®
 */
class ProductService
{
    public function __construct(
        private readonly ProductRepository $repository
    ) {}

    public function paginate(array $filters = []): LengthAwarePaginator
    {
        return $this->repository->paginate($filters);
    }

    public function create(array $data): Product
    {
        return $this->repository->create($data);
    }
}
```

### Repository
```php
<?php

namespace App\Repositories;

use App\Models\Product;
use Illuminate\Pagination\LengthAwarePaginator;

/**
 * ProductRepository - Acesso a dados Produtos
 *
 * @author Descomplicar® Crescimento Digital
 * @link https://descomplicar.pt
 * @copyright 2025 Descomplicar®
 */
class ProductRepository
{
    public function paginate(array $filters = []): LengthAwarePaginator
    {
        return Product::query()
            ->when($filters['category'] ?? null, fn($q, $cat) => $q->where('category_id', $cat))
            ->when($filters['active'] ?? null, fn($q, $active) => $q->where('active', $active))
            ->orderBy('created_at', 'desc')
            ->paginate($filters['per_page'] ?? 15);
    }

    public function create(array $data): Product
    {
        return Product::create($data);
    }
}
```

## Debugging PHP

### Xdebug

```php
// php.ini
zend_extension=xdebug.so
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=127.0.0.1
xdebug.client_port=9003
```

### Logging

```php
// Monolog exemplo
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$log = new Logger('app');
$log->pushHandler(new StreamHandler('logs/app.log', Logger::DEBUG));

$log->info('User logged in', ['user_id' => $userId]);
$log->error('Database error', ['exception' => $e->getMessage()]);
```

### Profiling

```bash
# Com Blackfire
blackfire run php script.php

# Com Xhprof
php -d extension=xhprof.so script.php
```

## Testes Unitários

### PHPUnit

```php
<?php

use PHPUnit\Framework\TestCase;

class ProductServiceTest extends TestCase
{
    private ProductService $service;

    protected function setUp(): void
    {
        $this->service = new ProductService(
            new InMemoryProductRepository()
        );
    }

    public function test_create_product(): void
    {
        $product = $this->service->create([
            'name' => 'Test Product',
            'price' => 99.99
        ]);

        $this->assertInstanceOf(Product::class, $product);
        $this->assertEquals('Test Product', $product->name);
    }
}
```

### Pest (alternativa moderna)

```php
<?php

test('creates product', function () {
    $product = app(ProductService::class)->create([
        'name' => 'Test',
        'price' => 99.99
    ]);

    expect($product)
        ->toBeInstanceOf(Product::class)
        ->name->toBe('Test');
});
```

## Checklist Entrega

- [ ] Assinatura Descomplicar® em todos os ficheiros
- [ ] php -l sem erros
- [ ] PHPDoc em funções públicas
- [ ] Type hints completos
- [ ] PSR-12 compliant
- [ ] Segurança validada (injection, XSS)
- [ ] Se API: documentação endpoints
- [ ] Testes unitários (cobertura >70%)

---

## Datasets Dify (Consulta Obrigatória)

Em caso de dúvidas ou para aprofundar conhecimento, consultar os seguintes datasets via MCP:

| Dataset | ID | Prioridade |
|---------|----|-----------:|
| **TI (Tecnologia da Informação)** | `7f63ec0c-6321-488c-b107-980140199850` | 1 |
| **Desenvolvimento de Software** | `e7c7decc-0ded-4351-ab14-b110b3c38ec9` | 1 |
| **Wordpress** | `9da0b2b9-5051-4b99-b9f6-20bf35067092` | 2 |
| **PerfexCRM** | `43354eb6-f0b2-40cc-aa53-44e375ab347c` | 3 |

### Como Consultar

```javascript
# PRIMARIO: NotebookLM (Gemini 2.5 RAG)
# mcp__notebooklm__notebook_query({notebook_id: "2876d1fe-5cea-4d98-8140-b0e1a81c6bc4", query: "<tema>"})  // Claude Code
# mcp__notebooklm__notebook_query({notebook_id: "73102308-70ef-403e-9be9-eae0cfc62d55", query: "<tema>"})  // Desenvolvimento de MCPs
# mcp__notebooklm__notebook_query({notebook_id: "57d9c6c9-48ba-4d83-8f71-cc890f348a53", query: "<tema>"})  // AI Code Editors
# mcp__notebooklm__notebook_query({notebook_id: "24947ffa-0019-448a-a340-2f4a275d2eb1", query: "<tema>"})  // Programacao
# mcp__notebooklm__notebook_query({notebook_id: "ebee9fe1-78fd-4f85-8938-f19f3ea32131", query: "<tema>"})  // Obsidian + Claude
# FALLBACK: Dify KB (se NotebookLM insuficiente)

// Pesquisar padrões Laravel
mcp__dify-kb__dify_kb_retrieve_segments({
  dataset_id: "e7c7decc-0ded-4351-ab14-b110b3c38ec9",
  query: "laravel service repository pattern"
})

// APIs e autenticação
mcp__dify-kb__dify_kb_retrieve_segments({
  dataset_id: "7f63ec0c-6321-488c-b107-980140199850",
  query: "api rest jwt sanctum"
})

// Desenvolvimento Perfex
mcp__dify-kb__dify_kb_retrieve_segments({
  dataset_id: "43354eb6-f0b2-40cc-aa53-44e375ab347c",
  query: "module development hooks"
})
```

### Quando Consultar

- Implementar padrões de arquitectura
- Desenvolver APIs RESTful
- Integrar sistemas de autenticação
- Criar módulos Perfex CRM
- Refactorizar código legacy

---
**Versão**: 1.0.0 | **Autor**: Descomplicar®

---

## Healing Log

Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.

```jsonl
{"date":"","issue":"","fix":"","source":"user|auto"}
```

*Adicionar nova linha após cada erro corrigido.*
