Installation
This page gets you from "nothing installed" to a running Lift app you can curl.
1. Check prerequisites
You need PHP 8.1 or newer and Composer.
php -v # must be ≥ 8.1
composer -V # any recent version
If php -v shows 7.x, install PHP 8.1+ first:
- Ubuntu/Debian:
sudo apt install php8.3-cli php8.3-curl php8.3-mbstring - macOS (Homebrew):
brew install php - Windows: download from windows.php.net
Recommended PHP extensions (none are strictly required, but you'll want them):
| Extension | Needed for |
|---|---|
ext-curl |
HTTP client |
ext-mbstring |
UTF-8 string handling, JWT signing |
ext-pdo + ext-pdo_mysql / ext-pdo_pgsql / ext-pdo_sqlite |
Database |
ext-redis |
RedisCache, RedisQueue, RedisSessionStore |
ext-pcntl |
Graceful queue worker shutdown |
ext-opcache |
Production performance (huge speedup) |
2. Create the project
mkdir my-app
cd my-app
composer init --name="me/my-app" --type=project --no-interaction
composer require malinichevvv/lift-php
That's the only dependency. Lift pulls in the small PSR interface packages it needs (psr/http-message, psr/container, etc.) automatically.
3. Lay out the files
Lift doesn't enforce any structure, but this is the smallest layout that's also production-ready:
my-app/
├── composer.json
├── composer.lock
├── vendor/ (created by composer)
├── public/
│ └── index.php ← single entry point, the only PHP file the web server serves
├── src/ ← your classes (controllers, services, …)
├── views/ ← optional, if you use templates
├── storage/ ← runtime files (logs, cache, sessions)
└── .env ← optional, environment-specific config
Create public/index.php:
<?php
declare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use Lift\App;
use Lift\Http\Response;
$app = new App();
$app->get('/', fn() => Response::json([
'status' => 'ok',
'time' => date('c'),
'php' => PHP_VERSION,
]));
$app->run();
4. Verify it works
php -S 127.0.0.1:8000 -t public
In another terminal:
curl http://127.0.0.1:8000/
# {"status":"ok","time":"2025-...","php":"8.3.6"}
If you see JSON — Lift is installed and running. 🎉
5. Configure your real web server
The PHP built-in server is fine for development. For production you'll want PHP-FPM behind Nginx or Apache.
Nginx + PHP-FPM
server {
listen 80;
server_name example.com;
root /var/www/my-app/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Static assets: serve directly, with long cache
location ~* \.(css|js|svg|png|jpg|jpeg|gif|woff2?)$ {
expires 30d;
access_log off;
}
}
Apache
/var/www/my-app/public/.htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]
</IfModule>
Make sure AllowOverride All is set for that directory in your vhost.
Caddy (zero-config alternative)
example.com {
root * /var/www/my-app/public
php_fastcgi unix//run/php/php8.3-fpm.sock
file_server
encode gzip
}
6. Enable OPcache in production
This single change roughly doubles request throughput. Add to php.ini (or a drop-in file in /etc/php/8.3/fpm/conf.d/):
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0 ; production only — flush manually on deploy
opcache.save_comments=1 ; required for #[Route] attribute routing
opcache.jit=tracing
opcache.jit_buffer_size=64M
After enabling, restart PHP-FPM (sudo systemctl restart php8.3-fpm).
7. (Optional) Environment file
For 12-factor config, drop a .env next to your project root:
APP_ENV=local
APP_DEBUG=true
APP_KEY=base64:GENERATE_ME_LATER
DB_DSN="mysql:host=127.0.0.1;dbname=myapp;charset=utf8mb4"
DB_USER=root
DB_PASS=secret
Load it in public/index.php before instantiating the app:
$app = new App();
$app->loadEnv(__DIR__ . '/../.env');
Then anywhere in your code:
use Lift\Config\Env;
$debug = Env::bool('APP_DEBUG', false);
$dsn = Env::string('DB_DSN');
8. (Optional) Use the lift CLI
The lift binary is installed by Composer to vendor/bin/lift. It scaffolds boilerplate and runs queue workers / migrations:
vendor/bin/lift make:controller UserController
vendor/bin/lift make:request StoreUserRequest
vendor/bin/lift make:model User
vendor/bin/lift queue:work
vendor/bin/lift migrate
Full list: Console (CLI).
Common installation gotchas
- ❌
Class "Lift\App" not found→ you forgotrequire '.../vendor/autoload.php'at the top ofindex.php. - ❌
SyntaxError: unexpected token "fn"→ your PHP is older than 7.4 (Lift requires 8.1+). Runphp -vto confirm. - ❌ 404 for every route except
/→ your web server isn't rewriting URLs toindex.php. Re-check the Nginx/Apache config above. - ❌
composer require malinichevvv/lift-phpsays "Could not find package" → if you're trying a not-yet-released version, install from path or VCS:composer config repositories.lift path /path/to/lift composer require malinichevvv/lift-php:@dev
Next steps
You now have a running app. Time to make it do something.