Cuando desarrollamos una aplicación web, una de las decisiones más comunes es elegir qué método HTTP utilizar para una ruta: GET o POST. A simple vista puede parecer una decisión menor, sobre todo cuando no estamos enviando parámetros, pero elegir correctamente el método ayuda a mejorar la seguridad, mantener una arquitectura más clara y evitar comportamientos inesperados.
En este artículo explicaremos de forma práctica cuándo usar GET, cuándo usar POST y por qué no todas las acciones deberían ejecutarse desde un simple enlace.
La regla básica
Una forma sencilla de verlo es la siguiente:
GET → consultar, mostrar o leer información. POST → enviar información, ejecutar acciones o modificar el estado del sistema.
Esta diferencia es importante porque no todos los accesos a una URL deberían tener consecuencias dentro del sistema. Una ruta que solamente muestra información puede trabajar con GET. En cambio, una ruta que guarda, actualiza, elimina o dispara un proceso debería utilizar POST u otro método apropiado.
Cuándo usar GET
El método GET se utiliza principalmente para consultar información. Es decir, cuando el usuario entra a una URL y espera ver datos, una página, un listado o un formulario, pero sin modificar nada en el sistema.
Ejemplos comunes de rutas que sí pueden usar GET:
- Mostrar el listado de productos.
- Ver el detalle de un pedido.
- Abrir un formulario de registro.
- Consultar reportes.
- Filtrar información en una tabla.
- Mostrar una pantalla de configuración.
Ejemplo genérico en Laravel:
Route::get('/admin/productos', [ProductController::class, 'index'])
->name('admin.products.index');
En este caso, la ruta solamente muestra información. No guarda datos, no elimina registros y no dispara procesos internos. Por eso GET es adecuado.
Cuándo usar POST
El método POST se utiliza cuando el usuario va a enviar información o cuando una acción puede modificar el estado de la aplicación.
Ejemplos comunes de acciones que deberían usar POST:
- Guardar un producto.
- Crear un pedido.
- Registrar un cliente.
- Enviar un formulario.
- Ejecutar una sincronización.
- Procesar información externa.
- Generar una acción administrativa.
Ejemplo genérico:
Route::post('/admin/productos', [ProductController::class, 'store'])
->name('admin.products.store');
Aquí la ruta recibe información y crea un nuevo registro. Por lo tanto, usar POST es lo correcto.
¿Y si no estoy enviando parámetros?
Una duda común aparece cuando tenemos un botón que no envía datos visibles, pero sí ejecuta una acción. Por ejemplo:
- Sincronizar productos.
- Procesar pedidos pendientes.
- Actualizar inventario.
- Ejecutar una tarea interna.
En estos casos podría parecer práctico usar un enlace con href y una ruta GET, porque no estamos enviando campos de formulario. Sin embargo, la decisión no depende solamente de si enviamos parámetros, sino de lo que ocurre cuando se visita la URL.
Si al abrir la URL se ejecuta un proceso, se modifica información o se cambia el estado del sistema, entonces no debería ser GET. Debería ser POST.
Ejemplo: ejecutar una sincronización
Supongamos que tenemos una aplicación administrativa y queremos agregar un botón para sincronizar información con un servicio externo.
Una opción incorrecta sería hacerlo así:
<a href="/admin/sincronizar-productos" class="btn btn-primary">
Sincronizar productos
</a>
Y definir la ruta como GET:
Route::get('/admin/sincronizar-productos', [SyncController::class, 'syncProducts']);
El problema es que esa URL ejecuta un proceso. No solo muestra información. Por lo tanto, puede activarse accidentalmente si el usuario recarga la página, abre el enlace en otra pestaña, el navegador intenta previsualizarlo o incluso si algún rastreador accede a esa URL.
La forma más adecuada sería usar una ruta POST:
Route::post('/admin/sincronizar-productos', [SyncController::class, 'syncProducts'])
->name('admin.products.sync');
Y ejecutarla desde un formulario:
<form action="{{ route('admin.products.sync') }}" method="POST">
@csrf
<button type="submit" class="btn btn-primary">
Sincronizar productos
</button>
</form>
Aunque el formulario no envíe campos adicionales, el uso de POST comunica correctamente que se trata de una acción, no de una simple consulta.
Por qué evitar GET para acciones importantes
Usar GET para ejecutar acciones puede provocar varios problemas:
- La acción puede ejecutarse accidentalmente al recargar la página.
- La URL puede compartirse o abrirse sin intención.
- Un navegador puede intentar previsualizar o precargar el enlace.
- Un bot o rastreador podría visitar la ruta.
- No se aprovecha la protección CSRF de la misma manera que con formularios
POST. - Se rompe la semántica de la aplicación, porque una consulta termina modificando el sistema.
Por eso, aunque usar GET pueda parecer más cómodo visualmente, no siempre es la opción correcta.
La importancia del CSRF
En frameworks como Laravel, los formularios POST suelen incluir un token CSRF para validar que la petición realmente fue generada desde la aplicación y no desde un sitio externo.
Ejemplo:
<form action="{{ route('admin.products.sync') }}" method="POST">
@csrf
<button type="submit">
Ejecutar sincronización
</button>
</form>
La directiva @csrf genera un token oculto que Laravel verifica al recibir la solicitud. Esto ayuda a proteger acciones sensibles como guardar información, eliminar registros o ejecutar procesos administrativos.
¿Qué pasa si el formulario afecta el diseño?
En ocasiones se evita usar un formulario porque visualmente no encaja bien dentro de un grupo de botones o dentro de una interfaz administrativa. Sin embargo, ese es un problema de presentación, no de arquitectura.
Podemos mantener el método correcto y ajustar el diseño con CSS:
<div class="btn-group" role="group">
<a href="{{ route('admin.products.index') }}" class="btn btn-secondary">
Regresar
</a>
<form action="{{ route('admin.products.sync') }}" method="POST" class="m-0 d-inline">
@csrf
<button type="submit" class="btn btn-primary">
Sincronizar
</button>
</form>
</div>
También puede resolverse con una petición AJAX usando fetch, manteniendo el método POST y enviando el token CSRF en los encabezados.
<button type="button" id="btn-sync" class="btn btn-primary">
Sincronizar
</button>
<script>
document.getElementById('btn-sync').addEventListener('click', function () {
fetch('/admin/sincronizar-productos', {
method: 'POST',
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
'Accept': 'application/json'
}
});
});
</script>
Lo importante es no cambiar a GET solo porque estéticamente es más cómodo usar un enlace.
GET no debe tener efectos secundarios
Una buena práctica es que las rutas GET no tengan efectos secundarios importantes. Es decir, visitar una URL con GET no debería crear registros, eliminar información, actualizar inventario ni ejecutar procesos internos.
Por ejemplo, estas rutas deberían evitarse:
GET /admin/eliminar-producto/10 GET /admin/procesar-pedidos GET /admin/sincronizar-inventario GET /admin/ejecutar-comando
Aunque técnicamente puedan funcionar, no son una buena práctica porque una simple visita a la URL puede cambiar el estado del sistema.
Entonces, ¿cuándo usar cada uno?
| Situación | Método recomendado | Motivo |
|---|---|---|
| Mostrar un listado | GET | Solo consulta información. |
| Ver detalle de un registro | GET | No modifica datos. |
| Mostrar un formulario | GET | Solo carga la interfaz. |
| Guardar un formulario | POST | Crea o modifica información. |
| Ejecutar una sincronización | POST | Dispara un proceso interno. |
| Eliminar un registro | DELETE o POST | Modifica el estado del sistema. |
| Actualizar información | PUT, PATCH o POST | Modifica datos existentes. |
Más allá de GET y POST
En aplicaciones modernas también es común utilizar otros métodos HTTP:
PUT: para actualizar completamente un recurso.PATCH: para actualizar parcialmente un recurso.DELETE: para eliminar un recurso.
Sin embargo, en formularios HTML tradicionales normalmente se trabaja con GET y POST. Frameworks como Laravel permiten simular métodos como PUT, PATCH o DELETE mediante campos ocultos.
<form action="{{ route('admin.products.destroy', $product) }}" method="POST">
@csrf
@method('DELETE')
<button type="submit">
Eliminar producto
</button>
</form>
Esto permite mantener una estructura más clara y alineada con las buenas prácticas de desarrollo web.
Ejemplo práctico de flujo correcto
Supongamos que tenemos un módulo de pedidos y necesitamos estas acciones:
GET /admin/pedidos → Mostrar pedidos GET /admin/pedidos/15 → Ver detalle del pedido GET /admin/pedidos/create → Mostrar formulario POST /admin/pedidos → Guardar pedido POST /admin/pedidos/sincronizar → Ejecutar sincronización DELETE /admin/pedidos/15 → Eliminar pedido
Este tipo de estructura permite entender rápidamente qué hace cada ruta y qué impacto tiene dentro de la aplicación.
Conclusión
Elegir entre GET y POST no debería depender únicamente de si enviamos parámetros o de qué opción se ve mejor en la interfaz. La decisión debe basarse en la intención de la ruta.
Si la ruta solo consulta o muestra información, GET es correcto. Si la ruta guarda, modifica, elimina o ejecuta un proceso dentro del sistema, entonces debe usarse POST u otro método adecuado.
En proyectos reales, esta diferencia ayuda a construir aplicaciones más seguras, ordenadas y fáciles de mantener. Además, evita que acciones importantes se ejecuten accidentalmente desde una URL que debería ser únicamente de consulta.
La interfaz siempre se puede ajustar con CSS o JavaScript, pero la intención técnica de una ruta debe mantenerse clara desde el diseño de la aplicación.







Deja un comentario