php
Use when building PHP applications with Laravel — models and migrations on MySQL, validation, money and unit calculations, Artisan commands, Pest or PHPUnit tests, and running the stack in Docker. Als
SKILL.mdskills/languages/php/SKILL.md
GitHubPHP with Laravel
Default: the current PHP 8.x, Laravel (the mainstream framework — choose a micro-framework only with a written reason, "it is lighter" is not one), MySQL 8 or SQLite for tests, Composer, PHPUnit or Pest, Docker Compose to run everything.
Setup
composer create-project laravel/laravel appinside a PHP container, so the host needs only Docker.- Keep local settings in the environment file Laravel reads at start-up, commit only the example file without secrets, and generate
APP_KEYper environment. - Compose services:
app(php-fpm orphp artisan servefor development),db(MySQL with a named volume), optionalqueue.
Modelling
- One migration per schema change; never edit a migration that has run anywhere else — add a new one.
- Use Eloquent casts for types (
'price' => 'integer','bought_at' => 'immutable_datetime'). - Store money in integer minor units and quantities with explicit units (grams, millilitres). Convert at the edge.
- Validate input with Form Requests; keep controllers thin and put calculations in plain service classes you can unit-test.
Calculations people check by hand
For price-per-unit, discounts and point rebates:
- Compute in integers or
bcmath; floats produce off-by-one-yen style errors. - Write down the rounding rule (floor, round half up, banker's) and test the boundary cases.
- Keep the history of inputs so a result can be explained later ("previous price", "change since last time").
Testing
php artisan testwith an in-memory SQLite database (DB_CONNECTION=sqlite,DB_DATABASE=:memory:) for speed, plus a CI job against MySQL if you use MySQL-specific features.- Use factories for test data and
RefreshDatabaseto isolate tests. - Feature tests over HTTP for routes, unit tests for services.
Verification loop
composer validateandphp -lon changed files.vendor/bin/pint --test(formatting) and a static analyser (Larastan/PHPStan) at a level you keep green.php artisan test.docker compose upfrom a clean checkout to prove the setup instructions work.
Pitfalls
- Mass assignment: define
$fillable(or$guarded) on every model. - N+1 queries: eager-load relations with
with(); enableModel::preventLazyLoading()in development. - Time zones: set
APP_TIMEZONEand store UTC in the database; MySQLTIMESTAMPconverts,DATETIMEdoes not. - Strict mode in MySQL rejects invalid dates and truncation that older setups accepted; keep it on and fix the data.
- Config cache: after
php artisan config:cache,env()outside config files returns null. Read settings throughconfig(). - Composer platform: set
config.platform.phpto the production PHP version so dependency resolution matches.