{
 "id": "laravel-php",
 "kind": "skill",
 "name": "Laravel and PHP",
 "description": "Build and change Laravel and PHP applications: routes, controllers, Eloquent, migrations, Blade, authentication, queues, tests and code style. Version aware.",
 "version": "1.0.0",
 "author": "Hexa Hub",
 "files": {
  "SKILL.md": "---\nname: laravel-php\ndescription: Build and change Laravel and PHP applications: routes, controllers, Eloquent, migrations, Blade, authentication, queues, tests and code style. Version aware.\ntitle: Laravel and PHP\nicon: tabler:brand-laravel\ncategory: Development\ntriggers: laravel, artisan, eloquent, blade, migration, livewire, inertia, composer, php, pest, phpunit, pint, phpstan, sanctum, breeze, jetstream, middleware\nmarkers: php, composer\nrecipes: laravel.about, laravel.route-list, laravel.migrate-status, laravel.migrate-pretend, laravel.migrate, laravel.test, laravel.pint-check, check.php-lint, check.phpstan, check.composer-validate, deps.composer-install, mysql.query\nrelated: frontend-tailwind-js, sql-server-liquibase\ncheck: *.php => check.php-lint file=$file\n---\n\n# Laravel and PHP\n\n## Start by learning the project (cheap, read only)\n1. `laravel.about`: Laravel and PHP versions, environment, drivers. Tell the user the versions; **advice depends on them** (Laravel 11 and later has a slimmer skeleton: middleware and exceptions are configured in `bootstrap/app.php`, there is no `Http/Kernel.php`; older projects differ). If unsure for the installed version, read the code that is there and follow it, or use the official docs for that version.\n2. Read `composer.json` (packages: Livewire, Inertia, Sanctum, Pest vs PHPUnit) and follow what the project already uses. Look at one existing controller, model and test and copy their style.\n3. `laravel.route-list` for the routes; `find_code` for where something is handled.\n\n## Changing code\n- New things start from a generator the user can run (`make:model -mfc`, `make:request`, `make:policy`); you write the files with the same content and naming.\n- Validation in Form Requests; authorization in policies or gates; thin controllers, logic in actions or services; mass assignment protected (`$fillable`).\n- Eloquent: eager load with `with()` to avoid N+1 queries; `chunkById`/`cursor` for large sets; define relations on both sides; casts for dates and enums; scopes for repeated conditions.\n- Config values via `config()`; `env()` only inside `config/*.php`. Blade escapes with `{{ }}`; `{!! !!}` only for trusted HTML.\n- Queues for slow work (mail, exports); scheduled jobs in the scheduler. Use database transactions for multi-step writes.\n\n## Database and migrations\n- Every schema change is a migration with a working `down()`. Name tables and columns like the existing ones; add indexes and foreign keys deliberately.\n- Flow: write the migration, `laravel.migrate-status`, then **`laravel.migrate-pretend`** (shows the SQL, nothing runs) and show the user, and only if asked `laravel.migrate` (asks; blocked on prod). Never edit a migration that already ran elsewhere: add a new one.\n- Database login for `.env`: write `DB_PASSWORD={{secret:name}}` with `write_file` (the vault handle) and Hexa puts the real value in the file after the user approves; never ask the user to paste the password into the chat. To look at data, `mysql.query` with the same handle.\n\n## Checks (run them, report them)\nAfter PHP edits Hexa runs `php -l` on each changed file. Then run, as far as installed: `laravel.pint-check` (style), `check.phpstan` with `target` (analysis), `laravel.test` (tests; asks). Add or update a test for new behaviour: feature tests call the route and assert the response and database state (`RefreshDatabase`, factories); unit tests for plain logic. Say plainly which of these you ran and which you could not.\n\n## Authentication\nUse the starter kit the project already has (Breeze, Jetstream, Fortify) or Sanctum for APIs; do not hand-roll password hashing or sessions. `Hash::make`, throttle login routes, `auth` middleware on protected routes, authorize with policies. Check the installed package versions before copying examples.\n\n## Security and operations\nCSRF on state-changing forms (`@csrf`); never build SQL by string concatenation; validate uploads (type, size) and store them outside `public` unless meant to be public; `APP_DEBUG=false` and a real `APP_KEY` outside local development; `php artisan config:cache` and `route:cache` in production deployments.\n\n## Dependencies\n`deps.composer-install` installs from `composer.lock` (asks). Do not run `composer update` or add packages without the user asking; say which package and why, and read its docs for the version.\n"
 }
}
