<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PHP Archives - Leonardo Nascimento | Engenheiro de Software</title>
	<atom:link href="https://leonardonascimento.dev/categoria/php/feed/" rel="self" type="application/rss+xml" />
	<link>https://leonardonascimento.dev/categoria/php/</link>
	<description>Especializado em backend, APIs e sistemas escaláveis. Experiência em arquitetura de sistemas, integrações, mensageria, performance e aplicações de alta disponibilidade.</description>
	<lastBuildDate>Fri, 30 Jan 2026 02:50:50 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://leonardonascimento.dev/wp-content/uploads/2021/05/cropped-programming-32x32.png</url>
	<title>PHP Archives - Leonardo Nascimento | Engenheiro de Software</title>
	<link>https://leonardonascimento.dev/categoria/php/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Sistema completo de cobranças via WhatsApp: boleto, Pix e NF-e na prática</title>
		<link>https://leonardonascimento.dev/blog/sistema-completo-de-cobrancas-via-whatsapp-boleto-pix-e-nf/</link>
					<comments>https://leonardonascimento.dev/blog/sistema-completo-de-cobrancas-via-whatsapp-boleto-pix-e-nf/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Fri, 30 Jan 2026 11:00:00 +0000</pubDate>
				<category><![CDATA[API]]></category>
		<category><![CDATA[Arquitetura]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[Dicas & Truques]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Produção]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[api banco inter]]></category>
		<category><![CDATA[api rest]]></category>
		<category><![CDATA[automação financeira]]></category>
		<category><![CDATA[boleto banco inter]]></category>
		<category><![CDATA[boleto registrado]]></category>
		<category><![CDATA[cache redis]]></category>
		<category><![CDATA[cobrança automatizada]]></category>
		<category><![CDATA[cobrança recorrente]]></category>
		<category><![CDATA[cron laravel]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[inadimplência]]></category>
		<category><![CDATA[integração banco inter]]></category>
		<category><![CDATA[laravel]]></category>
		<category><![CDATA[laravel 8]]></category>
		<category><![CDATA[laravel scheduler]]></category>
		<category><![CDATA[ligação automática]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[oauth2]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[php-fpm]]></category>
		<category><![CDATA[pix api]]></category>
		<category><![CDATA[pix dinâmico]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[sistema de cobranças]]></category>
		<category><![CDATA[sms cobrança]]></category>
		<category><![CDATA[webhooks]]></category>
		<category><![CDATA[whatsapp api]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2360</guid>

					<description><![CDATA[<p>Automatizar cobranças nunca foi simples. Entre regras bancárias, vencimentos, Pix, boletos registrados, notificações, inadimplência e conciliação, a maioria dos sistemas acaba virando um emaranhado de scripts difíceis de manter. Neste artigo, vou mostrar como funciona, na prática, um sistema real de cobrança construído em Laravel, integrando Boleto e Pix do Banco Inter, com webhooks, PDFs, [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/sistema-completo-de-cobrancas-via-whatsapp-boleto-pix-e-nf/">Sistema completo de cobranças via WhatsApp: boleto, Pix e NF-e na prática</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><a href="https://leonardonascimento.dev/blog/fluxo-n8n-api-whatsapp-log-com-dedupe-e-tratamento-de-erro/" type="post" id="2316">Automatizar </a>cobranças nunca foi simples. Entre regras bancárias, vencimentos, Pix, boletos registrados, notificações, inadimplência e conciliação, a maioria dos sistemas acaba virando um emaranhado de scripts difíceis de manter.</p>



<p>Neste artigo, vou mostrar <strong>como funciona, na prática</strong>, um sistema real de cobrança construído em <strong><a href="https://leonardonascimento.dev/categoria/laravel" type="link" id="https://leonardonascimento.dev/categoria/laravel" target="_blank" rel="noreferrer noopener nofollow">Laravel</a></strong>, integrando <strong>Boleto e Pix do Banco Inter</strong>, com <strong>webhooks</strong>, <strong>PDFs</strong>, <strong>crons</strong>, <strong>Docker</strong>, <strong>e-mails</strong>, <strong>WhatsApp</strong>, <strong>SMS</strong> e até <strong>ligações automáticas</strong>.</p>



<p>Todo o conteúdo é baseado em um projeto open source real, usado em produção, disponível no GitHub:</p>



<p>👉 <strong>Repositório:</strong><br><a href="https://github.com/leonardop21/boleto-inter-free">https://github.com/leonardop21/boleto-inter-free</a></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Importante: este não é um “tutorial de Hello World”. É um guia técnico completo, voltado para quem quer <strong>entender arquitetura</strong>, <strong>evitar erros comuns</strong> e <strong>colocar cobrança automática em produção com segurança</strong>.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-por-que-integrar-diretamente-com-o-banco-inter">Por que integrar diretamente com o Banco Inter?</h2>



<p>O Banco Inter oferece uma <a href="https://leonardonascimento.dev/blog/arquitetura-de-uma-api-rest-em-laravel-preparada-para-producao/" type="post" id="2358">API </a>robusta para PJ, com suporte nativo a:</p>



<ul class="wp-block-list">
<li>Boletos registrados</li>



<li>Pix com QR Code dinâmico</li>



<li>Webhooks de status</li>



<li>Consulta de cobranças</li>



<li>Download de PDFs</li>



<li>Extratos bancários</li>
</ul>



<p>Ao integrar diretamente com o Inter, você elimina intermediários, reduz custos e ganha controle total sobre o fluxo financeiro.</p>



<p>Mas isso vem com desafios:</p>



<ul class="wp-block-list">
<li>Certificados mTLS</li>



<li>OAuth2</li>



<li>Regras rígidas de vencimento</li>



<li>Webhooks que precisam ser idempotentes</li>



<li>PDFs que precisam ser armazenados ou regenerados</li>



<li>Conciliação automática</li>
</ul>



<p>É exatamente isso que o projeto resolve.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-visao-geral-da-arquitetura-do-sistema">Visão geral da arquitetura do sistema</h2>



<p>Antes de entrar em código, é importante entender <strong>como o sistema foi pensado</strong>.</p>



<h3 class="wp-block-heading" id="h-componentes-principais">Componentes principais</h3>



<ul class="wp-block-list">
<li><strong>Laravel 8</strong> como base</li>



<li><strong>MySQL</strong> para dados transacionais</li>



<li><strong>Redis</strong> para cache com tags</li>



<li><strong>Banco Inter API</strong> para cobranças</li>



<li><strong>Notifish</strong> para WhatsApp</li>



<li><strong>SMTP</strong> para e-mails</li>



<li><strong>SMS Dev</strong> para SMS</li>



<li><strong>King SMS (Voicer)</strong> para ligações</li>



<li><strong>Docker + Nginx + PHP-FPM</strong> em produção</li>
</ul>



<p>Nada aqui é experimental. Tudo foi pensado para <strong>rodar 24/7</strong>, com falhas previsíveis e logs rastreáveis.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-por-que-redis-e-obrigatorio-neste-projeto">Por que Redis é obrigatório neste projeto?</h2>



<p>Um erro comum em sistemas de cobrança é <strong>consultar a API do banco o tempo todo</strong>.</p>



<p>Esse projeto evita isso usando <strong>cache agressivo com tags</strong>, por exemplo:</p>



<ul class="wp-block-list">
<li>Cache de cobranças</li>



<li>Cache de clientes</li>



<li>Cache de serviços</li>



<li>Cache de status de boletos e Pix</li>
</ul>



<p>Quando um boleto muda de status (via webhook), o cache relacionado é invalidado.</p>



<p>👉 Sem Redis (ou Memcached), o sistema <strong>não funciona corretamente</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-instalacao-do-projeto-ambiente-local">Instalação do projeto (ambiente local)</h2>



<h3 class="wp-block-heading" id="h-1-clonando-o-repositorio">1. Clonando o repositório</h3>



<pre class="wp-block-code"><code>git clone https://github.com/leonardop21/boleto-inter-free.git
cd boleto-inter-free
composer install
</code></pre>



<h3 class="wp-block-heading" id="h-2-configuracao-inicial">2. Configuração inicial</h3>



<pre class="wp-block-code"><code>cp .env.example .env
php artisan key:generate
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-configurando-o-banco-de-dados-e-cache">Configurando o banco de dados e cache</h2>



<p>No <code>.env</code>:</p>



<pre class="wp-block-code"><code>DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=boleto_inter
DB_USERNAME=user
DB_PASSWORD=pass

CACHE_DRIVER=redis
SESSION_DRIVER=redis
TIME_CACHE_IN_SECONDS=604800
</code></pre>



<p>Depois:</p>



<pre class="wp-block-code"><code>php artisan migrate
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-como-funciona-o-modelo-de-cobranca">Como funciona o modelo de cobrança</h2>



<p>O sistema foi pensado para <strong>cobrança recorrente</strong>, mas funciona também para cobranças pontuais.</p>



<h3 class="wp-block-heading" id="h-entidades-principais">Entidades principais</h3>



<ul class="wp-block-list">
<li><strong>Cliente</strong></li>



<li><strong>Serviço</strong></li>



<li><strong>Cliente x Serviço</strong></li>



<li><strong>Boleto</strong></li>



<li><strong>Pix</strong></li>



<li><strong>NF-e (opcional)</strong></li>
</ul>



<p>O fluxo é simples:</p>



<ol class="wp-block-list">
<li>Você cadastra um cliente</li>



<li>Cadastra um serviço</li>



<li>Vincula o serviço ao cliente</li>



<li>O sistema gera boletos ou Pix automaticamente</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-integracao-com-o-banco-inter-parte-critica">Integração com o Banco Inter (parte crítica)</h2>



<h3 class="wp-block-heading" id="h-certificados-mtls">Certificados mTLS</h3>



<p>O Inter exige:</p>



<ul class="wp-block-list">
<li>Um arquivo <code>.crt</code></li>



<li>Um arquivo <code>.key</code></li>
</ul>



<p>No <code>.env</code>:</p>



<pre class="wp-block-code"><code>INTER_PATH_CRT=/caminho/inter.crt
INTER_PATH_KEY=/caminho/inter.key
</code></pre>



<h3 class="wp-block-heading" id="h-oauth2">OAuth2</h3>



<pre class="wp-block-code"><code>INTER_CLIENT_ID=seu_client_id
INTER_CLIENT_SECRET=seu_client_secret
INTER_CLIENT_SCOPE="extrato.read boleto-cobranca.read boleto-cobranca.write"
INTER_BASE_URL="https://cdpj.partners.bancointer.com.br/"
</code></pre>



<p>Sem isso, <strong>nenhuma requisição funciona</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-webhooks-o-coracao-da-automacao">Webhooks: o coração da automação</h2>



<p>O sistema registra dois webhooks no Inter:</p>



<ul class="wp-block-list">
<li><strong>Boleto</strong></li>



<li><strong>Pix</strong></li>
</ul>



<pre class="wp-block-code"><code>INTER_WEBHOOK_URL=https://seusite.com/api/inter/webhook/boleto
INTER_WEBHOOK_URL_PIX=https://seusite.com/api/inter/webhook/pix
</code></pre>



<h3 class="wp-block-heading" id="h-o-que-acontece-quando-um-pagamento-e-feito">O que acontece quando um pagamento é feito?</h3>



<ol class="wp-block-list">
<li>O Inter chama o webhook</li>



<li>O sistema valida a assinatura</li>



<li>Atualiza o status da cobrança</li>



<li>Invalida caches relacionados</li>



<li>Registra logs</li>



<li>(Opcional) dispara notificações internas</li>
</ol>



<p>Isso evita:</p>



<ul class="wp-block-list">
<li>Jobs de polling</li>



<li>Consultas desnecessárias</li>



<li>Status desatualizado</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-geracao-automatica-de-boletos">Geração automática de boletos</h2>



<p>Este é um dos pontos mais sofisticados do projeto.</p>



<p>Comando:</p>



<pre class="wp-block-code"><code>php artisan ln:auto_generate_boleto
</code></pre>



<h3 class="wp-block-heading" id="h-regras-implementadas">Regras implementadas</h3>



<ul class="wp-block-list">
<li>Se o dia de vencimento já passou → gera para o mês seguinte</li>



<li>Se o cliente escolheu dia 31 → ajusta para último dia do mês</li>



<li>Respeita meses com 28, 29, 30 ou 31 dias</li>



<li>Evita boletos duplicados</li>



<li>Gera PDF automaticamente</li>



<li>Salva logs detalhados</li>
</ul>



<p>Tudo isso roda <strong>sem intervenção humana</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-geracao-automatica-de-pix">Geração automática de Pix</h2>



<p>Comando:</p>



<pre class="wp-block-code"><code>php artisan ln:auto_generate_pix
</code></pre>



<ul class="wp-block-list">
<li>Gera QR Code</li>



<li>Gera payload Pix</li>



<li>Cria cobrança no Inter</li>



<li>Registra vencimento</li>



<li>Gera imagem do QR Code (GD)</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-envio-de-cobrancas-por-e-mail">Envio de cobranças por e-mail</h2>



<p>O sistema envia:</p>



<ul class="wp-block-list">
<li>Boleto em PDF</li>



<li>Pix com QR Code</li>



<li>NF-e (se configurado)</li>
</ul>



<p>Configuração SMTP no <code>.env</code>:</p>



<pre class="wp-block-code"><code>MAIL_HOST=
MAIL_PORT=587
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=tls
</code></pre>



<p>Além disso, o layout do e-mail é personalizável:</p>



<ul class="wp-block-list">
<li>Logo</li>



<li>Cor de fundo</li>



<li>Links de suporte</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-envio-por-whatsapp-notifish">Envio por WhatsApp (Notifish)</h2>



<p>Integração direta com a API do <a href="https://notifish.com/">Notifish</a>.</p>



<pre class="wp-block-code"><code>NOTIFISH_BASE_URL=https://seu.notifish.com/api/v2/
NOTIFISH_API_KEY=sua_key
NOTIFISH_UUID=sua_instancia
</code></pre>



<p>O sistema gera uma <strong>URL assinada temporária</strong> para o PDF do boleto, válida por poucos minutos — sem expor IDs internos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-sms-e-ligacoes-automaticas-para-inadimplentes">SMS e ligações automáticas para inadimplentes</h2>



<h3 class="wp-block-heading" id="h-sms">SMS</h3>



<pre class="wp-block-code"><code>php artisan ln:send-boleto-sms
php artisan ln:send-pix-sms
</code></pre>



<h3 class="wp-block-heading" id="h-ligacao-voz-robotica">Ligação (voz robótica)</h3>



<pre class="wp-block-code"><code>php artisan ln:send-boleto-voicer
php artisan ln:send-pix-voicer
</code></pre>



<p>Isso é usado <strong>somente após o vencimento</strong>, como camada extra de cobrança.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-crons-como-tudo-roda-sozinho">Crons: como tudo roda sozinho</h2>



<p>Você <strong>não agenda cada comando individualmente</strong>.</p>



<p>Apenas:</p>



<pre class="wp-block-code"><code>* * * * * php artisan schedule:run
</code></pre>



<p>O Laravel Scheduler cuida do resto.</p>



<p>Exemplo:</p>



<ul class="wp-block-list">
<li>Dia 1 → gera boletos</li>



<li>Antes do vencimento → envia lembrete</li>



<li>Após vencimento → cobrança progressiva</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-docker-em-producao">Docker em produção</h2>



<p>O projeto já vem com:</p>



<ul class="wp-block-list">
<li><code>Dockerfile</code></li>



<li><code>docker-compose.prod.yml</code></li>



<li>Nginx configurado</li>



<li>PHP-FPM otimizado</li>



<li>Redis</li>



<li>MySQL</li>
</ul>



<p>Subir produção:</p>



<pre class="wp-block-code"><code>docker compose -f docker-compose.prod.yml up -d --build
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-logs-rastreabilidade-e-auditoria">Logs, rastreabilidade e auditoria</h2>



<p>Cada processo tem seu próprio log:</p>



<ul class="wp-block-list">
<li>Boletos</li>



<li>Pix</li>



<li>NF-e</li>



<li>Webhooks</li>



<li>Erros de API</li>
</ul>



<p>Isso é fundamental para:</p>



<ul class="wp-block-list">
<li>Suporte</li>



<li>Auditoria</li>



<li>Contabilidade</li>



<li>Diagnóstico rápido</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-para-quem-este-projeto-e-indicado">Para quem este projeto é indicado?</h2>



<ul class="wp-block-list">
<li>Desenvolvedores PHP/Laravel</li>



<li>SaaS com cobrança recorrente</li>



<li>Sistemas internos de empresas</li>



<li>Agências que querem padronizar cobrança</li>



<li>Projetos que precisam de autonomia financeira</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-conclusao">Conclusão</h2>



<p>Automatizar cobranças não é só “gerar boleto”.<br>É lidar com:</p>



<ul class="wp-block-list">
<li>Datas</li>



<li>Erros bancários</li>



<li>Comunicação</li>



<li>Inadimplência</li>



<li>Escala</li>



<li>Observabilidade</li>
</ul>



<p>Este projeto resolve isso de forma <strong>pragmática</strong>, <strong>realista</strong> e <strong>testada em produção</strong>.</p>



<p>👉 Repositório completo:<br><a href="https://github.com/leonardop21/boleto-inter-free">https://github.com/leonardop21/boleto-inter-free</a></p>



<p></p>
<p>The post <a href="https://leonardonascimento.dev/blog/sistema-completo-de-cobrancas-via-whatsapp-boleto-pix-e-nf/">Sistema completo de cobranças via WhatsApp: boleto, Pix e NF-e na prática</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/sistema-completo-de-cobrancas-via-whatsapp-boleto-pix-e-nf/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Arquitetura de uma API REST em Laravel preparada para produção</title>
		<link>https://leonardonascimento.dev/blog/arquitetura-de-uma-api-rest-em-laravel-preparada-para-producao/</link>
					<comments>https://leonardonascimento.dev/blog/arquitetura-de-uma-api-rest-em-laravel-preparada-para-producao/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Wed, 28 Jan 2026 22:44:00 +0000</pubDate>
				<category><![CDATA[API]]></category>
		<category><![CDATA[Arquitetura]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[Dicas & Truques]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[teste]]></category>
		<category><![CDATA[api rest]]></category>
		<category><![CDATA[arquitetura de software]]></category>
		<category><![CDATA[autenticação api]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[ci/cd]]></category>
		<category><![CDATA[clean architecture]]></category>
		<category><![CDATA[desenvolvimento backend]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[docker compose]]></category>
		<category><![CDATA[documentação api]]></category>
		<category><![CDATA[engenharia de software]]></category>
		<category><![CDATA[github actions]]></category>
		<category><![CDATA[laravel]]></category>
		<category><![CDATA[laravel sanctum]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[projeto para portfólio]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[repository pattern]]></category>
		<category><![CDATA[service layer]]></category>
		<category><![CDATA[swagger]]></category>
		<category><![CDATA[testes automatizados]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2358</guid>

					<description><![CDATA[<p>Em processos seletivos técnicos, não basta entregar código funcional. Cada vez mais, empresas avaliam arquitetura, decisões técnicas, organização do projeto, automação e capacidade de escalar a solução. Este artigo detalha a arquitetura de uma API REST desenvolvida em Laravel para gerenciamento de tarefas, criada como parte de um teste técnico, mas estruturada como um projeto [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/arquitetura-de-uma-api-rest-em-laravel-preparada-para-producao/">Arquitetura de uma API REST em Laravel preparada para produção</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Em processos seletivos técnicos, não basta entregar código funcional. Cada vez mais, empresas avaliam <strong>arquitetura, decisões técnicas, organização do projeto, automação e capacidade de escalar a solução</strong>.</p>



<p>Este artigo detalha a arquitetura de uma <strong><a href="https://leonardonascimento.dev/blog/como-monitorar-aplicacao-e-servidor-pelo-whatsapp-logs-erros-e-alertas/" type="post" id="2290">API REST</a> desenvolvida em Laravel para gerenciamento de tarefas</strong>, <a href="https://github.com/leonardop21/laravel-task" type="link" id="https://github.com/leonardop21/laravel-task" target="_blank" rel="noreferrer noopener nofollow">criada como parte de um teste técnico,</a> mas estruturada como um projeto <strong>pronto para produção</strong>, seguindo boas práticas amplamente utilizadas em ambientes corporativos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-visao-geral-da-solucao">Visão geral da solução</h2>



<p>A aplicação consiste em uma <strong>API RESTful para gerenciamento de tarefas</strong>, com suporte a:</p>



<ul class="wp-block-list">
<li>Autenticação via Bearer Token (Laravel Sanctum)</li>



<li>CRUD completo de tarefas</li>



<li>Marcação de tarefas como concluídas</li>



<li>Cache de consultas com Redis</li>



<li>Banco de dados PostgreSQL</li>



<li>Documentação interativa via Swagger</li>



<li>Ambiente Dockerizado (dev, test e prod)</li>



<li>Testes automatizados</li>



<li>Pipeline de CI/CD com GitHub Actions</li>
</ul>



<p>O foco não foi apenas “fazer funcionar”, mas <strong>pensar a aplicação como um produto escalável e previsível</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-decisao-arquitetural-api-stateless-e-autenticacao">Decisão arquitetural: API stateless e autenticação</h2>



<p>A API foi construída como <strong>stateless</strong>, utilizando <strong>Bearer Token via Laravel Sanctum</strong>.</p>



<h3 class="wp-block-heading" id="h-beneficios-dessa-abordagem">Benefícios dessa abordagem:</h3>



<ul class="wp-block-list">
<li>Facilidade de integração com frontends (SPA, mobile, terceiros)</li>



<li>Independência de sessão</li>



<li>Escalabilidade horizontal</li>



<li>Compatibilidade com gateways, load balancers e proxies</li>
</ul>



<p>A autenticação é desacoplada do fluxo de negócio, o que facilita manutenção e evolução futura.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-postgresql-como-banco-principal">PostgreSQL como banco principal</h2>



<p>A escolha do <strong>PostgreSQL</strong> não foi aleatória. Ele é amplamente utilizado em ambientes corporativos por oferecer:</p>



<ul class="wp-block-list">
<li>Confiabilidade transacional</li>



<li>Suporte avançado a índices</li>



<li>Tipos de dados ricos</li>



<li>Excelente desempenho em cenários complexos</li>
</ul>



<p>Isso torna a aplicação preparada para crescer sem precisar trocar a base de dados no curto ou médio prazo.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-redis-como-camada-de-cache">Redis como camada de cache</h2>



<p>Para reduzir carga no banco e melhorar tempo de resposta, foi implementado <strong>cache com Redis</strong>, com TTL de 120 segundos nas consultas mais comuns.</p>



<h3 class="wp-block-heading" id="h-beneficios-diretos">Benefícios diretos:</h3>



<ul class="wp-block-list">
<li>Redução de queries repetitivas</li>



<li>Menor latência</li>



<li>Melhor desempenho sob carga</li>



<li>Escalabilidade em leitura</li>
</ul>



<p>Essa abordagem demonstra preocupação com <strong>performance real</strong>, não apenas com lógica funcional.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-arquitetura-limpa-repository-pattern-service-layer">Arquitetura limpa: Repository Pattern + Service Layer</h2>



<p><a href="https://leonardonascimento.dev/blog/php-alem-do-crud-como-escrever-codigo-que-nao-vira-problema-em-producao/" type="post" id="2348">A aplicação segue princípios de <strong>Clean Architecture</strong></a>, separando responsabilidades de forma clara:</p>



<ul class="wp-block-list">
<li><strong>Controllers</strong>: recebem requisições e retornam respostas</li>



<li><strong>Services</strong>: concentram regras de negócio</li>



<li><strong>Repositories</strong>: isolam o acesso a dados</li>



<li><strong>Models</strong>: representam as entidades</li>
</ul>



<h3 class="wp-block-heading" id="h-vantagens-dessa-separacao">Vantagens dessa separação:</h3>



<ul class="wp-block-list">
<li>Código mais legível</li>



<li>Facilidade de testes</li>



<li>Menor acoplamento</li>



<li>Evolução segura do domínio</li>
</ul>



<p>Essa estrutura é comum em times maduros e projetos de longo prazo.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-docker-como-base-do-ambiente">Docker como base do ambiente</h2>



<p>Toda a aplicação roda em <strong>Docker</strong>, com ambientes bem definidos:</p>



<h3 class="wp-block-heading" id="h-desenvolvimento">Desenvolvimento</h3>



<ul class="wp-block-list">
<li>Código em volume</li>



<li>Hot reload</li>



<li>PostgreSQL + Redis + Nginx</li>



<li>Testes executados automaticamente</li>
</ul>



<h3 class="wp-block-heading" id="h-producao">Produção</h3>



<ul class="wp-block-list">
<li>Build otimizado</li>



<li>Código embutido na imagem</li>



<li>Assets compilados no build</li>



<li>Sem dependência de volume</li>
</ul>



<p>Essa separação reduz o clássico problema de “funciona na minha máquina” e aproxima o ambiente local da produção.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-testes-automatizados-como-parte-do-fluxo">Testes automatizados como parte do fluxo</h2>



<p>A aplicação conta com <strong>testes unitários e de feature</strong>, executados de três formas:</p>



<ul class="wp-block-list">
<li>Localmente no ambiente dev</li>



<li>Isoladamente via Docker</li>



<li>Automaticamente no CI/CD</li>
</ul>



<p>Isso garante:</p>



<ul class="wp-block-list">
<li>Segurança para refatorações</li>



<li>Detecção precoce de bugs</li>



<li>Confiança na entrega contínua</li>
</ul>



<p>Testes não são tratados como opcional, mas como <strong>parte da arquitetura</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-ci-cd-com-github-actions">CI/CD com GitHub Actions</h2>



<p>Cada push ou pull request dispara um workflow que:</p>



<ol class="wp-block-list">
<li>Sobe toda a stack Docker (app, banco, cache)</li>



<li>Executa migrations</li>



<li>Roda a suíte completa de testes</li>



<li>Bloqueia o merge em caso de falha</li>
</ol>



<p>Esse processo simula um pipeline real de empresas que operam com <strong>entrega contínua e qualidade de código como requisito</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-documentacao-com-swagger">Documentação com Swagger</h2>



<p>A API possui <strong>documentação interativa via Swagger</strong>, acessível após subir a aplicação.</p>



<p>Isso permite:</p>



<ul class="wp-block-list">
<li>Testes manuais rápidos</li>



<li>Onboarding mais fácil</li>



<li>Comunicação clara entre backend e frontend</li>



<li>Uso por terceiros sem dependência de documentação externa</li>
</ul>



<p>Documentação é tratada como parte do produto, não como etapa posterior.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-beneficios-dessa-arquitetura-em-um-contexto-profissional">Benefícios dessa arquitetura em um contexto profissional</h2>



<p>Essa abordagem entrega vantagens claras em ambientes reais:</p>



<ul class="wp-block-list">
<li>Código organizado e previsível</li>



<li>Facilidade de manutenção</li>



<li>Escalabilidade técnica</li>



<li>Padronização de ambientes</li>



<li>Menor risco em deploys</li>



<li>Base sólida para crescimento</li>
</ul>



<p>Não se trata apenas de uma API de tarefas, mas de <strong>um modelo replicável para aplicações reais</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-o-que-esse-projeto-demonstra-tecnicamente">O que esse projeto demonstra tecnicamente</h2>



<p>Esse projeto evidencia competências como:</p>



<ul class="wp-block-list">
<li><a href="http://leonardonascimento.dev/categoria/laravel">Domínio de Laravel além do básico</a></li>



<li>Conhecimento de arquitetura backend</li>



<li>Uso consciente de cache e banco</li>



<li>Experiência com Docker e ambientes reais</li>



<li>Cultura de testes</li>



<li>Automação de CI/CD</li>



<li>Pensamento orientado a produto e escala</li>
</ul>



<p>São exatamente esses pontos que diferenciam um desenvolvedor <strong>pleno/sênior</strong> em processos seletivos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-conclusao">Conclusão</h2>



<p>Mais do que cumprir um teste técnico, o objetivo deste projeto foi demonstrar <strong>capacidade de pensar sistemas como um todo</strong>, indo além do CRUD simples.</p>



<p>Arquitetura, automação, testes e previsibilidade são o que tornam uma aplicação sustentável — e é isso que empresas buscam quando contratam profissionais para projetos de longo prazo.</p>



<p></p>



<p><a href="https://github.com/leonardop21/laravel-task" target="_blank" rel="noreferrer noopener nofollow">Link do teste prático</a></p>
<p>The post <a href="https://leonardonascimento.dev/blog/arquitetura-de-uma-api-rest-em-laravel-preparada-para-producao/">Arquitetura de uma API REST em Laravel preparada para produção</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/arquitetura-de-uma-api-rest-em-laravel-preparada-para-producao/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Automação de WhatsApp para WordPress: uma solução escalável para empresas e portais</title>
		<link>https://leonardonascimento.dev/blog/automacao-de-whatsapp-para-wordpress-uma-solucao-escalavel-para-empresas-e-portais/</link>
					<comments>https://leonardonascimento.dev/blog/automacao-de-whatsapp-para-wordpress-uma-solucao-escalavel-para-empresas-e-portais/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Tue, 27 Jan 2026 11:39:00 +0000</pubDate>
				<category><![CDATA[API]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[Dicas & Truques]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Produção]]></category>
		<category><![CDATA[Seo & Marketing]]></category>
		<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[automação de conteúdo]]></category>
		<category><![CDATA[automação editorial]]></category>
		<category><![CDATA[automação whatsapp]]></category>
		<category><![CDATA[comunicação empresarial]]></category>
		<category><![CDATA[distribuição de conteúdo]]></category>
		<category><![CDATA[integração wordpress]]></category>
		<category><![CDATA[marketing digital b2b]]></category>
		<category><![CDATA[plugin wordpress]]></category>
		<category><![CDATA[whatsapp wordpress]]></category>
		<category><![CDATA[wordpress para empresas]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2355</guid>

					<description><![CDATA[<p>O Notifish é um plugin para WordPress oficialmente aprovado no repositório do WordPress que permite automatizar o envio de conteúdos publicados no site diretamente para o WhatsApp, integrando o fluxo editorial do WordPress a canais de distribuição de alto engajamento. Com a aprovação no diretório oficial, o plugin passa a atender padrões rígidos de segurança, [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/automacao-de-whatsapp-para-wordpress-uma-solucao-escalavel-para-empresas-e-portais/">Automação de WhatsApp para WordPress: uma solução escalável para empresas e portais</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><a href="https://notifish.com/" target="_blank" rel="noreferrer noopener nofollow">O <strong>Notifish</strong> é um plugin para WordPress </a>oficialmente aprovado no repositório do WordPress que permite <strong>automatizar o envio de conteúdos publicados no site diretamente para o WhatsApp</strong>, integrando o fluxo editorial do WordPress a canais de distribuição de alto engajamento.</p>



<p>Com a aprovação no diretório oficial, o plugin passa a atender <strong>padrões rígidos de segurança, qualidade de código e boas práticas exigidas pela equipe do WordPress</strong>, o que garante mais confiabilidade para quem busca soluções profissionais de distribuição de conteúdo.</p>



<p>👉 Repositório oficial do plugin:<br><a href="https://wordpress.org/plugins/notifish/" target="_blank" rel="noreferrer noopener nofollow">https://wordpress.org/plugins/notifish/</a></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-o-que-e-o-plugin-notifish">O que é o plugin Notifish</h2>



<p>O Notifish é um plugin que conecta o WordPress à plataforma Notifish, permitindo que <strong>publicações sejam enviadas automaticamente para grupos, listas ou contatos no <a href="https://leonardonascimento.dev/blog/como-monitorar-aplicacao-e-servidor-pelo-whatsapp-logs-erros-e-alertas/" type="post" id="2290">WhatsApp</a></strong> a partir do momento em que um post é publicado ou atualizado.</p>



<p>Na prática, ele elimina processos manuais comuns em portais, blogs e sites de conteúdo, como copiar links, formatar mensagens e disparar envios individualmente, centralizando tudo dentro do próprio fluxo editorial.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-para-quem-o-notifish-e-indicado">Para quem o Notifish é indicado</h2>



<p>O plugin foi desenvolvido para cenários reais de uso, como:</p>



<ul class="wp-block-list">
<li>Portais de notícias e sites jornalísticos</li>



<li>Blogs com publicação frequente</li>



<li>Produtores de conteúdo e infoprodutores</li>



<li>Empresas que usam WhatsApp como canal de comunicação</li>



<li>Projetos WordPress que dependem de distribuição rápida de conteúdo</li>
</ul>



<p>Em todos esses casos, o WhatsApp deixa de ser apenas um canal complementar e passa a fazer parte da estratégia de publicação.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-como-funciona-a-integracao-com-o-wordpress">Como funciona a integração com o WordPress</h2>



<p>Após a instalação do plugin e a configuração da chave de API, o funcionamento é simples:</p>



<ol class="wp-block-list">
<li>O conteúdo é publicado normalmente no WordPress</li>



<li>O plugin identifica a publicação</li>



<li>O Notifish envia a mensagem para os grupos ou listas configuradas</li>



<li>O envio fica registrado para controle e auditoria</li>
</ol>



<p>Todo o processo acontece de forma transparente para o editor, sem necessidade de ferramentas externas ou fluxos paralelos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-principais-vantagens-do-notifish">Principais vantagens do Notifish</h2>



<h3 class="wp-block-heading" id="h-automacao-real-no-fluxo-editorial">Automação real no fluxo editorial</h3>



<p>O envio das mensagens acontece no momento certo, integrado ao ciclo de publicação, sem depender de ações manuais.</p>



<h3 class="wp-block-heading" id="h-distribuicao-imediata-do-conteudo">Distribuição imediata do conteúdo</h3>



<p>Assim que a matéria vai ao ar, ela já pode ser entregue ao público em um canal com alta taxa de abertura e leitura.</p>



<h3 class="wp-block-heading" id="h-centralizacao-de-operacoes">Centralização de operações</h3>



<p>O <a href="https://leonardonascimento.dev/blog/wordpress-nao-e-amador-amador-e-o-uso-que-fazem-dele/" type="post" id="2338">WordPress </a>deixa de ser apenas um CMS e passa a ser também um ponto central de distribuição de conteúdo.</p>



<h3 class="wp-block-heading" id="h-mais-controle-sobre-comunicacao-via-whatsapp">Mais controle sobre comunicação via WhatsApp</h3>



<p>O uso de automação reduz falhas humanas, duplicidade de envios e inconsistências na comunicação.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-aprovacao-no-repositorio-oficial-do-wordpress">Aprovação no repositório oficial do WordPress</h2>



<p>A presença do Notifish no repositório oficial do WordPress é um ponto relevante, pois indica que o plugin:</p>



<ul class="wp-block-list">
<li>Segue as diretrizes de segurança do WordPress</li>



<li>Utiliza boas práticas de desenvolvimento</li>



<li>Passou por revisão manual da equipe do WordPress</li>



<li>Pode ser instalado e atualizado diretamente pelo painel administrativo</li>
</ul>



<p>Isso reduz riscos técnicos e aumenta a confiabilidade do projeto para uso em produção.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-impacto-em-seo-e-engajamento">Impacto em SEO e engajamento</h2>



<p>Embora o WhatsApp não seja um fator direto de ranqueamento, a automação de distribuição impacta positivamente métricas importantes para SEO, como:</p>



<ul class="wp-block-list">
<li>Aumento de tráfego recorrente</li>



<li>Maior taxa de retorno ao site</li>



<li>Crescimento de engajamento com o conteúdo</li>



<li>Ampliação do alcance orgânico das publicações</li>
</ul>



<p>Em projetos editoriais, isso significa <strong>conteúdo sendo consumido mais rápido e com mais frequência</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-onde-instalar-o-plugin-notifish">Onde instalar o plugin Notifish</h2>



<p>O plugin está disponível no repositório oficial do WordPress e pode ser instalado diretamente pelo painel administrativo ou acessado pelo link abaixo:</p>



<p><a href="https://wordpress.org/plugins/notifish">https://wordpress.org/plugins/notifish</a></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-consideracoes-finais">Considerações finais</h2>



<p>O Notifish não é apenas um plugin de envio de mensagens, mas uma <strong>ferramenta de integração entre conteúdo e distribuição</strong>, pensada para quem publica com frequência e precisa de escala sem perder controle.</p>



<p>Para sites WordPress que utilizam o WhatsApp como canal estratégico, a automação deixa de ser um diferencial e passa a ser uma necessidade operacional.</p>
<p>The post <a href="https://leonardonascimento.dev/blog/automacao-de-whatsapp-para-wordpress-uma-solucao-escalavel-para-empresas-e-portais/">Automação de WhatsApp para WordPress: uma solução escalável para empresas e portais</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/automacao-de-whatsapp-para-wordpress-uma-solucao-escalavel-para-empresas-e-portais/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PHP além do CRUD: como escrever código que não vira problema em produção</title>
		<link>https://leonardonascimento.dev/blog/php-alem-do-crud-como-escrever-codigo-que-nao-vira-problema-em-producao/</link>
					<comments>https://leonardonascimento.dev/blog/php-alem-do-crud-como-escrever-codigo-que-nao-vira-problema-em-producao/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Mon, 26 Jan 2026 11:05:00 +0000</pubDate>
				<category><![CDATA[Arquitetura]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[arquitetura de software]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[boas práticas]]></category>
		<category><![CDATA[código limpo]]></category>
		<category><![CDATA[dto]]></category>
		<category><![CDATA[engenharia de software]]></category>
		<category><![CDATA[php avançado]]></category>
		<category><![CDATA[services layer]]></category>
		<category><![CDATA[sistemas em produção]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2348</guid>

					<description><![CDATA[<p>A maioria dos desenvolvedores PHP sabe fazer CRUD.Isso não te torna pleno. Muito menos sênior. O que diferencia um dev mais experiente não é o que ele sabe fazer, mas o que ele evita fazer. Vou te ensinar aqui um padrão prático, usado em projetos reais, que resolve três problemas clássicos: public function store(Request $request){if [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/php-alem-do-crud-como-escrever-codigo-que-nao-vira-problema-em-producao/">PHP além do CRUD: como escrever código que não vira problema em produção</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>A maioria dos desenvolvedores PHP sabe fazer CRUD.<br>Isso não te torna pleno. Muito menos sênior.</p>



<p>O que diferencia um dev mais experiente não é <em>o que ele sabe fazer</em>, mas <strong>o que ele evita fazer</strong>.</p>



<p>Vou te ensinar aqui <strong>um padrão prático</strong>, usado em projetos reais, que resolve três problemas clássicos:</p>



<ul class="wp-block-list">
<li>Controllers inchados</li>



<li>Regras de negócio espalhadas</li>



<li>Código impossível de testar ou evoluir</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>public function store(Request $request)<br>{<br>if (!$request-&gt;email) {<br>return response()-&gt;json([&#8216;error&#8217; =&gt; &#8216;Email obrigatório&#8217;], 422);<br>}</p>



<pre class="wp-block-code"><code>$user = User::create(&#91;
    'name' =&gt; $request-&gt;name,
    'email' =&gt; $request-&gt;email,
]);

Mail::to($user-&gt;email)-&gt;send(new WelcomeMail($user));

Log::info('Usuário criado', &#91;'id' =&gt; $user-&gt;id]);

return response()-&gt;json($user);</code></pre>



<p>}</p>



<p>Funciona? Funciona.</p>



<p>É bom? Não.</p>



<p>Por quê?</p>



<ul class="wp-block-list">
<li>Controller decide regra de negócio</li>



<li>Controller cria usuário</li>



<li>Controller dispara e-mail</li>



<li>Controller registra log</li>
</ul>



<p>Isso <strong>acopla tudo</strong>.</p>



<h2 class="wp-block-heading" id="h-pensamento-pleno-senior-separar-responsabilidade">Pensamento pleno/sênior: separar responsabilidade</h2>



<p>Controller <strong>não decide regra</strong>.<br>Controller <strong>orquestra</strong>.</p>



<p>Vamos refatorar com um <strong>Service + DTO</strong>, padrão simples e poderoso.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-criando-um-dto-data-transfer-object">Criando um DTO (Data Transfer Object)</h2>



<p>Isso evita Request sendo usado como regra de negócio.</p>



<pre class="wp-block-code"><code>final class CreateUserDTO
{
    public function __construct(
        public readonly string $name,
        public readonly string $email,
    ) {}
}
</code></pre>



<p>Simples, explícito e tipado.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-criando-o-service-onde-a-regra-mora"> Criando o Service (onde a regra mora)</h2>



<pre class="wp-block-code"><code>final class CreateUserService
{
    public function execute(CreateUserDTO $dto): User
    {
        if (!filter_var($dto-&gt;email, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException('Email inválido');
        }

        $user = User::create(&#91;
            'name' =&gt; $dto-&gt;name,
            'email' =&gt; $dto-&gt;email,
        ]);

        Mail::to($user-&gt;email)-&gt;send(new WelcomeMail($user));

        Log::info('Usuário criado', &#91;'id' =&gt; $user-&gt;id]);

        return $user;
    }
}
</code></pre>



<p>Agora sim:</p>



<ul class="wp-block-list">
<li>Regra centralizada</li>



<li>Código reutilizável</li>



<li>Fácil de testar</li>



<li>Fácil de evoluir</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-controller-limpo-como-deveria-ser"> Controller limpo (como deveria ser)</h2>



<pre class="wp-block-code"><code>public function store(Request $request, CreateUserService $service)
{
    $dto = new CreateUserDTO(
        name: $request-&gt;name,
        email: $request-&gt;email
    );

    $user = $service-&gt;execute($dto);

    return response()-&gt;json($user);
}
</code></pre>



<p>O controller:</p>



<ul class="wp-block-list">
<li>Recebe request</li>



<li>Constrói DTO</li>



<li>Chama serviço</li>



<li>Retorna resposta</li>
</ul>



<p>Nada além disso.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">O ganho real (que júnior não enxerga)</h2>



<h3 class="wp-block-heading" id="h-testabilidade">Testabilidade</h3>



<p>Agora você testa a regra <strong>sem framework</strong>:</p>



<pre class="wp-block-code"><code>public function test_user_creation()
{
    $service = new CreateUserService();

    $dto = new CreateUserDTO(
        name: 'Leo',
        email: 'leo@email.com'
    );

    $user = $service-&gt;execute($dto);

    $this-&gt;assertEquals('Leo', $user-&gt;name);
}
</code></pre>



<p>Sem Request.<br>Sem Controller.<br>Sem gambiarra.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading" id="h-evolucao-sem-dor"> Evolução sem dor</h3>



<p>Amanhã você precisa:</p>



<ul class="wp-block-list">
<li>Enviar evento para fila</li>



<li>Criar usuário em sistema externo</li>



<li>Validar regra nova</li>
</ul>



<p>Você altera <strong>um lugar só</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Mentalidade sênior (isso vale ouro)</h2>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8221; Código que funciona não é código bom.mCódigo bom é o que aguenta mudança.&#8221; </p>
</blockquote>



<p>Pleno/sênior pensa assim:</p>



<ul class="wp-block-list">
<li>Onde essa regra deve morar?</li>



<li>O que vai mudar daqui 6 meses?</li>



<li>Quem vai dar manutenção nisso?</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Erros clássicos que isso evita</h2>



<ul class="wp-block-list">
<li>Fat models</li>



<li>Controllers gigantes</li>



<li>Services que viram controllers</li>



<li>Regra duplicada</li>



<li>Código impossível de refatorar</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Esse tipo de abordagem <strong>não aparece em tutorial de YouTube</strong>, mas é exatamente o que mantém sistemas vivos em produção.</p>
<p>The post <a href="https://leonardonascimento.dev/blog/php-alem-do-crud-como-escrever-codigo-que-nao-vira-problema-em-producao/">PHP além do CRUD: como escrever código que não vira problema em produção</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/php-alem-do-crud-como-escrever-codigo-que-nao-vira-problema-em-producao/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>O que é Lighthouse e como usar para melhorar seu site</title>
		<link>https://leonardonascimento.dev/blog/o-que-e-lighthouse-e-como-usar-para-melhorar-seu-site/</link>
					<comments>https://leonardonascimento.dev/blog/o-que-e-lighthouse-e-como-usar-para-melhorar-seu-site/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Wed, 21 Jan 2026 23:20:00 +0000</pubDate>
				<category><![CDATA[API]]></category>
		<category><![CDATA[Arquitetura]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[Frontend]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Produção]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Seo & Marketing]]></category>
		<category><![CDATA[core web vitals]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[lighthouse]]></category>
		<category><![CDATA[otimização de sites]]></category>
		<category><![CDATA[performance web]]></category>
		<category><![CDATA[seo técnico]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2318</guid>

					<description><![CDATA[<p>Performance, acessibilidade e boas práticas deixaram de ser “detalhes técnicos” e passaram a impactar diretamente tráfego, conversão e experiência do usuário. Para ajudar a medir esses pontos de forma objetiva, o Google criou o Google Lighthouse. Mais do que uma nota colorida, o Lighthouse é uma ferramenta de diagnóstico. Saber usá-lo corretamente evita decisões erradas [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/o-que-e-lighthouse-e-como-usar-para-melhorar-seu-site/">O que é Lighthouse e como usar para melhorar seu site</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Performance, acessibilidade e boas práticas deixaram de ser “detalhes técnicos” e passaram a impactar diretamente tráfego, conversão e experiência do usuário. Para ajudar a medir esses pontos de forma objetiva, o Google criou o <strong>Google Lighthouse</strong>.</p>



<p>Mais do que uma nota colorida, o Lighthouse é uma ferramenta de diagnóstico. Saber usá-lo corretamente evita decisões erradas e otimizações inúteis.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-o-que-e-o-lighthouse">O que é o Lighthouse</h2>



<p>O Lighthouse é uma ferramenta automatizada de auditoria de páginas web. Ele analisa uma URL e gera um relatório com métricas e recomendações em cinco áreas principais:</p>



<ul class="wp-block-list">
<li><strong>Performance</strong></li>



<li><strong>Acessibilidade</strong></li>



<li><strong>Boas práticas</strong></li>



<li><strong>SEO</strong></li>



<li><strong>Progressive Web App (PWA)</strong></li>
</ul>



<p>O objetivo não é apenas pontuar o site, mas mostrar <strong>onde estão os gargalos reais</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-onde-o-lighthouse-esta-disponivel">Onde o Lighthouse está disponível</h2>



<p>Você pode usar o Lighthouse de várias formas:</p>



<ul class="wp-block-list">
<li><strong>Chrome DevTools</strong> (nativo do navegador)</li>



<li><strong>Linha de comando (CLI)</strong></li>



<li><strong>CI/CD</strong> (auditorias automatizadas)</li>



<li><strong>Ferramentas online baseadas no Lighthouse</strong></li>
</ul>



<p>Para a maioria dos casos, o DevTools já resolve bem.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-como-rodar-o-lighthouse-pelo-chrome">Como rodar o Lighthouse pelo Chrome</h2>



<ol class="wp-block-list">
<li>Abra o site no Chrome</li>



<li>Pressione <code>F12</code> ou <code>Ctrl + Shift + I</code></li>



<li>Vá até a aba <strong>Lighthouse</strong></li>



<li>Escolha o tipo de dispositivo (Mobile ou Desktop)</li>



<li>Clique em <strong>Generate report</strong></li>
</ol>



<p>Em poucos segundos, o relatório é gerado.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-as-metricas-mais-importantes-e-o-que-elas-significam">As métricas mais importantes (e o que elas significam)</h2>



<h3 class="wp-block-heading" id="h-performance">Performance</h3>



<p>Avalia tempo de carregamento e resposta da página. Algumas métricas-chave:</p>



<ul class="wp-block-list">
<li><strong>LCP (Largest Contentful Paint)</strong><br>Mede quando o maior elemento visível aparece. Impacta diretamente a percepção de velocidade.</li>



<li><strong>INP (Interaction to Next Paint)</strong><br>Avalia a resposta do site às interações do usuário.</li>



<li><strong>CLS (Cumulative Layout Shift)</strong><br>Mede instabilidade visual (elementos “pulando” na tela).</li>
</ul>



<p>Essas métricas fazem parte do <strong>Core Web Vitals</strong>, usados pelo Google como sinal de experiência.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading" id="h-acessibilidade">Acessibilidade</h3>



<p>Verifica se o site pode ser usado por pessoas com limitações visuais, motoras ou cognitivas. Exemplos de checagem:</p>



<ul class="wp-block-list">
<li>contraste de cores</li>



<li>textos alternativos em imagens</li>



<li>labels em formulários</li>



<li>estrutura semântica do HTML</li>
</ul>



<p>Mesmo que não seja um requisito legal em todos os casos, acessibilidade melhora usabilidade para todos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading" id="h-boas-praticas">Boas práticas</h3>



<p>Aqui entram problemas mais técnicos, como:</p>



<ul class="wp-block-list">
<li>uso de APIs inseguras</li>



<li>imagens com proporções erradas</li>



<li>erros de console</li>



<li>bibliotecas desatualizadas</li>
</ul>



<p>É uma área que ajuda a manter o site saudável ao longo do tempo.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading" id="h-seo">SEO</h3>



<p>O Lighthouse não substitui ferramentas avançadas de SEO, mas valida o básico:</p>



<ul class="wp-block-list">
<li>meta tags essenciais</li>



<li>indexabilidade</li>



<li>uso correto de links</li>



<li>estrutura mínima de conteúdo</li>
</ul>



<p>Se o site falha aqui, dificilmente terá bom desempenho orgânico.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-o-erro-mais-comum-otimizar-so-para-a-nota">O erro mais comum: otimizar só para a nota</h2>



<p>Muita gente usa o Lighthouse como competição de pontuação. Isso é um erro.</p>



<p>Um site pode ter nota 100 e ainda assim:</p>



<ul class="wp-block-list">
<li>carregar dados desnecessários</li>



<li>ter arquitetura ruim</li>



<li>sofrer em cenários reais de tráfego</li>
</ul>



<p>O relatório deve ser lido como <strong>ferramenta de diagnóstico</strong>, não como objetivo final.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-mobile-vs-desktop-sempre-priorize-mobile">Mobile vs Desktop: sempre priorize mobile</h2>



<p>O Google avalia sites com <strong>mobile-first indexing</strong>. Isso significa que:</p>



<ul class="wp-block-list">
<li>o relatório mobile é mais relevante</li>



<li>problemas no mobile impactam mais SEO</li>



<li>otimizações devem começar pelo mobile</li>
</ul>



<p>Um site rápido no desktop e lento no celular está em desvantagem.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-lighthouse-em-producao-e-ci-cd">Lighthouse em produção e CI/CD</h2>



<p>Em projetos mais maduros, o Lighthouse pode rodar automaticamente:</p>



<ul class="wp-block-list">
<li>antes de deploy</li>



<li>após mudanças críticas</li>



<li>em pipelines de CI/CD</li>
</ul>



<p>Isso ajuda a evitar regressões de performance e garante que melhorias não sejam perdidas com o tempo.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-limitacoes-do-lighthouse">Limitações do Lighthouse</h2>



<p>Apesar de poderoso, o Lighthouse tem limites:</p>



<ul class="wp-block-list">
<li>roda em ambiente controlado</li>



<li>não reflete todos os cenários reais</li>



<li>não substitui métricas de usuários reais (RUM)</li>
</ul>



<p>O ideal é combiná-lo com dados reais de uso, como relatórios de experiência de campo.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-quando-o-lighthouse-faz-mais-diferenca">Quando o Lighthouse faz mais diferença</h2>



<p>Ele é especialmente útil para:</p>



<ul class="wp-block-list">
<li>identificar gargalos iniciais de performance</li>



<li>validar mudanças estruturais</li>



<li>educar times sobre impacto técnico</li>



<li>criar baseline de qualidade</li>
</ul>



<p>Não é uma bala de prata, mas é um excelente ponto de partida.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>O Lighthouse não serve para “tirar nota alta”, mas para <strong>entender como o site se comporta</strong> do ponto de vista do usuário. Quando usado com critério, ele direciona otimizações que realmente fazem diferença.</p>



<p>Ignorá-lo pode custar performance, experiência e visibilidade. Usá-lo mal pode custar tempo. O valor está em interpretar os dados, não apenas executá-los.</p>
<p>The post <a href="https://leonardonascimento.dev/blog/o-que-e-lighthouse-e-como-usar-para-melhorar-seu-site/">O que é Lighthouse e como usar para melhorar seu site</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/o-que-e-lighthouse-e-como-usar-para-melhorar-seu-site/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Laravel: Jobs, filas e processamento assíncrono: quando usar e quando evitar</title>
		<link>https://leonardonascimento.dev/blog/laravel-jobs-filas-e-processamento-assincrono-quando-usar-e-quando-evitar/</link>
					<comments>https://leonardonascimento.dev/blog/laravel-jobs-filas-e-processamento-assincrono-quando-usar-e-quando-evitar/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Thu, 08 Jan 2026 14:22:46 +0000</pubDate>
				<category><![CDATA[Arquitetura]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[filas]]></category>
		<category><![CDATA[jobs]]></category>
		<category><![CDATA[mensageria]]></category>
		<category><![CDATA[processamento assíncrono]]></category>
		<category><![CDATA[produção]]></category>
		<category><![CDATA[redis]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2271</guid>

					<description><![CDATA[<p>Fila resolve dor real: tirar do request o que não precisa estar ali. O problema é que muita gente usa fila como “remédio genérico” e acaba criando um sistema mais frágil, mais difícil de depurar e com risco de duplicidade. Jobs e processamento assíncrono são excelentes quando usados com critério. Quando usados por impulso, viram [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/laravel-jobs-filas-e-processamento-assincrono-quando-usar-e-quando-evitar/">Laravel: Jobs, filas e processamento assíncrono: quando usar e quando evitar</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Fila resolve dor real: tirar do request o que não precisa estar ali. O problema é que muita gente usa fila como “remédio genérico” e acaba criando um sistema mais frágil, mais difícil de depurar e com risco de duplicidade.</p>



<p><a href="https://leonardonascimento.dev/categoria/laravel/" type="category" id="44">Jobs e processamento</a> assíncrono são excelentes quando usados com critério. Quando usados por impulso, viram fonte de incidentes.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">O que fila realmente te dá (e o que ela não dá)</h2>



<p>Fila te dá principalmente três coisas: desacoplamento do tempo de resposta, capacidade de absorver picos e reprocessamento controlado. Ela não te dá garantia de que algo vai rodar uma vez só, nem te livra de tratar falhas externas. Na verdade, ela te obriga a tratar isso.</p>



<p>Se você joga um processo para a fila sem pensar em idempotência, retries e observabilidade, você só mudou o problema de lugar.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Quando usar jobs e filas</h2>



<h3 class="wp-block-heading">1) Tudo que não precisa bloquear o usuário</h3>



<p>Se o usuário não precisa do resultado imediato, isso já é um sinal forte de fila.</p>



<p>Exemplos comuns:</p>



<ul class="wp-block-list">
<li>envio de e-mail e notificações</li>



<li>geração de relatórios</li>



<li>criação de thumbnails / processamento de mídia</li>



<li>sincronização com sistemas externos</li>



<li>webhooks de saída (enviar eventos para terceiros)</li>
</ul>



<p>A regra prática: se o usuário já pode seguir o fluxo sem esperar, tire do request.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2) Integrações externas e chamadas instáveis</h3>



<p><a href="https://leonardonascimento.dev/tag/api/" type="post_tag" id="210">API de terceiros falha</a>, oscila, responde lento. Fila é ótima para isso porque permite retries e isolamento.</p>



<p>Exemplos:</p>



<ul class="wp-block-list">
<li>gateway de pagamento</li>



<li>WhatsApp / SMS</li>



<li>ERP e sistemas legados</li>



<li>qualquer HTTP externo</li>
</ul>



<p>Mas aqui entra o ponto crítico: fila não é desculpa para “tentar infinitamente”. Você precisa controlar tentativas e saber quando desistir.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3) Processamentos pesados e previsíveis</h3>



<p><a href="https://leonardonascimento.dev/blog/boas-praticas-para-estruturar-projetos-em-laravel-de-medio-e-grande-porte/" type="post" id="2262">Tudo que consome</a> CPU, memória ou I/O e pode gerar timeout em request tende a ser melhor em job.</p>



<p>Exemplos:</p>



<ul class="wp-block-list">
<li>exportar CSV grande</li>



<li>processar lote de dados</li>



<li>recalcular agregações</li>



<li>rodar rotinas de normalização/validação em massa</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">4) Fan-out (um evento dispara várias ações)</h3>



<p>Quando algo acontece e você precisa executar várias tarefas em sequência ou em paralelo, jobs ajudam a manter o sistema organizado.</p>



<p>Exemplo: “pedido pago” dispara:</p>



<ul class="wp-block-list">
<li>enviar confirmação</li>



<li>baixar estoque</li>



<li>emitir nota</li>



<li>notificar financeiro</li>



<li>gerar registro no CRM</li>
</ul>



<p>Se você faz tudo no request, vira um fluxo pesado e frágil. Com jobs, você separa responsabilidades.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">5) Absorver picos sem derrubar o sistema</h3>



<p>Fila é uma forma de “buffer”. Em vez de o sistema tentar processar tudo na hora e morrer, você coloca em fila e processa no ritmo que aguenta.</p>



<p>Isso é útil quando:</p>



<ul class="wp-block-list">
<li>picos são comuns</li>



<li>demanda varia muito</li>



<li>você precisa garantir estabilidade</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Quando evitar jobs e filas</h2>



<h3 class="wp-block-heading">1) Quando você precisa de resposta imediata e consistente</h3>



<p>Se o usuário precisa saber na hora se deu certo, jogar em fila pode piorar a experiência.</p>



<p>Exemplos:</p>



<ul class="wp-block-list">
<li>login</li>



<li>criar pagamento e retornar confirmação</li>



<li>reservar algo que não pode duplicar</li>



<li>operações transacionais críticas</li>
</ul>



<p>Você até pode usar job para efeitos colaterais, mas a decisão central precisa ser síncrona.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2) Quando a operação é simples e rápida</h3>



<p>Às vezes a operação leva 20ms e você coloca na fila “por padrão”. Isso adiciona:</p>



<ul class="wp-block-list">
<li>complexidade</li>



<li>delay</li>



<li>necessidade de monitoramento</li>



<li>risco de falha assíncrona</li>
</ul>



<p>Fila não pode ser usada como padrão para tudo. Senão você cria um sistema cheio de jobs pequenos e difíceis de rastrear.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3) Quando você não tem observabilidade</h3>



<p>Fila sem visibilidade vira caixa-preta.</p>



<p>Se você não tem:</p>



<ul class="wp-block-list">
<li>logs por job</li>



<li>métricas de falha</li>



<li>alertas de backlog</li>



<li>dead-letter ou estratégia de falha</li>
</ul>



<p>você vai descobrir problemas tarde demais. Nesse cenário, manter síncrono pode ser mais seguro até organizar a casa.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">4) Quando você não consegue garantir idempotência</h3>



<p>Jobs podem rodar duas vezes. Isso é normal: retry, timeouts, quedas de worker, reentregas. Se o job não é idempotente, você corre risco de:</p>



<ul class="wp-block-list">
<li>cobrança duplicada</li>



<li>disparo duplicado</li>



<li>registro duplicado</li>



<li>integração duplicada</li>
</ul>



<p>Se não dá para tornar idempotente, trate o caso com mais cuidado. Às vezes o certo é manter a operação central síncrona e colocar apenas efeitos colaterais na fila.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">O ponto que derruba sistemas: duplicidade</h2>



<p>Em produção, o seu job vai rodar duas vezes em algum momento. Não é “se”, é “quando”. Por isso, projetos maduros tratam idempotência como requisito.</p>



<p>Algumas abordagens comuns:</p>



<ul class="wp-block-list">
<li>chave idempotente por evento (event_id / request_id)</li>



<li>lock distribuído (Redis)</li>



<li>uniqueness controlada (Laravel unique jobs quando aplicável)</li>



<li>constraints no banco (único onde fizer sentido)</li>
</ul>



<p>Não é uma bala de prata, mas é obrigatório ter uma estratégia.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Filas também precisam de limites</h2>



<p>Jobs não podem tentar para sempre. Você precisa definir:</p>



<ul class="wp-block-list">
<li>número de tentativas</li>



<li>backoff entre tentativas</li>



<li>timeout</li>



<li>comportamento ao falhar (alerta, dead letter, reprocessamento manual)</li>
</ul>



<p>E precisa aceitar que algumas coisas falham. O sistema não pode entrar em loop eterno tentando recuperar erro externo.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Sinais de que você deve ir para fila</h2>



<p>Se você está em dúvida, aqui vão sinais bem práticos:</p>



<ul class="wp-block-list">
<li>requests começando a estourar timeout</li>



<li>picos derrubando a API</li>



<li>integrações externas travando fluxos principais</li>



<li>usuários esperando por coisas que não precisam esperar</li>



<li>o mesmo fluxo acumulando responsabilidades demais</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Jobs e filas são uma das melhores ferramentas para dar escala e estabilidade em sistemas Laravel, mas elas exigem maturidade. Quando bem usadas, melhoram performance, isolam falhas e deixam o sistema mais previsível. Quando usadas sem critério, viram um sistema difícil de operar, cheio de jobs duplicados e incidentes intermitentes.</p>



<p>Fila não é atalho. É arquitetura.</p>
<p>The post <a href="https://leonardonascimento.dev/blog/laravel-jobs-filas-e-processamento-assincrono-quando-usar-e-quando-evitar/">Laravel: Jobs, filas e processamento assíncrono: quando usar e quando evitar</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/laravel-jobs-filas-e-processamento-assincrono-quando-usar-e-quando-evitar/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Boas práticas para estruturar projetos em Laravel de médio e grande porte</title>
		<link>https://leonardonascimento.dev/blog/boas-praticas-para-estruturar-projetos-em-laravel-de-medio-e-grande-porte/</link>
					<comments>https://leonardonascimento.dev/blog/boas-praticas-para-estruturar-projetos-em-laravel-de-medio-e-grande-porte/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Wed, 07 Jan 2026 14:12:16 +0000</pubDate>
				<category><![CDATA[Arquitetura]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Produção]]></category>
		<category><![CDATA[arquitetura]]></category>
		<category><![CDATA[boas práticas]]></category>
		<category><![CDATA[código sustentável]]></category>
		<category><![CDATA[escalabilidade]]></category>
		<category><![CDATA[estrutura de projeto]]></category>
		<category><![CDATA[laravel]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2262</guid>

					<description><![CDATA[<p>Quando o projeto Laravel é pequeno, quase qualquer organização funciona. Você cria controllers, models, requests, alguns services, resolve tudo no “app/” e segue. O problema começa quando o sistema cresce: mais módulos, mais regras, integrações, filas, diferentes times mexendo no mesmo lugar… e, de repente, o que era simples vira uma base difícil de evoluir. [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/boas-praticas-para-estruturar-projetos-em-laravel-de-medio-e-grande-porte/">Boas práticas para estruturar projetos em Laravel de médio e grande porte</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Quando o projeto <a href="https://leonardonascimento.dev/categoria/laravel/" type="category" id="44">Laravel </a>é pequeno, quase qualquer organização funciona. Você cria controllers, models, requests, alguns services, resolve tudo no “app/” e segue. O problema começa quando o sistema cresce: mais módulos, mais regras, integrações, filas, diferentes times mexendo no mesmo lugar… e, de repente, o que era simples vira uma base difícil de evoluir.</p>



<p>Estruturar um projeto Laravel bem não é sobre “<a href="https://leonardonascimento.dev/categoria/arquitetura/" type="category" id="217">inventar arquitetura</a>”. É sobre reduzir atrito: facilitar manutenção, evitar acoplamento desnecessário e deixar o código previsível para quem chega depois.</p>



<p>A seguir estão práticas que funcionam bem em projetos médios e grandes, especialmente quando já existe operação de produção, roadmap e mudanças frequentes.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Comece pela regra: controller não é lugar de lógica</h2>



<p>Controller deveria orquestrar: receber request, validar, chamar a camada certa e responder. Quando regra de negócio fica no controller, você cria um ponto de acoplamento difícil de testar e difícil de reutilizar. Em projeto grande isso vira padrão ruim rapidamente, porque todo mundo copia o que já existe.</p>



<p>O que funciona melhor é mover lógica para classes dedicadas (services/use cases/actions), e deixar o controller como uma “casca” fina. Você ganha clareza, reaproveitamento e testes mais simples.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Estruture por domínio (feature) quando o sistema crescer</h2>



<p>A estrutura padrão do Laravel (Controllers, Models, Jobs, etc.) é ótima até um certo ponto. Em sistemas grandes, ela tende a espalhar a mesma funcionalidade por várias pastas e o dev precisa “caçar” arquivos para entender um fluxo.</p>



<p>Uma abordagem que escala melhor é organizar por <strong>domínio/feature</strong>. Exemplo: tudo relacionado a “Billing” fica próximo (requests, actions, policies, resources, etc.). Isso reduz a fricção para manter e evoluir partes específicas do sistema.</p>



<p>Você não precisa mudar tudo de uma vez. Dá para começar com um ou dois domínios e ir migrando aos poucos, sem reescrever o projeto inteiro.</p>



<h3 class="wp-block-heading">Estrutura tradicional do Laravel (por tipo)</h3>



<pre class="wp-block-preformatted">app/<br>├── Http/<br>│   ├── Controllers/<br>│   ├── Requests/<br>│   └── Resources/<br>├── Models/<br>├── Jobs/<br>├── Policies/<br>├── Services/</pre>



<p>Problema em projeto grande:<br>para entender <strong>Billing</strong>, você precisa abrir 6 pastas diferentes.</p>



<p>Estrutura por domínio / feature</p>



<p>app/<br>└── Domains/<br>└── Billing/<br>├── Http/<br>│ ├── Controllers/<br>│ ├── Requests/<br>│ └── Resources/<br>├── Actions/<br>├── Jobs/<br>├── Policies/<br>├── Models/<br>└── Services/</p>



<p>Ou até mais simples:</p>



<pre class="wp-block-preformatted">app/<br>└── Billing/<br>    ├── BillingController.php<br>    ├── CreateInvoice.php<br>    ├── Invoice.php<br>    ├── InvoicePolicy.php<br>    ├── SendInvoiceJob.php<br>    └── InvoiceResource.php</pre>



<p>O Laravel não se importa com a pasta, desde que o namespace esteja correto.</p>



<h2 class="wp-block-heading">Por que isso escala melhor?</h2>



<p>Porque quando alguém entra no projeto e precisa mexer em Billing:</p>



<ul class="wp-block-list">
<li>não precisa caçar arquivos espalhados</li>



<li>não quebra coisas de outros domínios</li>



<li>entende o fluxo mais rápido</li>



<li>reduz medo de alterar código</li>
</ul>



<p>Em projeto grande, isso faz <strong>muita diferença</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Requests e validações como primeiro filtro</h2>



<p>Em projeto grande, dado ruim entrando vira bug caro. Centralizar validação em <strong>Form Requests</strong> mantém o controller limpo e torna regras de entrada explícitas.</p>



<p>Além disso, vale padronizar:</p>



<ul class="wp-block-list">
<li>mensagens de erro;</li>



<li>formatos de resposta (principalmente APIs);</li>



<li>validações compartilhadas (traits, rules customizadas).</li>
</ul>



<p>Quando a validação é consistente, o sistema vira mais previsível e o time para de reinventar a roda a cada endpoint.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Padronize respostas de API desde cedo</h2>



<p>Quando cada <a href="https://leonardonascimento.dev/tag/api/" type="post_tag" id="210">endpoint </a>responde de um jeito, cada client precisa de lógica diferente, e isso vira dívida técnica distribuída. Para projetos médios e grandes, uma camada consistente de resposta é obrigatória: Resources, transformers, ou uma padronização interna.</p>



<p>O ponto aqui não é “estética”. É operação. Quando algo quebra, você quer logs previsíveis, payload previsível, erros previsíveis. Isso reduz tempo de diagnóstico.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Regras de negócio: não misture persistência com decisão</h2>



<p>Um erro comum em Laravel é “decidir” coisas dentro de models e ao mesmo tempo persistir em todo lugar, sem fronteira clara. Em sistemas maiores, o ideal é separar:</p>



<ul class="wp-block-list">
<li><strong>Decisão / regra</strong> (o que pode ou não pode)</li>



<li><strong>Persistência</strong> (salvar, consultar)</li>



<li><strong>Orquestração</strong> (fluxo do caso de uso)</li>
</ul>



<p>Isso permite evoluir regra sem quebrar camada de persistência, e vice-versa. E facilita testar o que realmente importa: a regra.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Jobs, filas e idempotência não são detalhe</h2>



<p>Em projeto grande, você inevitavelmente vai para filas: e-mails, notificações, integrações, processamento pesado. O que quebra sistemas grandes não é “usar fila”. É usar fila sem cuidado com:</p>



<ul class="wp-block-list">
<li>idempotência (job rodar duas vezes sem duplicar efeito);</li>



<li>retries (quando deve tentar de novo e quando deve falhar);</li>



<li>timeouts;</li>



<li>dead letter / estratégia para falhas recorrentes;</li>



<li>logs por job.</li>
</ul>



<p>Se o seu projeto depende de integração externa, trate isso como cenário normal: o externo vai falhar. A fila é o lugar certo para absorver isso, desde que bem desenhado.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Serviços externos: isole e trate como dependência instável</h2>



<p>Integrações externas deveriam estar em classes próprias (clients/adapters), com:</p>



<ul class="wp-block-list">
<li>timeout explícito;</li>



<li>tratamento de erro consistente;</li>



<li>retry controlado quando fizer sentido;</li>



<li>logs contextualizados.</li>
</ul>



<p>Evite espalhar <code>Http::post()</code> por todo lugar. Em projeto grande isso vira caos, porque não existe ponto único para ajustar comportamento (ex: mudar header, adicionar auth, alterar timeout).</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Migrations, seeds e dados de referência bem cuidados</h2>



<p>Projeto grande normalmente tem muita migration. E migration desorganizada vira armadilha: ambientes quebram, dev novo não sobe projeto, staging fica inconsistente.</p>



<p>Boas práticas que ajudam:</p>



<ul class="wp-block-list">
<li>migrations com nomes claros;</li>



<li>dados de referência (enums/tabelas fixas) com seeders idempotentes;</li>



<li>evitar “seed que depende de estado manual”;</li>



<li>sempre testar “do zero” em ambiente limpo.</li>
</ul>



<p>Isso evita que o setup do projeto vire uma gincana.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Configuração: tudo em config e .env, nada hardcoded</h2>



<p>Quando cresce, o sistema precisa rodar em múltiplos ambientes e, muitas vezes, múltiplos clientes. Configuração hardcoded vira problema de deploy e vira risco de segurança.</p>



<p>Padronize:</p>



<ul class="wp-block-list">
<li><code>config/*.php</code> como fonte de configuração;</li>



<li><code>.env</code> apenas para valores variáveis;</li>



<li>nunca commitar senhas e keys;</li>



<li>e preferencialmente separar integrações por “config + service container”.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Observabilidade: logs estruturados desde o começo</h2>



<p>Em projetos grandes, o custo de “descobrir o que aconteceu” é alto. Sem logs bons você perde tempo, perde confiança e perde previsibilidade operacional.</p>



<p>O que vale padronizar:</p>



<ul class="wp-block-list">
<li>logs com contexto (tenant, user_id, request_id, correlation_id);</li>



<li>níveis corretos (info, warning, error);</li>



<li>logs de integrações e jobs;</li>



<li>e um formato consistente (para facilitar busca).</li>
</ul>



<p>Isso é o que transforma incidentes em diagnóstico rápido.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Testes: foque no que dá retorno real</h2>



<p>Não dá para testar tudo em projeto grande, e tentar fazê-lo costuma falhar. O que dá mais retorno é:</p>



<ul class="wp-block-list">
<li>testes de regras de negócio (unit/integration);</li>



<li>testes de fluxos críticos;</li>



<li>testes de contratos de API;</li>



<li>e testes de integração com serviços externos (com mocks ou ambientes controlados).</li>
</ul>



<p>Teste não é para “subir porcentagem”. É para reduzir risco onde mais dói.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Conclusão</h2>



<p>Projetos Laravel grandes não quebram porque Laravel é limitado. Eles quebram porque a base cresce sem estrutura, sem padrões e sem fronteiras claras entre responsabilidades.</p>



<p>Se você mantiver controllers finos, separar domínio/feature, isolar integrações, tratar filas com seriedade e padronizar validação/retorno/log, o projeto continua evoluindo sem virar um monstro. E o melhor: o time consegue manter velocidade sem sacrificar estabilidade.</p>
<p>The post <a href="https://leonardonascimento.dev/blog/boas-praticas-para-estruturar-projetos-em-laravel-de-medio-e-grande-porte/">Boas práticas para estruturar projetos em Laravel de médio e grande porte</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/boas-praticas-para-estruturar-projetos-em-laravel-de-medio-e-grande-porte/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Erros comuns em APIs que causam problemas em produção</title>
		<link>https://leonardonascimento.dev/blog/erros-comuns-em-apis-que-causam-problemas-em-producao/</link>
					<comments>https://leonardonascimento.dev/blog/erros-comuns-em-apis-que-causam-problemas-em-producao/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Fri, 02 Jan 2026 03:39:38 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Segurança]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[http request]]></category>
		<category><![CDATA[postman]]></category>
		<category><![CDATA[programação]]></category>
		<category><![CDATA[segurança api]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2248</guid>

					<description><![CDATA[<p>APIs geralmente funcionam muito bem no começo. Passam nos testes, respondem rápido em ambiente local e entregam o que foi pedido. O problema é que produção cobra coisas que quase nunca são consideradas no início. A maioria dos problemas que aparecem em APIs não vem da linguagem, mas de decisões técnicas erradas ou simplesmente ignoradas. [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/erros-comuns-em-apis-que-causam-problemas-em-producao/">Erros comuns em APIs que causam problemas em produção</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>APIs geralmente funcionam muito bem no começo. Passam nos testes, respondem rápido em ambiente local e entregam o que foi pedido. O problema é que produção cobra coisas que quase nunca são consideradas no início.</p>



<p>A maioria dos problemas que aparecem em APIs não vem da linguagem, mas de decisões técnicas erradas ou simplesmente ignoradas. Abaixo estão os erros mais comuns que vejo em sistemas que começam a dar dor de cabeça depois de ir para produção.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">1) Confiar demais no frontend</h2>



<p>Esse é um clássico.</p>



<p>Validar apenas no frontend é assumir que:</p>



<ul class="wp-block-list">
<li>todo cliente vai se comportar bem;</li>



<li>ninguém vai chamar a API direto;</li>



<li>dados nunca vão chegar quebrados.</li>
</ul>



<p>Em produção, isso não acontece.</p>



<p>API precisa validar tudo o que recebe: tipo, formato, limites e estados possíveis. Qualquer dado inválido que entra no sistema vira bug silencioso, inconsistência ou erro difícil de rastrear depois.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">2) Não padronizar respostas de erro</h2>



<p>Uma hora o endpoint retorna erro como string, outra hora como objeto, outra hora com HTTP 200 e mensagem de erro no corpo.</p>



<p>Isso gera:</p>



<ul class="wp-block-list">
<li>confusão para quem consome a API;</li>



<li>lógica duplicada no client;</li>



<li>dificuldade de debug.</li>
</ul>



<p>API de produção precisa ter padrão. Mesmo formato de resposta, mesmos campos, mesmos códigos HTTP. Isso reduz erro e aumenta previsibilidade.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3) Ignorar controle de requisições</h2>



<p>Sem rate limiting, uma API fica exposta a:</p>



<ul class="wp-block-list">
<li>abuso involuntário;</li>



<li>loops mal implementados em integrações;</li>



<li>sobrecarga em horários de pico.</li>
</ul>



<p>Muitas quedas de API não são ataques. São apenas clientes chamando demais um endpoint que não foi preparado para isso.</p>



<p><strong>Controle de requisições não é opcional em produção.</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">4) Misturar regra de negócio com camada HTTP</h2>



<p>Quando controller começa a virar:</p>



<ul class="wp-block-list">
<li>regra de negócio;</li>



<li>validação;</li>



<li>persistência;</li>



<li>resposta HTTP;</li>
</ul>



<p>o código se torna frágil.</p>



<p>Esse tipo de acoplamento dificulta:</p>



<ul class="wp-block-list">
<li>testes;</li>



<li>reutilização de lógica;</li>



<li>manutenção futura.</li>
</ul>



<p>Separar responsabilidades não é academicismo. É o que evita refatorações dolorosas depois.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">5) Não pensar em idempotência</h2>



<p>Em produção, requisições podem ser reenviadas. Jobs podem rodar mais de uma vez. Webhooks podem disparar duplicado.</p>



<p>Se a API não for idempotente:</p>



<ul class="wp-block-list">
<li>registros duplicam;</li>



<li>ações são executadas mais de uma vez;</li>



<li>efeitos colaterais aparecem.</li>
</ul>



<p>Esse tipo de bug geralmente só aparece depois de um tempo, quando já tem dado real envolvido.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">6) Assumir que dependências externas sempre funcionam</h2>



<p>APIs de terceiros falham. Sempre.</p>



<p>Se sua API depende de outro serviço e não define:</p>



<ul class="wp-block-list">
<li>timeout;</li>



<li>tratamento de erro;</li>



<li>comportamento de fallback;</li>
</ul>



<p>ela vai travar junto.</p>



<p>Código de produção não assume sucesso. Ele se prepara para falha.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">7) Falta de timeout nas requisições</h2>



<p>Sem timeout, uma chamada externa lenta pode:</p>



<ul class="wp-block-list">
<li>travar workers;</li>



<li>consumir conexões;</li>



<li>gerar fila acumulada;</li>



<li>derrubar performance geral.</li>
</ul>



<p>Timeout é uma forma de proteção do sistema. Não definir é deixar o sistema vulnerável.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">8) Falta de logs úteis</h2>



<p>Log demais é tão ruim quanto log nenhum.</p>



<p>Em produção, log precisa responder perguntas como:</p>



<ul class="wp-block-list">
<li>o que aconteceu?</li>



<li>quando aconteceu?</li>



<li>com qual dado?</li>



<li>em qual ponto do fluxo?</li>
</ul>



<p>Logs genéricos ou inexistentes transformam qualquer incidente em caça ao erro.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">9) Falta de versionamento da API</h2>



<p>Alterar contrato de API sem versionamento quebra clientes silenciosamente.</p>



<p>Versão não é detalhe. É o que permite evoluir a API sem destruir integrações existentes.</p>



<p>Ignorar isso costuma gerar retrabalho e retratação depois.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">10) Tratar produção como ambiente de teste</h2>



<p>Produção não é lugar para:</p>



<ul class="wp-block-list">
<li>“ver se funciona”;</li>



<li>testar comportamento;</li>



<li>improvisar correções.</li>
</ul>



<p>APIs em produção precisam ser previsíveis, estáveis e fáceis de operar. Qualquer mudança deve assumir impacto real.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Conclusão</h2>



<p>APIs quebram porque foram pensadas apenas para funcionar, não para operar em produção.</p>



<p>Evitar esses erros não exige ferramentas mirabolantes. Exige postura técnica, atenção ao contexto e responsabilidade com quem vai depender da API depois.</p>
<p>The post <a href="https://leonardonascimento.dev/blog/erros-comuns-em-apis-que-causam-problemas-em-producao/">Erros comuns em APIs que causam problemas em produção</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/erros-comuns-em-apis-que-causam-problemas-em-producao/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>UPDOWN.IO: Receba notificação no WhatsApp caso seu site fique indisponível</title>
		<link>https://leonardonascimento.dev/blog/updown-io-receba-notificacao-no-whatsapp-caso-seu-site-fique-indisponivel/</link>
					<comments>https://leonardonascimento.dev/blog/updown-io-receba-notificacao-no-whatsapp-caso-seu-site-fique-indisponivel/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Sun, 20 Oct 2024 23:55:18 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Alertas]]></category>
		<category><![CDATA[Api WhatsApp]]></category>
		<category><![CDATA[Callback]]></category>
		<category><![CDATA[Callbacks]]></category>
		<category><![CDATA[Composer]]></category>
		<category><![CDATA[Configurar Projeto]]></category>
		<category><![CDATA[Estratégia]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Integração WhatsApp]]></category>
		<category><![CDATA[Interface Simples]]></category>
		<category><![CDATA[Intervalos de Tempo]]></category>
		<category><![CDATA[Localizações]]></category>
		<category><![CDATA[Monitoramento de Sites]]></category>
		<category><![CDATA[Múltiplos Sites]]></category>
		<category><![CDATA[Número Configurado]]></category>
		<category><![CDATA[Pasta Public]]></category>
		<category><![CDATA[PHP 7.4]]></category>
		<category><![CDATA[Requisições POST]]></category>
		<category><![CDATA[Servidor HTTP]]></category>
		<category><![CDATA[Slack]]></category>
		<category><![CDATA[SMS]]></category>
		<category><![CDATA[StatusPage]]></category>
		<category><![CDATA[Subdomínio de Teste]]></category>
		<category><![CDATA[Telegram]]></category>
		<category><![CDATA[Tempo de Resposta]]></category>
		<category><![CDATA[Tempo Real]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Updown Notify Whatsapp]]></category>
		<category><![CDATA[Updown.io]]></category>
		<category><![CDATA[WhatsApp]]></category>
		<category><![CDATA[WppConnect]]></category>
		<category><![CDATA[Wppconnect-server]]></category>
		<category><![CDATA[Zapier]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=164</guid>

					<description><![CDATA[<p>Com mais de 6 pontos de acompanhamento espalhados pelo mundo, o Updown.io é um sistema de monitoramento de sites em tempo real. Através de uma interface simples e agradável, é possível monitorar múltiplos sites , com intervalos de tempo entre 15 segundos e 1 hora, selecionar até 8 localizações,&#160; com tempo mínimo de resposta entre [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/updown-io-receba-notificacao-no-whatsapp-caso-seu-site-fique-indisponivel/">UPDOWN.IO: Receba notificação no WhatsApp caso seu site fique indisponível</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p> Com mais de 6 pontos de acompanhamento espalhados pelo mundo, o <a rel="noreferrer noopener" href="https://bit.ly/3IlDSdD" data-type="URL" data-id="https://bit.ly/3IlDSdD" target="_blank">Updown.io</a> é um sistema de monitoramento de sites em tempo real. </p>



<p>Através de uma interface simples e agradável, é possível monitorar múltiplos sites , com intervalos de tempo entre 15 segundos e 1 hora, selecionar até 8 localizações,&nbsp; com tempo mínimo de resposta entre 0.125 e 2.0 segundos e “callbacks” (SMS, Telegram, Slack, StatusPage, Zapier) para ser informado em caso de queda ou restauração do serviço.</p>



<p>Desenvolvi a estratégia para um amigo, que gostaria de receber alertas no WhatsApp em tempo real, quando algum site ou sistema fica-se fora do ar, decidimos tornar o código fonte público.</p>



<h2 class="wp-block-heading">Requerimentos</h2>



<ul class="wp-block-list"><li><a rel="noreferrer noopener" href="https://github.com/wppconnect-team/wppconnect-server" data-type="URL" data-id="https://github.com/wppconnect-team/wppconnect-server" target="_blank">Wppconnect Server</a></li><li>PHP 7.4</li></ul>



<p></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>O Wppconnect Server é uma lib não oficial do WhatsApp para envio e recebimento de mensagens. para receber a notificação em seu WhatsApp é necessário ter configurado o Wppconnect server. </p><p>Neste tutorial, aprenderemos a configurar o Updown Notify WhatsApp</p></blockquote>



<h3 class="wp-block-heading">Updown Notify Whatsapp</h3>



<p></p>



<p><strong>Clone o projeto e acesse o diretório </strong></p>



<p><code>git clone https://github.com/leonardop21/updown-notify-whatsapp &amp;&amp; cd updown-notify-whatsapp</code></p>



<p><strong>Instale as dependências (Necessário ter o composer configurado na máquina)</strong></p>



<p><code>composer install</code></p>



<p><strong>Configurando o projeto</strong></p>



<p>      No arquivo <code>/public/callback</code> configure um chave pública, ex: Afwe14we555d1230we23sdx</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="354" src="https://leonardonascimento.dev/wp-content/uploads/2022/03/key-1024x354.png" alt="" class="wp-image-175" srcset="https://leonardonascimento.dev/wp-content/uploads/2022/03/key-1024x354.png 1024w, https://leonardonascimento.dev/wp-content/uploads/2022/03/key-300x104.png 300w, https://leonardonascimento.dev/wp-content/uploads/2022/03/key-768x265.png 768w, https://leonardonascimento.dev/wp-content/uploads/2022/03/key-1536x531.png 1536w, https://leonardonascimento.dev/wp-content/uploads/2022/03/key.png 1632w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p></p>



<p>      No arquivo&nbsp;<code>/services/WppInfo</code>&nbsp;na função <code>__construct() </code>preencha os dados gerados no Wppconnect-server, para receber notificações no WhatsApp</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="430" src="https://leonardonascimento.dev/wp-content/uploads/2022/03/wpp-info-1024x430.png" alt="" class="wp-image-177" srcset="https://leonardonascimento.dev/wp-content/uploads/2022/03/wpp-info-1024x430.png 1024w, https://leonardonascimento.dev/wp-content/uploads/2022/03/wpp-info-300x126.png 300w, https://leonardonascimento.dev/wp-content/uploads/2022/03/wpp-info-768x323.png 768w, https://leonardonascimento.dev/wp-content/uploads/2022/03/wpp-info.png 1514w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p></p>



<p><strong>Apontando para a pasta public</strong></p>



<p>Configure seu servidor http, para ler a partir da pasta public.</p>



<p><strong>Agora, no sistema do Updown.io </strong></p>



<p>      No <a rel="noreferrer noopener" href="https://bit.ly/3IlDSdD" data-type="URL" data-id="https://bit.ly/3IlDSdD" target="_blank">Updown.io</a> insira a sua url de callback junto com a key que definiu, ex:&nbsp;<code>https://meusite.com.br/callback?key=Afwe14we555d1230we23sdx</code></p>



<p>O Updown Notify Whatsapp<strong> aceita apenas requisições post</strong> com a key configurada no passo anterior, do contrário, uma página 404 será exibida.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="610" height="280" src="https://leonardonascimento.dev/wp-content/uploads/2022/03/webhook.png" alt="" class="wp-image-178" srcset="https://leonardonascimento.dev/wp-content/uploads/2022/03/webhook.png 610w, https://leonardonascimento.dev/wp-content/uploads/2022/03/webhook-300x138.png 300w" sizes="(max-width: 610px) 100vw, 610px" /></figure>



<p><strong>Testando a aplicação</strong></p>



<p>      Criei um subdomínio de teste e inseri no updown.io.</p>



<p>      No momento em que o site ficou fora do ar, recebi um aviso no WhatsApp, quando voltou ao normal, recebi outro aviso, conforme demonstra as imagens abaixo.</p>



<p><strong>Updown detectou site fora do ar</strong></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="352" src="https://leonardonascimento.dev/wp-content/uploads/2022/03/site-fora-1024x352.png" alt="" class="wp-image-180" srcset="https://leonardonascimento.dev/wp-content/uploads/2022/03/site-fora-1024x352.png 1024w, https://leonardonascimento.dev/wp-content/uploads/2022/03/site-fora-300x103.png 300w, https://leonardonascimento.dev/wp-content/uploads/2022/03/site-fora-768x264.png 768w, https://leonardonascimento.dev/wp-content/uploads/2022/03/site-fora.png 1244w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p></p>



<p><strong>Callback Updown</strong></p>



<p>      O Updown enviou um callback ao sistema, que por sua vez acionou o Wppconnect-Server enviando uma mensagem para o número configurado no services/WppInfo</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="493" height="1024" src="https://leonardonascimento.dev/wp-content/uploads/2022/03/Whats-Fora-493x1024.png" alt="" class="wp-image-186" srcset="https://leonardonascimento.dev/wp-content/uploads/2022/03/Whats-Fora-493x1024.png 493w, https://leonardonascimento.dev/wp-content/uploads/2022/03/Whats-Fora-144x300.png 144w, https://leonardonascimento.dev/wp-content/uploads/2022/03/Whats-Fora.png 616w" sizes="auto, (max-width: 493px) 100vw, 493px" /></figure>



<p></p>



<p><strong>Site funcionando normalmente</strong></p>



<p>      Updown detectou que o site voltou a funcionar</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="311" src="https://leonardonascimento.dev/wp-content/uploads/2022/03/site-ok-1-1024x311.png" alt="" class="wp-image-187" srcset="https://leonardonascimento.dev/wp-content/uploads/2022/03/site-ok-1-1024x311.png 1024w, https://leonardonascimento.dev/wp-content/uploads/2022/03/site-ok-1-300x91.png 300w, https://leonardonascimento.dev/wp-content/uploads/2022/03/site-ok-1-768x233.png 768w, https://leonardonascimento.dev/wp-content/uploads/2022/03/site-ok-1.png 1217w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p></p>



<p><strong>Callback Updown</strong></p>



<p>      O Updown enviou um callback ao sistema, que por sua vez acionou o Wppconnect-Server enviando uma mensagem para o número configurado no services/WppInfo</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="491" height="1024" src="https://leonardonascimento.dev/wp-content/uploads/2022/03/whats-ok-491x1024.png" alt="" class="wp-image-188" srcset="https://leonardonascimento.dev/wp-content/uploads/2022/03/whats-ok-491x1024.png 491w, https://leonardonascimento.dev/wp-content/uploads/2022/03/whats-ok-144x300.png 144w, https://leonardonascimento.dev/wp-content/uploads/2022/03/whats-ok.png 614w" sizes="auto, (max-width: 491px) 100vw, 491px" /></figure>



<p></p>



<p>Links úteis</p>



<p><a href="https://github.com/wppconnect-team/wppconnect-server" data-type="URL" data-id="https://github.com/wppconnect-team/wppconnect-server" target="_blank" rel="noreferrer noopener">WPPCONNECT-SERVER</a></p>



<p><a href="https://github.com/leonardop21/updown-notify-whatsapp" data-type="URL" data-id="https://github.com/leonardop21/updown-notify-whatsapp" target="_blank" rel="noreferrer noopener">UPDOWN-NOFITY-WHATSAPP</a></p>
<p>The post <a href="https://leonardonascimento.dev/blog/updown-io-receba-notificacao-no-whatsapp-caso-seu-site-fique-indisponivel/">UPDOWN.IO: Receba notificação no WhatsApp caso seu site fique indisponível</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/updown-io-receba-notificacao-no-whatsapp-caso-seu-site-fique-indisponivel/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Protegendo formulários de Landing Page com Captcha v3 invisível e honeypot</title>
		<link>https://leonardonascimento.dev/blog/protegendo-formularios-de-landingpage-com-captcha-v3-invisivel-e-honeypot/</link>
					<comments>https://leonardonascimento.dev/blog/protegendo-formularios-de-landingpage-com-captcha-v3-invisivel-e-honeypot/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Sun, 20 Oct 2024 23:55:18 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Segurança]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=209</guid>

					<description><![CDATA[<p>Integrando formulário com o captcha invísivel (v3) &#8211; e enviando e-mails, utilizado em Landing pages A cada dia surgem diversas landing pages na web, seja para promover um evento ou até mesmo a venda de um produto, geralmente essas páginas possuem pelo menos um formulário de contato. Precisamos proteger esses formulários, se deixarmos a &#8220;esmo&#8221; [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/protegendo-formularios-de-landingpage-com-captcha-v3-invisivel-e-honeypot/">Protegendo formulários de Landing Page com Captcha v3 invisível e honeypot</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Integrando formulário com o captcha invísivel (v3) &#8211; e enviando e-mails, utilizado em Landing pages</p>



<p>A cada dia surgem diversas landing pages na web, seja para promover um evento ou até mesmo a venda de um produto, geralmente essas páginas possuem pelo menos um formulário de contato. </p>



<p>Precisamos proteger esses formulários, se deixarmos a &#8220;esmo&#8221; os clientes passarão a receber muitos spams e não queremos isso.</p>



<p>Alguns devs preferem criar um &#8220;honeypot&#8221; que é basicamente um field que recebe uma classe css e nesse css o campo é setado como hidden, no backend é feito uma validação, se esse field oculto for preenchido, o e-mail não é enviado, isso serve para bots menos &#8220;inteligentes&#8221;.</p>



<p>Uma das melhores soluções do mercado, querendo ou não, é a utilização do Captcha do Google. Pensando nisso, resolvi criar uma integração com o captcha e também utilizar o honeypot que citei acima. Tornei o projeto público, é muito simples de usar.</p>



<p>Você está livre para utilizar e modificar como preferir.</p>



<p><a href="https://github.com/leonardop21/captcha-send-form" target="_blank" rel="noreferrer noopener">https://github.com/leonardop21/captcha-send-form</a></p>
<p>The post <a href="https://leonardonascimento.dev/blog/protegendo-formularios-de-landingpage-com-captcha-v3-invisivel-e-honeypot/">Protegendo formulários de Landing Page com Captcha v3 invisível e honeypot</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/protegendo-formularios-de-landingpage-com-captcha-v3-invisivel-e-honeypot/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
