Code Refactoring of 1C-Bitrix Project
Audit showed: init.php 3000 lines, SQL queries in templates, identical code copied in 12 components, adding new catalog field requires edits in 8 places. Refactoring — converting this chaos into maintainable codebase without changing external behavior. Key word — "without changing behavior": refactoring shouldn't break what works.
Strategy: Don't Rewrite, Replace
Full Bitrix project rewrite — trap. Business logic accumulated over years in templates and handlers, not documented. Rewriting from scratch, you'll definitely lose edge cases caught by hotfixes.
Right approach — incremental refactoring: isolate one module, rewrite it, check behavior is identical, move on. Each iteration — working site.
Refactoring Priorities
Order determined by formula: change frequency × change complexity. Files changed weekly and easy to make mistakes in — refactor first.
Priority 1: init.php Decomposition.
Typical "bad" init.php contains:
- Event handlers (
AddEventHandler) - Custom functions (formatting helpers, URL generation)
- Classes (sometimes several in one file)
- Direct initialization (connecting to external APIs on every hit)
Target state: init.php contains only autoloader require_once and handler registration. All logic — in separate classes in /local/php_interface/classes/ or /local/modules/.
Directory structure /local/:
/local/
php_interface/
init.php → autoloader + registration
classes/
EventHandlers/ → Bitrix event handlers
Helpers/ → utilities
Services/ → business logic
modules/
project.core/ → custom project module
components/ → custom components
templates/ → site templates
Migration to /local/ — standard Bitrix practice. Everything in /local/ has priority over /bitrix/, allowing core updates without conflicts.
Priority 2: Extracting Logic from Component Templates.
Component template (template.php) should contain only HTML output. If it contains CIBlockElement::GetList(), $DB->Query(), complex calculations — this is problem.
Three refactoring levels:
-
result_modifier.php — move data preparation from
template.php. Simplest step, doesn't require new component. -
class.php — creating component class inheriting
CBitrixComponent. MethodexecuteComponent()contains logic,template.php— output only. -
Custom component in
/local/components/project/— when standard Bitrix component stops meeting requirements.
Priority 3: Replace Direct SQL with D7 ORM.
Direct queries via $DB->Query() — this is:
- No escaping (SQL-injections)
- Tied to specific DBMS
- No caching via built-in mechanism
Replace with \Bitrix\Main\Entity\DataManager or minimally \Bitrix\Main\DB\Connection::query() with parameterized queries. For iblocks — use \Bitrix\Iblock\Elements\ElementXxxTable (D7 ORM for iblocks, available since core 21.x).
Priority 4: Eliminate Duplication.
Find via phpcpd (PHP Copy/Paste Detector) identical code blocks in different templates. Typical pattern: component catalog.section has 5 templates with 80% identical code, differing in CSS classes and field order. Solution: one template with parameters or include files for common blocks.
Safe Refactoring Process
| Stage | Action | Control |
|---|---|---|
| 1. Fixation | Create backup + git-commit current state | git init if project not in VCS |
| 2. Tests | Write smoke-tests on critical pages | HTTP-statuses, key elements presence |
| 3. Isolation | Move one logic block to separate class | Tests pass |
| 4. Connection | Replace old code with new class call | Tests pass |
| 5. Removal | Delete old code | Tests pass |
| 6. Deploy | Deploy to production | Monitor errors 24 hours |
Each cycle — one logical block. Don't refactor multiple things simultaneously. On production error, you must know exactly which change caused it.
Common Traps
Refactoring without VCS. Surprisingly, significant portion of Bitrix projects still not stored in Git. First refactoring step — initialize repository with correct .gitignore (exclude /bitrix/, /upload/, /vendor/, keep /local/).
D7 transition "at once". D7 API doesn't cover everything. Old API (CIBlockElement, CSale*) works and supported. Migrate to D7 only code you're refactoring — don't touch working old code for "consistency".
Refactoring without monitoring. After refactoring deploy monitor b_event_log and server logs. Errors may manifest not immediately, but under specific conditions: specific product type, certain user group, specific browser.
Timeline Estimates
| Project Scale | Typical Refactoring Scope | Timeline |
|---|---|---|
| Small (up to 50 custom files) | init.php decomposition, template cleanup | 3-5 days |
| Medium (50-200 files) | + SQL replacement, duplication elimination | 1-2 weeks |
| Large (200+ files, custom modules) | + /local/ migration, modular architecture | 3-6 weeks |
Refactoring — investment. Its effect measured not visually, but in speed of subsequent development and regression count on updates.







