Cargando…

Esto está tardando más de lo esperado.

Volver al centro de ayuda

Trabajar en el código

Los comandos que corres a diario, las pruebas, las revisiones antes de un push y dónde vive cada cosa.

Esta guía es la referencia diaria del desarrollador: cómo arrancar la aplicación, qué comandos Artisan agrega el kit, cómo corren las dos suites de pruebas, qué detiene un push y qué carpetas vas a tocar de verdad. Léela una vez después de /help/get-it-running y vuelve cuando se te escape el nombre de un comando.

Arranca todo

Un comando inicia los cuatro procesos que necesita una copia de trabajo:

composer dev

Es un script de Composer que corre npx concurrently con, en este orden y cada uno con su color: php artisan serve (server), php artisan queue:listen --tries=1 (queue), php artisan pail --timeout=0 (logs) y npm run dev (vite). Detener uno detiene los cuatro (--kill-others).

Si sirves el sitio con Herd o Valet, el servidor de PHP sobra: abre la APP_URL de tu .env (por ejemplo http://your-project.test) y corre los otros tres tú mismo en terminales separadas.

npm run dev                       # Vite con recarga en caliente
php artisan queue:listen --tries=1
php artisan pail

La cola importa incluso en desarrollo: las notificaciones, el web push y el trabajo de cobros son jobs, y nada ocurre hasta que un worker los toma. Cuando prefieras no correr uno, pon QUEUE_CONNECTION=sync en .env y los jobs corren en línea dentro de la petición. Ambas opciones se explican en /help/queues-and-scheduled-work.

El resto del conjunto diario es Laravel puro:

Comando Cuándo
php artisan migrate Después de jalar una migración.
php artisan db:seed Una vez, después de la primera migración, para crear las cuentas, roles y permisos sembrados. --class=UserSeeder o --class=AdminSeeder resiembra un grupo; los seeders usan firstOrCreate, así que una cuenta existente conserva su contraseña.
php artisan tinker Para inspeccionar o corregir un registro desde la consola con los modelos de la aplicación.
npm run build Para compilar los assets una vez, sin vigilar cambios.
php artisan schedule:work Para correr los comandos programados en local, cada minuto, mientras siga abierto.

Las cuentas sembradas salen de config/app.php: los correos en sudo se vuelven administradores, los de default_users se vuelven usuarios normales. Cada contraseña es la parte del correo antes de la @, invertida y en minúsculas, así que [email protected] inicia sesión con tset. A un administrador sembrado se le pide cambiar esa contraseña en su primer inicio de sesión.

Los comandos Artisan que agrega el kit

Estos son los comandos propios del kit, en app/Console/Commands:

Comando Qué hace
help:stamp Reescribe el comentario de huella en cada documento de ayuda traducido para que registre de qué versión en inglés se escribió. Sólo lee y hashea archivos; nunca llama a la red.
help:stamp --check No escribe nada. Imprime una tabla de los documentos de ayuda a los que les falta traducción, cuya versión en inglés cambió después de escribir la traducción, cuya versión en inglés ya no existe, o que no tienen front matter, y sale con código de fallo cuando la tabla no está vacía.
lang:search Recorre app/, resources/views/ y routes/ buscando __(), @lang(), trans(), Lang::get(), etiquetas de inputs de Laravel Front, ->setTitle() y títulos de acciones, y agrega a lang/en.json toda llave que falte.
lang:sync Hace que cada archivo de idioma tenga las mismas llaves que el inglés, en el mismo orden. Una llave que sólo existe en otro idioma se agrega al inglés; una llave que falta en un idioma se traduce con el proveedor de IA configurado, o se deja en inglés cuando no hay ninguno configurado. Cubre lang/*.json y lang/{locale}/*.php.
lang:delete Quita de todo archivo lang/*.json las llaves que ningún archivo del proyecto usa ya. Nunca toca los archivos PHP de traducción.
lang:update Corre lang:sync, luego lang:search y luego lang:sync otra vez: la ronda completa de traducción en un comando.
pwa:generate-assets Pide un icono base cuadrado de al menos 512 px y dos colores de fondo, y luego escribe todos los tamaños de icono y pantalla de inicio que lista config/laravelpwa.php en public/images/icons.
stats:compute-daily Cuenta los usuarios que iniciaron sesión ayer y guarda el número en la tabla stats bajo daily_logged_users. Programado en routes/console.php para correr a diario a las 00:00.

El paquete weblabormx/billing-core en packages/ agrega uno más:

Comando Qué hace
billing:sync-exchange-rates {--date=} Obtiene y guarda los tipos de cambio para las fechas de suscripciones pagadas que necesitan conversión de moneda. Programado a diario a las 12:00, y sólo mientras los planes o los complementos estén habilitados.

Los paquetes instalados agregan los comandos que también vas a buscar: clean:code del paquete de estándares de código de Weblabor (--no-commit omite el commit que hace), webpush:vapid del canal de web push, dusk y dusk:chrome-driver de Laravel Dusk, ide-helper:generate e ide-helper:models del IDE helper (sus archivos de salida están ignorados por Git), y make:agent, make:tool, make:agent-middleware y agent:chat del paquete Laravel AI, descritos en /help/connect-an-ai-provider. php artisan list los imprime todos.

Las pruebas

Hay dos suites y corren de forma distinta.

Pruebas de funcionalidad

phpunit.xml declara una suite, WeblaborBase, sobre tests/WeblaborBase. Sus carpetas son Admin, Auth, BillingCore, Categories y Help, una por área del kit. La suite corre sobre una base de datos SQLite en memoria, así que no necesita servidor de base de datos y deja intactos tus datos de desarrollo:

Ajuste forzado por phpunit.xml Valor
APP_ENV testing
DB_CONNECTION / DB_DATABASE sqlite / :memory:
QUEUE_CONNECTION sync
MAIL_MAILER array
CACHE_DRIVER, SESSION_DRIVER array

tests/TestCase.php va más lejos antes de que arranque la aplicación: borra bootstrap/cache/config.php para que una configuración de MySQL en caché no se filtre a la corrida, carga .env y encima .env.testing, y fuerza SQLite una vez más. .env.testing está committeado y trae una APP_KEY más los ajustes de SQLite, y por eso una copia recién clonada puede correr las pruebas antes de tener .env.

Extiende Tests\FeatureTestCase para una prueba que toque la base de datos. Agrega RefreshDatabase y siembra PermissionSeeder y RoleSeeder antes de cada prueba, así que config('app.admin_role') existe y se le puede asignar a un usuario. Tests\TestCase es la base desnuda para una prueba que no necesita ninguna de las dos cosas.

php artisan test                                              # toda la suite
php artisan test tests/WeblaborBase/Admin/DevZoneTest.php     # un archivo
php artisan test --filter=test_user_can_login                 # un método
composer test                                                 # config:clear y luego la suite

composer test-without-billing-core corre scripts/ci/test-without-billing-core.sh: copia el proyecto a una carpeta temporal, ahí quita el paquete weblabormx/billing-core, migra y siembra un archivo SQLite desechable, verifica que no sobreviva ninguna ruta de cobros y corre dos pruebas de funcionalidad. Demuestra que el kit sigue arrancando cuando un proyecto se entrega sin cobros. Tu copia de trabajo no se modifica.

Pruebas de navegador

tests/Browser/WeblaborBase guarda las pruebas de Laravel Dusk, en las carpetas Auth y App. Manejan un Chrome real a través de ChromeDriver, contra la aplicación tal como la sirve tu .env, así que el sitio debe ser alcanzable en APP_URL y la base de datos que configuraste es la que usan. No forman parte de php artisan test.

php artisan dusk:chrome-driver --detect   # una vez, y después de que Chrome se actualice
php artisan dusk                           # todas las pruebas de navegador
php artisan dusk tests/Browser/WeblaborBase/Auth/LoginTest.php

tests/DuskTestCase.php inicia ChromeDriver en el puerto 9515 a menos que corras dentro de Sail, y abre Chrome sin ventana a 1920×1080. Tres variables de entorno cambian eso, leídas del shell o de .env:

Variable Efecto
DUSK_DRIVER_URL Dónde escucha ChromeDriver. Valor por omisión http://localhost:9515.
DUSK_HEADLESS_DISABLED Ponle cualquier valor para ver el navegador. php artisan dusk --browse la pone por ti.
DUSK_START_MAXIMIZED Ponle cualquier valor para maximizar la ventana en lugar del tamaño fijo.

Cuando existe un archivo llamado .env.dusk.local (.env.dusk.{APP_ENV}), Dusk lo intercambia por .env mientras corren las pruebas y restaura .env al terminar. Úsalo para apuntar las pruebas de navegador a una base de datos separada.

Extiende Tests\Browser\WeblaborBase\WeblaborBaseDuskTestCase. Te da makeVerifiedUser() (una cuenta verificada cuya contraseña es password), makeAdminUser() (lo mismo, con el rol admin después de sembrar permisos y roles), ensureActiveSubscription() para un flujo detrás del muro de pago, fillWireModel() para escribir en un campo wire:model, clickFirstSubmitButton(), assertBrowserPageLoaded() y latestVerificationCodeFromLog(), que lee el último código de verificación escrito en el log y por lo tanto necesita MAIL_MAILER=log. Toda cuenta creada con estos helpers se elimina definitivamente en tearDown(). Las pruebas fallidas dejan una captura en tests/Browser/screenshots, la salida de consola en tests/Browser/console y el código fuente de la página en tests/Browser/source; las tres carpetas están ignoradas por Git.

Playwright está presente en package.json como dependencia de desarrollo, pero ninguna prueba del repositorio lo usa; la suite de navegador corre con Dusk y ChromeDriver.

Análisis estático y estilo

vendor/bin/phpstan analyze
php artisan clean:code --no-commit

Larastan está instalado para el primero. No hay un phpstan.neon committeado, así que pasa las rutas y el nivel que quieras en la línea de comandos o agrega el archivo a tu proyecto. El segundo aplica los estándares de código de Weblabor a todo el proyecto; sin --no-commit hace commit del resultado. Ese es también el único trabajo que corre el pipeline de GitLab committeado: .gitlab-ci.yml instala las dependencias con scripts/ci/prepare-clean-code.sh, corre clean:code --no-commit y sube un commit "Code Style Fixes" cuando algo cambió. Sus otros trabajos hacen merge de master en staging y de staging en develop después de cada push a esas ramas. El pipeline no corre las pruebas.

composer install-locally-repo es para quien desarrolla los paquetes de Weblabor mismos: reemplaza vendor/weblabormx/weblabor-cs, laravel-front y tall-utils con enlaces simbólicos a copias hermanas. Déjalo en paz a menos que seas tú.

Depurar mientras trabajas

En el entorno local con APP_DEBUG=true la Debugbar muestra las consultas, vistas, eventos y tiempos de cada página, y el detector de consultas reporta consultas N+1 dentro de ella. DEBUGBAR_ENABLED, QUERY_DETECTOR_ENABLED, QUERY_DETECTOR_THRESHOLD y las demás variables que los ajustan, los canales de log incluido Slack, y el límite de excepciones están todos en /help/logs-and-debugging. php artisan pail sigue el log en la terminal y /logs lo muestra en el navegador.

Para recibir webhooks de Stripe en tu máquina, reenvíalos con la CLI de Stripe a la ruta que el kit expone en routes/api.php, y luego pon en .env el secreto que imprime:

stripe listen --forward-to your-project.test/api/stripe/webhook
STRIPE_WEBHOOK_SECRET=whsec_xxxxx

Qué detiene un push

composer install corre git config core.hooksPath scripts/git-hooks al final de cada volcado de autoload, así que los hooks de esa carpeta están activos en cada clon, incluidos los proyectos que derives del kit. Hay uno, pre-push, y corre:

php artisan help:stamp --check

Un push se rechaza mientras a algún documento de ayuda le falte traducción, tenga una traducción más vieja que su inglés, tenga una traducción cuyo inglés ya no existe, o no tenga front matter. La tabla que imprime nombra cada archivo y el problema. Corrige los documentos, corre php artisan help:stamp para volver a sellar las traducciones y vuelve a hacer push. Para la única vez que necesites hacer push de todos modos:

git push --no-verify

El hook necesita PHP y una aplicación que arranque en el shell que hace el push; desde un cliente de Git que no puede correr php artisan, falla, y --no-verify es la salida.

Dónde vive cada cosa

Carpeta Qué pones ahí
app/Livewire/Admin, App, Auth, Web, Shared Toda pantalla interactiva. Admin es el panel de administración, App el área con sesión iniciada, Auth el inicio de sesión, perfil y cuenta, Web las páginas públicas, Shared componentes que usa más de un área.
app/Front/Resources Los CRUDs del panel de administración, una clase por modelo, con su política en app/Policies. app/Front/Inputs, Filters, Actions y Pages guardan sus piezas personalizadas.
app/Models Modelos Eloquent, todos extendiendo App\Models\Model, con $guarded y nunca $fillable. Los casts, enums, traits y observers están en /help/models-casts-and-building-blocks.
app/Helpers Funciones globales, un archivo por capa (base.php para el kit); cada función está protegida con function_exists para que un proyecto derivado pueda agregar su propio archivo.
app/Console/Commands Comandos Artisan. Las programaciones van en routes/console.php.
app/Services, app/Jobs, app/Notifications, app/Mail Aquello a lo que un método de modelo delega.
routes/web.php, auth.php, app.php, admin.php, api.php Rutas públicas, de autenticación, de /app, de /admin y de API. Qué middleware envuelve cada grupo está en /help/routes-layouts-and-middleware.
resources/views/components Componentes Blade: <x-date-input>, <x-phone-input>, <x-email-input>, <x-domain-input>, <x-categories-input>, <x-language-switcher>, <x-sidebar-menu>, <x-loading-overlay>, <x-system-warnings> y el reproductor de audio. Busca aquí antes de escribir el mismo marcado dos veces.
resources/views/livewire, layouts, landing, pages, emails Vistas de componentes, layouts de página, la landing, páginas estáticas y plantillas de correo.
lang/en.json, lang/es.json, lang/{locale}/*.php Toda cadena que una persona lee, escrita en inglés en el código y traducida aquí.
docs/{project}/help/guides, docs/{project}/help/changelog El centro de ayuda que estás leyendo, con las traducciones en una carpeta de idioma junto a cada archivo en inglés.
stubs/ Las plantillas que usa php artisan make:*, ajustadas a las convenciones del kit.
packages/ Paquetes que viajan dentro del repositorio, hoy billing-core.