Files
blog-api/README.md

548 lines
18 KiB
Markdown

# 📰 BLOG-API — Microserviço de Blog/Notícias
![PHP](https://img.shields.io/badge/PHP-8.2%2B-777BB4?style=flat-square&logo=php&logoColor=white)
![Laravel](https://img.shields.io/badge/Laravel-12.x-FF2D20?style=flat-square&logo=laravel&logoColor=white)
![MySQL](https://img.shields.io/badge/MySQL%2FMariaDB-Banco%20de%20Dados-4479A1?style=flat-square&logo=mysql&logoColor=white)
![Status](https://img.shields.io/badge/Status-Funcional-brightgreen?style=flat-square)
Este é o microserviço responsável pelo gerenciamento de **posts**, **categorias**, **notícias publicadas**, **conteúdos em destaque** e **listagens públicas filtradas** dentro de um ecossistema baseado em APIs. O serviço permite cadastrar, consultar, atualizar e remover conteúdos de blog/notícias, além de disponibilizar endpoints públicos para consumo por frontend, gateway ou outros microsserviços.
---
## 👥 Integrantes do Grupo
- **João Carlos Campos**
- **Lucas Higinio**
---
## 📝 Descrição do Serviço
O **BLOG-API** atua como o serviço central de publicação de conteúdos informativos em uma arquitetura de microsserviços. Ele resolve o problema de organização e distribuição de notícias, permitindo que administradores cadastrem categorias e posts, enquanto usuários e outros serviços consomem apenas os conteúdos públicos publicados.
A API foi desenvolvida em **Laravel 12**, utilizando uma estrutura organizada com **Models**, **Migrations**, **Controllers**, **Form Requests**, **API Resources** e rotas versionadas em `/api/v1`. O projeto está preparado para evoluir com autenticação JWT nas rotas administrativas, mantendo separadas as operações públicas de leitura e as operações administrativas de escrita.
---
## ⚙️ Responsabilidades do Microsserviço
- **Gerenciamento de Categorias:** cadastrar, listar, consultar, atualizar e excluir categorias de notícias.
- **Gerenciamento de Posts:** cadastrar, listar, consultar, atualizar e excluir posts do blog/notícias.
- **Geração de Slugs:** criar slugs automaticamente a partir do nome da categoria ou título do post.
- **Controle de Publicação:** permitir que posts sejam definidos como `draft` ou `published`.
- **Posts em Destaque:** permitir marcação de conteúdos especiais por meio do campo `is_featured`.
- **Listagem Pública:** disponibilizar posts e categorias para consumo externo.
- **Filtros e Paginação:** permitir busca por título, categoria, destaque, status e paginação.
- **Validação de Dados:** validar entradas por meio de Form Requests.
- **Padronização de Respostas:** retornar dados em JSON utilizando API Resources.
- **Health Checks:** fornecer rotas para verificar a saúde da API e da conexão com o banco.
---
## 🛠️ Tecnologias Utilizadas
| Tecnologia | Uso no Projeto |
|---|---|
| **PHP 8.2+** | Linguagem principal utilizada pela aplicação. |
| **Laravel 12** | Framework utilizado para construção da API REST. |
| **Composer** | Gerenciador de dependências PHP. |
| **MySQL/MariaDB** | Banco de dados relacional utilizado pelo microserviço. |
| **XAMPP** | Ambiente local usado para executar Apache, PHP e MySQL/MariaDB no Windows. |
| **PowerShell** | Terminal utilizado para execução dos comandos e testes locais. |
| **Git** | Controle de versão do código-fonte. |
| **GitHub/Git remoto** | Hospedagem do repositório e entrega do projeto. |
---
## ⚙️ Requisitos Necessários
Para rodar este microserviço localmente, é necessário ter instalado:
- **PHP 8.2 ou superior**.
- **Composer 2.x ou superior**.
- **MySQL ou MariaDB**, podendo ser pelo XAMPP.
- **Git** para clonar e versionar o projeto.
- **PowerShell**, Prompt de Comando, Git Bash ou terminal equivalente.
| Requisito | Versão Recomendada |
|---|---|
| PHP | 8.2+ |
| Laravel | 12.x |
| Composer | 2.x+ |
| Banco de dados | MySQL 8.x ou MariaDB compatível |
| Servidor local | XAMPP ou equivalente |
---
## 📦 Ambiente de Execução
Este projeto foi configurado para execução **sem Docker**, utilizando ambiente local com **XAMPP** no Windows. Portanto, os arquivos `Dockerfile` e `docker-compose.yml` não são obrigatórios nesta entrega.
> A opção escolhida para esta entrega foi a execução local sem Docker. Caso o projeto seja migrado futuramente para containers, será necessário criar o `Dockerfile`, o `docker-compose.yml` e atualizar esta documentação com portas, serviços, volumes e variáveis de ambiente.
---
## 🚀 Passo a Passo de Instalação e Execução
### 1. Clonar o Repositório
```bash
git clone https://github.com/JCUNME12/BLOG-API.git
cd BLOG-API
```
Caso esteja usando o repositório institucional, utilize:
```bash
git clone https://git.juancjc.com.br/Joao_Carlos_Campos/blog-api.git
cd blog-api
```
### 2. Instalar as Dependências
```bash
composer install
```
### 3. Criar o Arquivo `.env`
No Windows PowerShell, execute:
```powershell
copy .env.example .env
```
Em Linux, macOS ou Git Bash, execute:
```bash
cp .env.example .env
```
### 4. Gerar a Chave da Aplicação
```bash
php artisan key:generate
```
### 5. Criar o Banco de Dados
No MySQL/MariaDB, crie um banco chamado `blog_api`:
```sql
CREATE DATABASE blog_api;
```
### 6. Executar as Migrations
```bash
php artisan migrate
```
### 7. Iniciar o Servidor Local
```bash
php artisan serve
```
A aplicação ficará disponível em:
```text
http://127.0.0.1:8000
```
---
## 🔐 Configuração do `.env`
O arquivo `.env.example` deve ficar versionado no repositório. Já o arquivo `.env` real deve permanecer apenas na máquina local, pois contém configurações específicas do ambiente.
```dotenv
APP_NAME="Blog API"
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://127.0.0.1:8000
APP_LOCALE=pt_BR
APP_FALLBACK_LOCALE=pt_BR
APP_FAKER_LOCALE=pt_BR
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=blog_api
DB_USERNAME=root
DB_PASSWORD=
CACHE_STORE=file
SESSION_DRIVER=file
QUEUE_CONNECTION=sync
LOG_CHANNEL=stack
LOG_LEVEL=debug
```
Após alterar configurações de ambiente, limpe o cache do Laravel:
```bash
php artisan config:clear
php artisan route:clear
```
---
## 🧭 Observação Importante sobre Laravel 12
Em projetos Laravel 12, o arquivo `routes/api.php` precisa estar registrado no `bootstrap/app.php`. O bloco `withRouting` deve conter a entrada `api`:
```php
->withRouting(
web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
```
Sem essa configuração, as rotas `/api/v1/...` podem retornar `404 Not Found`, mesmo que estejam corretamente declaradas no arquivo `routes/api.php`.
---
## 🧪 Como Testar o Projeto
Para testar as rotas da API, podem ser usadas ferramentas como **Postman**, **Insomnia** ou o próprio terminal com **Invoke-RestMethod** no PowerShell.
### Teste de Saúde da API
```powershell
Invoke-RestMethod -Uri "http://127.0.0.1:8000/api/v1/health" -Method Get
```
### Teste de Conexão com o Banco
```powershell
Invoke-RestMethod -Uri "http://127.0.0.1:8000/api/v1/health-check-db" -Method Get
```
### Cabeçalhos Recomendados para POST, PUT e PATCH
```http
Accept: application/json
Content-Type: application/json
```
---
## 🔒 Rotas da API
Todas as rotas principais usam o prefixo `/api/v1`. As rotas públicas são voltadas para leitura, enquanto as rotas administrativas realizam operações de criação, atualização e exclusão.
| Método | Endpoint | Tipo | Descrição |
|---|---|---|---|
| `GET` | `/api/v1/health` | Público | Verifica se a API está online. |
| `GET` | `/api/v1/health-check-db` | Público | Verifica a conexão com o banco de dados. |
| `GET` | `/api/v1/public/posts` | Público | Lista posts publicados com filtros e paginação. |
| `GET` | `/api/v1/public/posts/{slug}` | Público | Busca um post publicado pelo slug. |
| `GET` | `/api/v1/public/categories` | Público | Lista categorias disponíveis. |
| `GET` | `/api/v1/public/categories/{slug}` | Público | Busca uma categoria pelo slug. |
| `GET` | `/api/v1/admin/posts` | Administrativo | Lista posts no contexto administrativo. |
| `POST` | `/api/v1/admin/posts` | Administrativo | Cria um novo post. |
| `GET` | `/api/v1/admin/posts/{id}` | Administrativo | Busca um post por ID. |
| `PUT/PATCH` | `/api/v1/admin/posts/{id}` | Administrativo | Atualiza um post existente. |
| `DELETE` | `/api/v1/admin/posts/{id}` | Administrativo | Remove um post. |
| `GET` | `/api/v1/admin/categories` | Administrativo | Lista categorias no contexto administrativo. |
| `POST` | `/api/v1/admin/categories` | Administrativo | Cria uma nova categoria. |
| `GET` | `/api/v1/admin/categories/{id}` | Administrativo | Busca uma categoria por ID. |
| `PUT/PATCH` | `/api/v1/admin/categories/{id}` | Administrativo | Atualiza uma categoria existente. |
| `DELETE` | `/api/v1/admin/categories/{id}` | Administrativo | Remove uma categoria sem posts vinculados. |
---
## 🔎 Filtros Disponíveis na Listagem de Posts
| Parâmetro | Tipo | Exemplo | Finalidade |
|---|---|---|---|
| `search` | string | `/api/v1/public/posts?search=Laravel` | Busca posts pelo título. |
| `category_id` | integer | `/api/v1/public/posts?category_id=1` | Filtra posts por ID da categoria. |
| `category_slug` | string | `/api/v1/public/posts?category_slug=tecnologia` | Filtra posts pelo slug da categoria. |
| `is_featured` | boolean | `/api/v1/public/posts?is_featured=true` | Filtra posts em destaque. |
| `status` | string | `/api/v1/public/posts?status=published` | Filtra por `draft` ou `published`. |
| `per_page` | integer | `/api/v1/public/posts?per_page=15` | Define a quantidade de itens por página. |
---
## 📤 Exemplos de Requisição e Resposta em JSON
### Criar Categoria
**Endpoint:** `POST /api/v1/admin/categories`
**Corpo da requisição:**
```json
{
"name": "Tecnologia",
"description": "Noticias sobre tecnologia, inovacao e software."
}
```
**Retorno esperado:**
```json
{
"data": {
"id": 1,
"name": "Tecnologia",
"slug": "tecnologia",
"description": "Noticias sobre tecnologia, inovacao e software.",
"posts_count": 0,
"created_at": "2026-05-28T16:17:19.000000Z",
"updated_at": "2026-05-28T16:17:19.000000Z"
}
}
```
### Criar Post
**Endpoint:** `POST /api/v1/admin/posts`
**Corpo da requisição:**
```json
{
"title": "Laravel 12 em Microsservicos",
"content": "Conteudo completo da noticia sobre Laravel 12 em uma arquitetura de microsservicos.",
"excerpt": "Resumo da noticia sobre Laravel 12.",
"category_id": 1,
"featured_image": "https://cdn.example.com/images/laravel.jpg",
"is_featured": true,
"status": "published",
"published_at": "2026-05-28 10:00:00"
}
```
**Retorno esperado:**
```json
{
"data": {
"id": 1,
"title": "Laravel 12 em Microsservicos",
"slug": "laravel-12-em-microsservicos",
"content": "Conteudo completo da noticia sobre Laravel 12 em uma arquitetura de microsservicos.",
"excerpt": "Resumo da noticia sobre Laravel 12.",
"featured_image": "https://cdn.example.com/images/laravel.jpg",
"is_featured": true,
"status": "published",
"published_at": "2026-05-28T10:00:00.000000Z",
"category": {
"id": 1,
"name": "Tecnologia",
"slug": "tecnologia",
"description": "Noticias sobre tecnologia, inovacao e software."
}
}
}
```
### Listar Posts Publicados
**Endpoint:** `GET /api/v1/public/posts`
**Retorno esperado:**
```json
{
"data": [
{
"id": 1,
"title": "Laravel 12 em Microsservicos",
"slug": "laravel-12-em-microsservicos",
"excerpt": "Resumo da noticia sobre Laravel 12.",
"is_featured": true,
"status": "published",
"published_at": "2026-05-28T10:00:00.000000Z",
"category": {
"id": 1,
"name": "Tecnologia",
"slug": "tecnologia"
}
}
],
"links": {
"first": "http://127.0.0.1:8000/api/v1/public/posts?page=1",
"last": "http://127.0.0.1:8000/api/v1/public/posts?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"per_page": 15,
"total": 1
}
}
```
### Excluir Post
**Endpoint:** `DELETE /api/v1/admin/posts/1`
**Retorno esperado:**
```json
{
"message": "Post deleted successfully."
}
```
---
## 📥 Dados Recebidos e Retornados
O serviço recebe dados relacionados às entidades **Categoria** e **Post**. As respostas são retornadas em JSON e seguem uma estrutura padronizada por meio de API Resources.
| Entidade | Dados Recebidos |
|---|---|
| Categoria | `name`, `slug` opcional, `description` |
| Post | `title`, `slug` opcional, `content`, `excerpt`, `category_id`, `featured_image`, `is_featured`, `status`, `published_at` |
| Resposta | Dados Retornados |
|---|---|
| Categoria | `id`, `name`, `slug`, `description`, `posts_count`, `created_at`, `updated_at` |
| Post | `id`, `title`, `slug`, `content`, `excerpt`, `featured_image`, `is_featured`, `status`, `published_at`, `category`, `created_at`, `updated_at` |
| Paginação | `data`, `links`, `meta` |
---
## 🔗 Integrações com Outros Microsserviços
Este serviço trabalha de forma desacoplada, mas foi projetado para integrar um ecossistema maior. Nesta versão, a integração real implementada é com seu próprio banco de dados. As demais integrações estão documentadas como evolução futura.
| Serviço | Tipo de Integração | Situação | Descrição |
|---|---|---|---|
| **Banco MySQL/MariaDB** | Consumo direto | Implementado | Armazena posts, categorias e metadados. |
| **Auth Service** | Consumo futuro | Preparado | Poderá validar tokens JWT para proteger rotas administrativas. |
| **API Gateway** | Consumidor da API | Previsto | Poderá centralizar chamadas para o BLOG-API. |
| **Frontend Web/Mobile** | Consumidor da API | Previsto | Poderá exibir posts, categorias, destaques e buscas. |
| **Notification Service** | Consumidor futuro | Previsto | Poderá notificar usuários quando novos posts forem publicados. |
| **Search Service** | Consumidor futuro | Previsto | Poderá indexar posts publicados para busca global. |
| **Media/Storage Service** | Consumo futuro | Previsto | Poderá armazenar imagens usadas no campo `featured_image`. |
---
## 🔄 Fluxo Principal do Serviço
O fluxo principal começa quando um administrador cria uma categoria e cadastra um post vinculado a ela. O BLOG-API valida os dados recebidos, gera o slug automaticamente, salva o conteúdo no banco e disponibiliza o post nas rotas públicas quando o status está como `published`.
```text
Administrador cadastra categoria
Administrador publica notícia
BLOG-API valida, gera slug e salva no banco
Frontend/Gateway consulta /api/v1/public/posts
Usuário visualiza notícia publicada
Serviços de busca/notificação podem consumir o conteúdo publicado
```
| Etapa | Descrição |
|---|---|
| 1 | O administrador cria uma categoria, como `Tecnologia`. |
| 2 | O administrador cria um post vinculado à categoria. |
| 3 | O serviço valida os dados usando Form Requests. |
| 4 | O sistema gera automaticamente os slugs. |
| 5 | O post é salvo como `draft` ou `published`. |
| 6 | Se estiver publicado, o post aparece nas rotas públicas. |
| 7 | Frontend, gateway ou outros serviços consomem a listagem. |
---
## ⚠️ Possíveis Erros e Retornos Esperados
Caso algo saia do fluxo ideal, a API retorna códigos HTTP e mensagens adequadas para facilitar o tratamento pelo cliente.
| Situação | Código HTTP | Exemplo de Retorno |
|---|---:|---|
| Dados inválidos | `422` | Campos obrigatórios ausentes ou em formato inválido. |
| Post inexistente | `404` | Registro de post não encontrado. |
| Categoria inexistente | `404` | Registro de categoria não encontrado. |
| Categoria com posts vinculados | `409` | Exclusão bloqueada por conflito de integridade. |
| Erro interno | `500` | Erro inesperado no servidor. |
| Banco indisponível | `503` | Falha no health check do banco de dados. |
### Exemplo de Erro de Validação
```json
{
"message": "The title field is required.",
"errors": {
"title": [
"The title field is required."
]
}
}
```
### Exemplo de Categoria com Posts Vinculados
```json
{
"message": "Category cannot be deleted because it has posts associated."
}
```
---
## 🧾 Arquivos Principais do Projeto
| Arquivo | Responsabilidade |
|---|---|
| `app/Models/Post.php` | Model de posts com relacionamento, casts e slug automático. |
| `app/Models/Category.php` | Model de categorias com relacionamento e slug automático. |
| `app/Http/Controllers/Api/PostController.php` | CRUD, filtros, paginação e respostas de posts. |
| `app/Http/Controllers/Api/CategoryController.php` | CRUD e validações de integridade das categorias. |
| `app/Http/Requests/PostRequest.php` | Validação dos dados de posts. |
| `app/Http/Requests/CategoryRequest.php` | Validação dos dados de categorias. |
| `app/Http/Resources/PostResource.php` | Padronização do JSON de posts. |
| `app/Http/Resources/CategoryResource.php` | Padronização do JSON de categorias. |
| `database/migrations/*create_categories_table.php` | Estrutura da tabela `categories`. |
| `database/migrations/*create_posts_table.php` | Estrutura da tabela `posts`. |
| `routes/api.php` | Rotas versionadas da API. |
| `routes/web.php` | Dashboard simples com rotas disponíveis. |
---
## ✅ Checklist de Entrega
| Item Obrigatório | Situação |
|---|---|
| Link do repositório | Atendido. |
| README completo | Atendido por este arquivo. |
| `.env.example` | Atendido e deve ser versionado. |
| `.env` real fora do Git | Atendido pelo `.gitignore`. |
| Documentação das rotas | Atendido. |
| Exemplos JSON | Atendido. |
| Explicação das integrações | Atendido. |
| Fluxo principal do serviço | Atendido. |
| Como executar localmente | Atendido. |
| Como testar localmente | Atendido. |
| Dockerfile e docker-compose.yml | Não aplicável nesta entrega sem Docker. |
---
## 📚 Referências
- [Laravel 12 Documentation](https://laravel.com/docs/12.x)
- [Composer Documentation](https://getcomposer.org/doc/)
- [PHP Manual](https://www.php.net/manual/pt_BR/)
- [MySQL Documentation](https://dev.mysql.com/doc/)
---
## 📌 Observação Final
Este microserviço está funcional localmente e foi testado com rotas de health check, CRUD de categorias, CRUD de posts, filtros públicos, paginação, slugs automáticos, status de publicação e posts em destaque.