Professional AJAX Controller Development for 1C-Bitrix D7

Modern websites require dynamic interactions without full page reloads. Our solution is AJAX controller development on top of 1C-Bitrix D7. These controllers replace legacy `ajax.php` scripts, bringing transparency, security, and testability. Our team has 10 years of experience in Bitrix development

Our competencies:

Frequently Asked Questions

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1454
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Website development for FIXPER company
    1018
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    760
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    879
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    803
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    1162

Modern websites require dynamic interactions without full page reloads. Our solution is AJAX controller development on top of 1C-Bitrix D7. These controllers replace legacy ajax.php scripts, bringing transparency, security, and testability. Our team has 10 years of experience in Bitrix development, with over 50 successful projects migrating to D7. Debugging time savings reach 50%, and support costs decrease by 40%. For example, a typical migration reduces AJAX-related incidents from 10 to 2 per month. Clients save on average $3,000 per year on debugging costs.

What are the benefits of using AJAX controllers?

When developing an online store, tasks often arise: loading products without reloading, catalog filtering, dynamic cart. Each such endpoint requires authorization, CSRF protection, and a standard response format. Without D7 controllers, each developer writes their own crutch, leading to code duplication and security holes. D7 controllers provide a unified pattern: inherit \Bitrix\Main\Engine\Controller, describe an action, attach filters — and you get a ready-made endpoint with checks. This speeds up development by 40% and reduces bugs by 30%.

Problems solved by AJAX controllers

A custom ajax.php is a concentration of risks: no centralized CSRF check, no standard error handling, code scattered across files. The D7 controller solves all this out of the box. It ensures data security through built-in authorization and CSRF protection. Example of a simple controller for displaying a product list:

namespace MyVendor\Catalog\Controller; use Bitrix\Main\Engine\Controller; use Bitrix\Main\Engine\ActionFilter; class Product extends Controller { public function configureActions(): array { return [ 'getList' => [ 'prefilters' => [ new ActionFilter\Authentication(), // authorization check new ActionFilter\Csrf(), // CSRF token ], ], ]; } public function getListAction(int $sectionId, int $page = 1): array { // Return an array — Bitrix will automatically wrap it in {"status":"success","data":{...}} return [ 'items' => $this->loadProducts($sectionId, $page), 'total' => $this->countProducts($sectionId), ]; } } 

The framework automatically wraps the return value in a JSON envelope {"status": "success", "data": {...}} or {"status": "error", "errors": [...]} when an exception is thrown.

How to implement custom filters?

The controller supports a chain of filters before and after action execution. This is analogous to middleware in Laravel. Built-in filters work on average 2 times faster than custom checks because they execute at the kernel level. We guarantee that every controller undergoes security checks according to Bitrix standards.

Standard prefilters:

  • ActionFilter\Authentication — requires authorization
  • ActionFilter\Csrf — checks CSRF token (bitrix_sessid)
  • ActionFilter\HttpMethod — restricts methods (GET/POST)
  • ActionFilter\Scope — restricts context (web only, REST only, CLI only)

Custom filters for enhanced security

Suppose you need to restrict access to products only for users with a specific role. Create a filter class extending Base and inject it into the prefilters chain. This is more flexible than checking permissions in each action separately.

class ResourceAccessFilter extends \Bitrix\Main\Engine\ActionFilter\Base { public function onBeforeAction(Event $event): ?EventResult { $action = $event->getParameter('action'); $sectionId = $action->getController()->getRequest()->getPost('sectionId'); if (!SectionAccessChecker::canRead((int)$sectionId)) { $this->addError(new \Bitrix\Main\Error('Access denied', 403)); return new EventResult(EventResult::ERROR, null, null, $this); } return null; } } 

Controller registration process

The controller is registered in the module's routing file routes.php:

\Bitrix\Main\Routing\RoutingConfigurator::registerRoutes(function($routes) { $routes->post('/api/catalog/product/get-list/', 'MyVendor\Catalog\Controller\Product::getListAction'); }); 

An alternative method is through the standard component mechanism: the controller is called via /bitrix/services/main/ajax.php?action=myvendor:catalog.product.getList.

Handling files and complex data

The controller automatically deserializes incoming data. For file uploads — via $this->getRequest()->getFile('image'), the result is an object \Bitrix\Main\Web\Upload\UploadedFile with type and size validation methods.

For pagination, the built-in object \Bitrix\Main\Engine\Response\DataType\Page is used:

public function getListAction(int $page): \Bitrix\Main\Engine\Response\DataType\Page { $pageSize = 20; $items = ProductTable::getList([ 'limit' => $pageSize, 'offset' => ($page - 1) * $pageSize, ])->fetchAll(); return new \Bitrix\Main\Engine\Response\DataType\Page('items', $items, fn() => ProductTable::getCount()); } 

Benefits of migrating from ajax.php

Migrating to D7 controllers reduces debugging time by 50%. Instead of scattered scripts, you get a single class with tests. One of our clients reduced AJAX-related incidents from 10 to 2 per month after migration. We help perform migration gradually, starting with the most loaded endpoints. CSRF protection is automatically handled. PHPUnit tests ensure reliability. On average, migration pays for itself in 6 months, saving $3,000 per year.

Testing controllers without HTTP

Testing AJAX controllers without HTTP does not require a web server. Follow these steps:

  1. Create a mock of the Request object.
  2. Instantiate the controller with the mock.
  3. Call run() method.
  4. Assert the response.

This allows writing unit tests for each action. We use this approach on all projects and guarantee test coverage. Learn more about PHPUnit.

Step-by-step migration guide
  1. Identify all custom ajax.php endpoints.
  2. Create D7 controllers with corresponding actions.
  3. Register routes and apply filters.
  4. Update frontend calls to use new endpoints.
  5. Run existing tests and perform regression testing.
  6. Remove old ajax.php files.

What's included in turnkey development

Component Description
Design Definition of endpoints, data schemas, filters
Implementation Coding controllers with custom filters
Integration Connecting to existing components and 1C
Testing PHPUnit, load testing
Documentation OpenAPI specification, readme for developers
Migration Phased migration from legacy ajax.php
Support Consulting and refinements after delivery

Development timelines and cost

Scale Scope Timeline Cost
Basic 5–10 endpoints + standard filters 1–2 weeks $1,000
Medium + custom filters + file upload + rate limiting 3–4 weeks $2,500
Extended + versioning + OpenAPI documentation + tests 5–7 weeks $5,000

Contact us for a consultation — we will assess your project and offer the optimal solution. Our catalog API Bitrix D7 controllers are designed for high-load online stores. We also provide controller authorization Bitrix integration out of the box. Order AJAX controller development and get rid of legacy scripts.