arrilot/bitrix-hermitage
Bitrix Hermitage is a lightweight toolkit for building 1C-Bitrix components in a cleaner, object-oriented style. It helps separate component logic from templates and organize code while staying compatible with Bitrix conventions.
Hermitage is a thin OOP page/controller layer for 1C-Bitrix — think "Laravel controllers and views, but the framework underneath is Bitrix." If you're coming from Laravel, map it mentally as: a page class ≈ an invokable controller, a Hermitage view ≈ a Blade template (plain PHP, no Blade syntax), and urlrewrite.php ≈ routes/web.php.
Minimal setup:
composer require arrilot/bitrix-hermitage (the package is archived and its last release is from March 2018 — pin the version and be prepared to vendor-fork it if you hit PHP 8 issues).vendor/autoload.php from /local/php_interface/init.php./local that maps a URL pattern or a symbolic page code to a page class./urlrewrite.php (or 404.php/a front controller) so that a request matching your rule instantiates the page class instead of executing a plain PHP file.First real use case: take one existing procedural page in the site root (say catalog/index.php) that is a soup of $APPLICATION->SetTitle(), component includes, and inline HTML, and port it to a single page class with a handle()-style method plus a view. Don't migrate the whole site — pick one page, get the dispatch path working end to end, then expand.
Where to look first: the package's README and its base page class (that's the contract you'll subclass), then your project's urlrewrite.php and /local/php_interface/init.php, since 90% of integration bugs live at that seam.
Page-as-class, one class per route. Each page class owns its data fetching, its Bitrix calls ($APPLICATION->SetTitle, SetPageProperty, breadcrumbs), and its view. This is the biggest win over procedural Bitrix: the page's inputs, outputs, and side effects are in one readable unit instead of scattered across include files.
Views as dumb templates. Keep Bitrix component calls ($APPLICATION->IncludeComponent(...)) in the view where they're markup-shaped, and keep querying/business logic in the page class. Pass data into the view explicitly rather than relying on globals bleeding through — this is the habit that makes the code testable later.
Layered adoption. Hermitage is best used as an outer shell over legacy Bitrix. New pages are full page classes; legacy pages stay as-is behind separate urlrewrite rules. You can also have a page class delegate to an existing IncludeComponent call for a subsystem you don't want to rewrite yet — that gives you a gradual migration path without a big-bang.
AJAX / JSON endpoints. The same page-class pattern is handy for AJAX handlers: a class that reads $_REQUEST, validates, returns JSON, and sets the correct content type. Centralizing this avoids the classic Bitrix problem of dozens of ad-hoc ajax.php files with inconsistent error handling.
Shared behavior via a base class. Put cross-cutting concerns — auth checks, layout selection, common view variables, redirect helpers — in one project-level abstract page class that all your pages extend. That's the closest analog to Laravel middleware, and it's the main extension point you'll actually use.
Composition over inheritance for reusable chunks. For repeated page fragments prefer view partials or plain helper classes rather than deep page-class hierarchies; Bitrix's own component system already covers the "reusable widget" niche, so don't rebuild it.
create_function-era patterns, deprecated notices). Audit before adopting on a new project; on an existing one, isolate it behind your own base class so you can replace it.urlrewrite.php is cached. Bitrix caches the rewrite rules; after editing them, clear the managed cache (/bitrix/admin/cache.php or $GLOBALS['CACHE_MANAGER']->cleanAll()). A "my route doesn't work" report is usually a stale rewrite cache, not a code bug.$USER, $APPLICATION, and $DB are process-wide globals. Code that's clean in a Laravel request lifecycle can leak here — especially if you test multiple pages in one PHP process, or under Bitrix's CLI/agent runners. Prefer passing dependencies in over reading globals deep inside helper methods.debug in .settings.php / dbconn.php ('debug' => true, exception handling off) — otherwise a bug in a page class looks identical to a 404.arrilot/bitrix-test (same author, also stale) is the pragmatic option for unit-testing page classes; without it, keep page classes free of direct global access so they're at least testable in isolation.vendor/ — fork it into a local path repository instead so updates (if any ever land) don't clobber you.How can I help you explore Laravel packages today?