Tema
Estructura del proyecto
Un proyecto Laravel recién creado tiene muchas carpetas y archivos. En esta lección aprenderás qué hay en cada una, cuáles vas a tocar todos los días y cuáles casi nunca. También conocerás artisan, el archivo .env y bootstrap/app.php, el corazón de la configuración en Laravel 11/12.
Concepto
Piensa en el proyecto como un restaurante:
public/es la puerta principal: lo único a lo que entran los clientes.routes/es el mesero que recibe el pedido y lo lleva a la cocina correcta.app/es la cocina: donde se prepara todo (controladores, modelos, lógica).resources/views/es el emplatado: cómo se presenta el platillo (HTML).database/es la despensa: estructura y datos iniciales.config/y.envson el manual de operaciones del restaurante.storage/es la bodega: archivos subidos, logs, caché.vendor/son los proveedores: código de terceros que no tocas.
El mapa completo
txt
mi-app/
├── app/
│ ├── Http/
│ │ └── Controllers/ ← tus controladores
│ ├── Models/ ← tus modelos Eloquent (User.php ya existe)
│ └── Providers/
│ └── AppServiceProvider.php ← configuración al arrancar la app
├── bootstrap/
│ ├── app.php ← configura rutas, middleware y excepciones
│ └── providers.php ← lista de service providers
├── config/ ← archivos de configuración (app, database, mail...)
├── database/
│ ├── factories/ ← generadores de datos falsos
│ ├── migrations/ ← "control de versiones" de tus tablas
│ ├── seeders/ ← datos iniciales
│ └── database.sqlite ← la BD si usas SQLite
├── public/
│ ├── index.php ← punto de entrada de TODAS las peticiones
│ └── build/ ← CSS/JS compilados por Vite (npm run build)
├── resources/
│ ├── css/app.css
│ ├── js/app.js
│ └── views/ ← plantillas Blade (.blade.php)
├── routes/
│ ├── web.php ← rutas de páginas web
│ └── console.php ← comandos y tareas programadas
├── storage/
│ ├── app/ ← archivos subidos (public/ y private/)
│ ├── framework/ ← caché, sesiones, vistas compiladas
│ └── logs/laravel.log ← ¡aquí ves los errores!
├── tests/ ← pruebas automáticas
├── vendor/ ← dependencias de Composer (NO se edita ni se sube a Git)
├── .env ← variables de entorno (NO se sube a Git)
├── .env.example ← plantilla del .env (SÍ se sube)
├── artisan ← la consola de Laravel
├── composer.json ← dependencias de PHP
├── package.json ← dependencias de JS
└── vite.config.js ← configuración de Vite¿Dónde está routes/api.php?
En Laravel 11/12 no viene por defecto. Se crea cuando lo necesitas con php artisan install:api (lo verás en APIs con Sanctum). Lo mismo pasa con routes/channels.php (php artisan install:broadcasting).
El archivo .env
Contiene la configuración que cambia según el entorno (tu PC, el servidor de pruebas, producción) y los secretos (contraseñas, claves de API).
env
APP_NAME="Mi App"
APP_ENV=local # local | production
APP_KEY=base64:xxxxxxxx # clave de cifrado (php artisan key:generate)
APP_DEBUG=true # true en local, SIEMPRE false en producción
APP_URL=http://mi-app.test
APP_LOCALE=es # idioma por defecto
APP_FALLBACK_LOCALE=en
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=mi_app
DB_USERNAME=root
DB_PASSWORD=
SESSION_DRIVER=database
QUEUE_CONNECTION=database
CACHE_STORE=database
MAIL_MAILER=log # en local, los correos se escriben en el logLos archivos de config/ leen esas variables con env(). Por ejemplo, config/app.php:
php
<?php
return [
// Si APP_NAME no existe en .env, usa 'Laravel'
'name' => env('APP_NAME', 'Laravel'),
'debug' => (bool) env('APP_DEBUG', false),
// ...
];Y en tu código usas config(), nunca env() directamente:
php
// ✅ Correcto: lee la configuración (funciona con la caché de config)
$nombre = config('app.name');
// ❌ Incorrecto fuera de config/: con "php artisan config:cache" devuelve null
$nombre = env('APP_NAME');Nunca subas el .env a Git
El .env tiene contraseñas de la base de datos, claves de correo y de pasarelas de pago. Laravel ya lo incluye en .gitignore; no lo quites. Revisa la lección de gestión de secretos.
bootstrap/app.php: el centro de control
En versiones anteriores la configuración estaba repartida en Kernel.php, RouteServiceProvider.php y Handler.php. Desde Laravel 11 todo vive aquí:
php
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
// 1. Qué archivos de rutas se cargan
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up', // ruta de "salud" para monitoreo
)
// 2. Registro y configuración de middleware
->withMiddleware(function (Middleware $middleware) {
// Aquí agregarás alias de middleware, por ejemplo:
// $middleware->alias(['admin' => \App\Http\Middleware\EsAdmin::class]);
})
// 3. Cómo se reportan y muestran los errores
->withExceptions(function (Exceptions $exceptions) {
//
})->create();Volverás a este archivo en las lecciones de middleware y APIs.
Artisan: tu asistente en la terminal
artisan es un script PHP que genera código y ejecuta tareas. Comandos que usarás a diario:
powershell
php artisan list # ver todos los comandos
php artisan help make:model # ayuda de un comando
# Generadores (make:*)
php artisan make:controller ProductoController
php artisan make:model Producto -mfs # modelo + migración + factory + seeder
php artisan make:request GuardarProductoRequest
php artisan make:middleware EsAdmin
php artisan make:policy ProductoPolicy --model=Producto
# Base de datos
php artisan migrate # ejecuta migraciones pendientes
php artisan migrate:fresh --seed # borra todo, migra y siembra (solo en local)
php artisan db:seed
# Utilidades
php artisan route:list # ver todas las rutas registradas
php artisan tinker # consola interactiva con tu app cargada
php artisan optimize:clear # limpia todas las cachés
php artisan storage:link # enlace público a storage/app/publicTinker: experimenta sin crear rutas
powershell
php artisan tinkerphp
> App\Models\User::count();
= 0
> config('app.name');
= "Mi App"
> now()->format('d/m/Y');
= "18/10/2026"
> exitArchivos que tocarás (y los que no)
| Tocas a diario | Tocas a veces | No tocas |
|---|---|---|
routes/web.php | bootstrap/app.php | vendor/ |
app/Http/Controllers/ | config/*.php | storage/framework/ |
app/Models/ | app/Providers/AppServiceProvider.php | public/index.php |
resources/views/ | .env | bootstrap/cache/ |
database/migrations/ | composer.json, package.json | public/build/ (lo genera Vite) |
Buena práctica
Cuando algo falle y la pantalla no diga mucho, abre storage/logs/laravel.log. Ahí Laravel guarda el error completo con el archivo y la línea exacta. Es el primer lugar donde mirar, sobre todo en producción.
Error común
"The stream or file storage/logs/laravel.log could not be opened: Permission denied" en servidores Linux. Laravel necesita escribir en storage/ y bootstrap/cache/. Solución en el servidor:
bash
sudo chown -R www-data:www-data storage bootstrap/cache
sudo chmod -R 775 storage bootstrap/cacheError común
Cambias el .env y "no pasa nada". Probablemente la configuración está cacheada. Ejecuta php artisan config:clear (o optimize:clear).
Ejercicios
- Abre tu proyecto y localiza: el archivo de rutas web, el modelo
User, la vista de bienvenida y el archivo de log. - Cambia
APP_NAMEen.enva "Mi Primera App" y crea una ruta/nombreque muestre ese valor usandoconfig(). - Usa
php artisan route:listy anota cuántas rutas tiene tu proyecto y cuál es la ruta/up. - Con Tinker, crea un usuario y cuéntalos.
Ver solución
- Ubicaciones:
txt
routes/web.php
app/Models/User.php
resources/views/welcome.blade.php
storage/logs/laravel.log- En
.env:
env
APP_NAME="Mi Primera App"En routes/web.php:
php
Route::get('/nombre', function () {
return 'Esta app se llama: ' . config('app.name');
});Si no ves el cambio, ejecuta php artisan config:clear.
php artisan route:listmuestra algo como:
txt
GET|HEAD / ........................................
GET|HEAD nombre ...................................
GET|HEAD up .......................................
GET|HEAD storage/{path} ........... storage.local/up es la ruta de salud configurada en bootstrap/app.php (health: '/up'): devuelve 200 si la app funciona, útil para servicios de monitoreo.
- En Tinker:
php
> App\Models\User::create(['name' => 'Ana', 'email' => 'ana@correo.com', 'password' => 'secreto123']);
> App\Models\User::count();
= 1(El modelo User aplica hash a la contraseña automáticamente gracias al cast 'password' => 'hashed'.)
Resumen
app/tiene tu lógica (controladores y modelos);resources/views/tus plantillas;routes/web.phptus rutas.public/es lo único accesible desde internet;vendor/y.envnunca se suben a Git..envguarda configuración por entorno y secretos; en tu código usaconfig(), noenv().bootstrap/app.phpcentraliza rutas, middleware y manejo de excepciones en Laravel 11/12.php artisangenera código (make:*), migra la BD, lista rutas y abre Tinker.- Los errores se registran en
storage/logs/laravel.log.