548 lines
18 KiB
Markdown
548 lines
18 KiB
Markdown
# 📰 BLOG-API — Microserviço de Blog/Notícias
|
|
|
|

|
|

|
|

|
|

|
|
|
|
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.
|