viames / pair
Lightweight PHP framework for fast server-rendered web applications with MVC routing, ActiveRecord ORM and API tooling
Requires
- php: ^8.3||^8.4||^8.5
- ext-curl: *
- ext-intl: *
- ext-json: *
- ext-mbstring: *
- ext-pdo: *
- psr/log: ^1.1|^2.0|^3.0
Requires (Dev)
- phpunit/phpunit: ^12.0
Suggests
- ext-redis: *
- ext-xdebug: *
- dev-main / 4.x-dev
- v3.x-dev
- 3.0.1
- 3.0.0
- v2.x-dev
- 2.0.0
- 2.0.0-beta
- 2.0.0-alpha
- v1.x-dev
- 1.9.17
- 1.9.16
- 1.9.15
- 1.9.14
- 1.9.13
- 1.9.12
- 1.9.11
- 1.9.10
- 1.9.9
- 1.9.8
- 1.9.7
- 1.9.6
- 1.9.5
- 1.9.4
- 1.9.3
- 1.9.2
- 1.9.1
- 1.9
- 1.8.24
- 1.8.23
- 1.8.22
- 1.8.21
- 1.8.20
- 1.8.19
- 1.8.18
- 1.8.17
- 1.8.16
- 1.8.15
- 1.8.14
- 1.8.13
- 1.8.12
- 1.8.11
- 1.8.10
- 1.8.9
- 1.8.8
- 1.8.7
- 1.8.6
- 1.8.5
- 1.8.4
- 1.8.3
- 1.8.2
- 1.8.1
- 1.8
- 1.7.22
- 1.7.21
- 1.7.20
- 1.7.19
- 1.7.18
- 1.7.17
- 1.7.16
- 1.7.15
- 1.7.14
- 1.7.13
- 1.7.12
- 1.7.11
- 1.7.10
- 1.7.9
- 1.7.8
- 1.7.7
- 1.7.6
- 1.7.5
- 1.7.4
- 1.7.3
- 1.7.2
- 1.7.1
- 1.7.0
- 1.6.9
- 1.6.8
- 1.6.7
- 1.6.6
- 1.6.5
- 1.6.4
- 1.6.3
- 1.6.2
- 1.6.1
- 1.6.0
- 1.5.18
- 1.5.17
- 1.5.16
- 1.5.15
- 1.5.14
- 1.5.13
- 1.5.12
- 1.5.11
- 1.5.10
- 1.5.9
- 1.5.8
- 1.5.7
- 1.5.6
- 1.5.5
- 1.5.4
- 1.5.3
- 1.5.2
- 1.5.1
- 1.5.0
- 1.4.9
- 1.4.8
- 1.4.7
- 1.4.6
- 1.4.5
- 1.4.4
- 1.4.3
- 1.4.2
- 1.4.1
- 1.4.0
- 1.3.0
- 1.2.6
- 1.2.5
- 1.2.4
- 1.2.3
- 1.2.2
- 1.2.1
- 1.2.0
- 1.1.0
- 1.0.0
This package is auto-updated.
Last update: 2026-04-25 09:55:22 UTC
README
Lightweight PHP framework for fast server-rendered web applications.
Website · Wiki · Boilerplate · Issues · Releases · Security
Pair is a lightweight PHP framework for server-rendered web applications. It focuses on fast setup, clear MVC routing, practical ActiveRecord-style ORM features, API tooling, progressive enhancement and optional integrations without heavy tooling.
Pair is designed for small and medium web applications where you want a clear PHP/MySQL stack, server-rendered pages, useful defaults, low operational overhead and a framework that remains easy to inspect, extend and maintain.
Version status
| Line | Status | Recommended use |
|---|---|---|
| Pair v3 | Stable | Production applications |
| Pair v4 | Alpha / development | New architecture testing, migration work and early adopters |
Pair v3 is the current stable release line. Pair v4 is under active development on main and may include breaking changes while the next major version is being finalized.
Quick start
1. Install Pair stable
composer require viames/pair:^3.0
Or simply:
composer require viames/pair
2. Bootstrap the application
<?php use Pair\Core\Application; require __DIR__ . '/vendor/autoload.php'; $app = Application::getInstance(); $app->run();
3. Start from the boilerplate
For a ready-to-use application structure, start from:
https://github.com/viames/pair_boilerplate
Why Pair
- Server-rendered web applications without a heavy frontend build chain.
- MVC routing with clear module/action conventions.
- ActiveRecord-style ORM with practical type casting and relation helpers.
- API tooling for CRUD resources and OpenAPI-oriented contracts.
- PairUI helpers for progressive enhancement.
- PWA, push and passkey helpers without forcing a SPA architecture.
- Runtime extensions for optional integrations.
- Installable package architecture for modules, templates, providers and custom package records.
- Useful defaults for timezone, logging, debugging and framework utilities.
- Small enough to understand, extend and maintain.
Core features
Routing and MVC
Default route format after the base path:
/<module>/<action>/<params...>
Example:
example.com/user/login
Typical legacy MVC module structure:
/modules/user/controller.php /modules/user/model.php /modules/user/viewLogin.php /modules/user/layouts/login.php
In Pair v4, legacy Pair\Core\Controller and Pair\Core\View remain available as migration bridges, but new modules should prefer explicit controllers and responses.
Docs: Router
ActiveRecord ORM
Pair maps PHP classes to database tables and supports practical ORM features such as:
- automatic casts for
int,bool,DateTime,floatandcsv - relation helpers
- query helpers
- cache-oriented access patterns
- database-backed CRUD resources
Docs: ActiveRecord
Pair v4 explicit controller path
Pair v4 prefers explicit responses over hidden controller/view bootstrapping.
<?php use Pair\Web\Controller; use Pair\Web\PageResponse; final class UserController extends Controller { public function defaultAction(): PageResponse { $state = new class ('Hello Pair v4') { public function __construct(public string $message) {} }; return $this->page('default', $state, 'User'); } }
Minimal layout example:
<main class="user-page"> <h1><?= htmlspecialchars($state->message, ENT_QUOTES, 'UTF-8') ?></h1> </main>
For reusable output contracts, Pair v4 prefers ReadModel objects built explicitly from persistence records.
API and OpenAPI tooling
Pair includes API helpers for CRUD-oriented resources and explicit response contracts. In Pair v4, OpenAPI generation for CRUD resources can use readModel contracts, so generated response schemas describe the public output model instead of leaking persistence classes.
Useful docs:
Log bar and debugging
Pair includes a built-in log bar for development and diagnostics:
- loaded objects
- memory usage
- timings
- SQL traces
- backtraces
- custom debug messages
Frontend helpers
PairUI
PairUI is a dependency-free helper for progressive enhancement in server-rendered applications.
Main directives:
data-text,data-html,data-show,data-ifdata-class,data-attr,data-prop,data-styledata-model,data-on,data-each
Docs: PairUI.js
PWA helpers
Available assets:
PairUI.jsPairPWA.jsPairSW.jsPairRouter.jsPairSkeleton.jsPairDevice.jsPairPasskey.js
Minimal frontend setup:
<script src="/assets/PairUI.js" defer></script> <script src="/assets/PairPWA.js" defer></script> <script src="/assets/PairRouter.js" defer></script> <script src="/assets/PairSkeleton.js" defer></script> <script src="/assets/PairDevice.js" defer></script> <script src="/assets/PairPasskey.js" defer></script>
Important notes:
- Keep progressive enhancement.
- Service workers require HTTPS, except on localhost.
- Use a single service worker URL if you also enable push notifications.
Passkey quick start
Backend:
class ApiController extends \Pair\Api\PasskeyController {}
This enables:
POST /api/passkey/login/options
POST /api/passkey/login/verify
POST /api/passkey/register/options
POST /api/passkey/register/verify
GET /api/passkey/list
DELETE /api/passkey/revoke/{id}
Optional integrations
Pair includes optional support for services and runtime integrations such as:
- Amazon S3
- Amazon SES
- Telegram Bot API
- OneSignal
- Stripe
- Passkey/WebAuthn helpers
- Web push helpers
In Pair v4 these integrations should be exposed through Runtime Extensions and manually registered adapters. This is separate from Installable Packages, the ZIP/manifest mechanism used for modules, templates, providers and custom package records.
Configuration reference: Configuration (.env)
Pair v4 development line
To test unreleased Pair v4 development code from main:
composer require viames/pair:4.x-dev@dev
Generate Pair v4 skeletons:
vendor/bin/pair make:module orders vendor/bin/pair make:api api vendor/bin/pair make:crud order --table=orders --fields=id,customer_id,total_amount
The generator writes explicit Pair v4 files and avoids overwriting user-edited files unless --force is provided.
Additional migration and design docs:
Upgrading
If you are upgrading a Pair v3 application to Pair v4, run the upgrader in dry-run mode first.
From a Pair application that has Pair installed as a dependency:
php vendor/viames/pair/scripts/upgrade-to-v4.php --dry-run php vendor/viames/pair/scripts/upgrade-to-v4.php --write
From inside the Pair repository itself:
composer run upgrade-to-v4 -- --dry-run composer run upgrade-to-v4 -- --write
The upgrader is conservative by design. It rewrites low-risk patterns automatically and reports legacy controller/view flows that still require manual migration.
Requirements
| Software | Minimum | Recommended | Notes |
|---|---|---|---|
| PHP | 8.3 | 8.4 / 8.5 | Required by Composer |
| Apache | 2.4 | 2.4+ | mod_rewrite recommended |
| MySQL | 8.0 | 8.0+ | utf8mb4, utf8mb4_unicode_ci, InnoDB |
| Composer | 2.x | Latest stable | Required for package installation |
Required PHP extensions:
curlintljsonmbstringpdopdo_mysql
Recommended or optional extensions:
fileinfofor reliable MIME detection in uploadsopensslfor Passkey/WebAuthn featuresredisfor Redis-backed integrationsxdebugfor development and debugging
Example project
Start from the boilerplate project to bootstrap a new application quickly:
https://github.com/viames/pair_boilerplate
Documentation
Main documentation lives in the Wiki:
https://github.com/viames/pair/wiki
Useful pages:
- Application
- Router
- Controller
- View
- ActiveRecord
- ApiExposable
- CrudController
- Form
- Collection
- Push notifications
- PairUI.js
- Configuration (.env)
- index.php
- .htaccess
- Classes folder
Development
Install dependencies:
composer install
Run tests:
composer test
Run the v4 benchmark harness:
composer run benchmark-v4
The benchmark harness measures:
- minimal request bootstrap primitives
- simple server-rendered page rendering
- simple JSON endpoint payload preparation
- record-to-read-model mapping cost
- response serialization cost
Support
- Issues: github.com/viames/pair/issues
- Wiki: github.com/viames/pair/wiki
- Source: github.com/viames/pair/tree/main/src
- Homepage: viames.github.io/pair
- Packagist: packagist.org/packages/viames/pair
Changelog
Version history is available in GitHub Releases:
https://github.com/viames/pair/releases
Security
If you discover a security issue, follow the private reporting guidance in SECURITY.md.
Contributing
Feedback, code contributions and documentation improvements are welcome via pull request.
License
MIT