Этот сниппет обработчика ajax запросов я часто использую в своих проектах.
Представим себе такую задачу: необходимо реализовать CRUD (create, update, delete) операции элементов инфоблока Битрикс. При этом сами операции должны выполняться от имени такого пользователя, который:
- авторизован на сайте
- принадлежит определённой группе пользователей
Операции должны инициироваться POST обращением по Ajax к определённому скрипту (обработчику аякс запроса)
Решение
С одной стороны можно нагородить отдельные php скрипты-обработчики вида
- create.php
- update.php
- delete.php
Но в этом случае мы столкнёмся с дублированием кода в каждом скрипте, т.к. помимо самой операции нужно:
- проверять, авторизован ли пользователь
- проверить, принадлежит ли он той группе пользователей, которая требуется
- как-то сообщать юзеру, что операция выполнена с ошибкой, если таковая появится
Именно поэтому вместо такой реализации можно применить следующую идею — реализовать единый обработчик, который на входе будет принимать:
- идентификатор метода (требуемой операции)
- значения параметров, необходимых для выполнения операции
На выходе — массив данных, состоящий из двух элементов:
header('Content-Type: application/json');
require_once($_SERVER['DOCUMENT_ROOT'] . "/bitrix/modules/main/include/prolog_before.php");
//ID инфоблока с которым работаем
protected $iblock_id = 56;
protected $user_group = 36;
//текстовая информация по умолчанию на выходе - пустая
//ошибка выполнения операции по умолчания - есть. её текстовая расшифровка - пустая
protected $error = ['status' => true, 'error_text'=>''];
//если требуемый метод присутствует в нашем классе
if (method_exists($this, $_POST['method'])){
//проверяем, авторизован ли пользователь и принадлежит ли он требуемой группе пользователей
if ($USER->IsAuthorized() && in_array($this->user_group, $USER->GetUserGroupArray())){
//подключаем модуль работы с инфоблоками
CModule::IncludeModule("iblock");
//преобразовываем спец. символы в HTML сущности для защиты от SQL инъекций
if (is_array($_POST['data'])){
foreach ($_POST['data'] as $key=>$value) {
$operation_data[htmlspecialcharsbx($key)] = htmlspecialcharsbx($value);
$method = (string)$_POST['method'];
//вызываем метод c HTML безопасным представлением данных для выполнения операции
$this->$method($operation_data);
//если пользователь не авторизован или не принадлежит нужной группе пользователей
$this->error['error_text'] = 'Пожалуйста, авторизуйтесь под своей учетной записью.';
//если вызвали несуществующий метод
$this->error['error_text'] = "Метод ".$_POST['method']." отсутствует в классе CRUD_IBlock";
//отпрвляем JSON с данными
echo json_encode(['data'=>$this->data, 'error'=>$this->error]);
protected function Create($operation_data){
// создаём элемент. данные для создания берём из массива $operation_data
// успешность создания элемента записываем в $result
$this->error['status'] = false;
$this->data = 'Элемент успешно создан';
$this->error['message'] = 'Описание причины невозможности создать элемент';
protected function Update($operation_data){
// обновляем элемент. данные для обновления берём из массива $operation_data
// успешность обновленния элемента записываем в $result
$this->error['status'] = false;
$this->data = 'Элемент успешно обновлен';
$this->error['message'] = 'Описание причины невозможности обновить элемент';
protected function Delete($operation_data){
// удаляем элемент. данные для удаления берём из массива $operation_data
// успешность удаления элемента записываем в $result
$this->error['status'] = false;
$this->data = 'Элемент успешно удален';
$this->error['message'] = 'Описание причины невозможности удалить элемент';
$crud = new CRUD_IBlock();
<?php
header('Content-Type: application/json');
require_once($_SERVER['DOCUMENT_ROOT'] . "/bitrix/modules/main/include/prolog_before.php");
class CRUD_IBlock {
//ID инфоблока с которым работаем
protected $iblock_id = 56;
//ID группы пользователя
protected $user_group = 36;
//текстовая информация по умолчанию на выходе - пустая
protected $data = '';
//ошибка выполнения операции по умолчания - есть. её текстовая расшифровка - пустая
protected $error = ['status' => true, 'error_text'=>''];
function __construct() {
//если требуемый метод присутствует в нашем классе
if (method_exists($this, $_POST['method'])){
global $USER;
//проверяем, авторизован ли пользователь и принадлежит ли он требуемой группе пользователей
if ($USER->IsAuthorized() && in_array($this->user_group, $USER->GetUserGroupArray())){
//подключаем модуль работы с инфоблоками
CModule::IncludeModule("iblock");
//преобразовываем спец. символы в HTML сущности для защиты от SQL инъекций
$operation_data = [];
if (is_array($_POST['data'])){
foreach ($_POST['data'] as $key=>$value) {
$operation_data[htmlspecialcharsbx($key)] = htmlspecialcharsbx($value);
}
}
$method = (string)$_POST['method'];
//вызываем метод c HTML безопасным представлением данных для выполнения операции
$this->$method($operation_data);
} else {
//если пользователь не авторизован или не принадлежит нужной группе пользователей
$this->error['error_text'] = 'Пожалуйста, авторизуйтесь под своей учетной записью.';
}
} else {
//если вызвали несуществующий метод
$this->error['error_text'] = "Метод ".$_POST['method']." отсутствует в классе CRUD_IBlock";
}
//отпрвляем JSON с данными
echo json_encode(['data'=>$this->data, 'error'=>$this->error]);
}
protected function Create($operation_data){
// создаём элемент. данные для создания берём из массива $operation_data
// ...
// успешность создания элемента записываем в $result
if ($result){
$this->error['status'] = false;
$this->data = 'Элемент успешно создан';
} else {
$this->error['message'] = 'Описание причины невозможности создать элемент';
}
}
protected function Update($operation_data){
// обновляем элемент. данные для обновления берём из массива $operation_data
// ...
// успешность обновленния элемента записываем в $result
if ($result){
$this->error['status'] = false;
$this->data = 'Элемент успешно обновлен';
} else {
$this->error['message'] = 'Описание причины невозможности обновить элемент';
}
}
protected function Delete($operation_data){
// удаляем элемент. данные для удаления берём из массива $operation_data
// ...
// успешность удаления элемента записываем в $result
if ($result){
$this->error['status'] = false;
$this->data = 'Элемент успешно удален';
} else {
$this->error['message'] = 'Описание причины невозможности удалить элемент';
}
}
}
$crud = new CRUD_IBlock();
<?php
header('Content-Type: application/json');
require_once($_SERVER['DOCUMENT_ROOT'] . "/bitrix/modules/main/include/prolog_before.php");
class CRUD_IBlock {
//ID инфоблока с которым работаем
protected $iblock_id = 56;
//ID группы пользователя
protected $user_group = 36;
//текстовая информация по умолчанию на выходе - пустая
protected $data = '';
//ошибка выполнения операции по умолчания - есть. её текстовая расшифровка - пустая
protected $error = ['status' => true, 'error_text'=>''];
function __construct() {
//если требуемый метод присутствует в нашем классе
if (method_exists($this, $_POST['method'])){
global $USER;
//проверяем, авторизован ли пользователь и принадлежит ли он требуемой группе пользователей
if ($USER->IsAuthorized() && in_array($this->user_group, $USER->GetUserGroupArray())){
//подключаем модуль работы с инфоблоками
CModule::IncludeModule("iblock");
//преобразовываем спец. символы в HTML сущности для защиты от SQL инъекций
$operation_data = [];
if (is_array($_POST['data'])){
foreach ($_POST['data'] as $key=>$value) {
$operation_data[htmlspecialcharsbx($key)] = htmlspecialcharsbx($value);
}
}
$method = (string)$_POST['method'];
//вызываем метод c HTML безопасным представлением данных для выполнения операции
$this->$method($operation_data);
} else {
//если пользователь не авторизован или не принадлежит нужной группе пользователей
$this->error['error_text'] = 'Пожалуйста, авторизуйтесь под своей учетной записью.';
}
} else {
//если вызвали несуществующий метод
$this->error['error_text'] = "Метод ".$_POST['method']." отсутствует в классе CRUD_IBlock";
}
//отпрвляем JSON с данными
echo json_encode(['data'=>$this->data, 'error'=>$this->error]);
}
protected function Create($operation_data){
// создаём элемент. данные для создания берём из массива $operation_data
// ...
// успешность создания элемента записываем в $result
if ($result){
$this->error['status'] = false;
$this->data = 'Элемент успешно создан';
} else {
$this->error['message'] = 'Описание причины невозможности создать элемент';
}
}
protected function Update($operation_data){
// обновляем элемент. данные для обновления берём из массива $operation_data
// ...
// успешность обновленния элемента записываем в $result
if ($result){
$this->error['status'] = false;
$this->data = 'Элемент успешно обновлен';
} else {
$this->error['message'] = 'Описание причины невозможности обновить элемент';
}
}
protected function Delete($operation_data){
// удаляем элемент. данные для удаления берём из массива $operation_data
// ...
// успешность удаления элемента записываем в $result
if ($result){
$this->error['status'] = false;
$this->data = 'Элемент успешно удален';
} else {
$this->error['message'] = 'Описание причины невозможности удалить элемент';
}
}
}
$crud = new CRUD_IBlock();
Если оперировать вышеприведённым кодом, то на вход подаём:
- method: название метода необходимой операции
- data: данные, требуемые для выполнения операции
На выходе получаем:
- data: мета данные после успешного выполнения операции
- error: массив из двух элементов — первый с ключем status: есть ли ошибка, второй с ключем message: текстовая расшифровка ошибки
Как пользоваться
Если использовать JQuery ajax запрос, то его примерный общий вид будет следующий:
//какие-то данные для выполнения операции
method: 'название_метода',
success: function(result){
//операция выполнена успешно
if (!result.error.status){
//мета данные в результате успешного выполнения операции
console.log (result.data);
//операция выполнена с ошибкой
console.log (result.error.message);
let data = {
//какие-то данные для выполнения операции
};
$.ajax({
url:'url_обработчика',
type:"POST",
dataType: 'json',
data: {
method: 'название_метода',
data: data
},
success: function(result){
//операция выполнена успешно
if (!result.error.status){
//мета данные в результате успешного выполнения операции
console.log (result.data);
}
//операция выполнена с ошибкой
else {
//расшифровка ошибки
console.log (result.error.message);
}
}
})
let data = {
//какие-то данные для выполнения операции
};
$.ajax({
url:'url_обработчика',
type:"POST",
dataType: 'json',
data: {
method: 'название_метода',
data: data
},
success: function(result){
//операция выполнена успешно
if (!result.error.status){
//мета данные в результате успешного выполнения операции
console.log (result.data);
}
//операция выполнена с ошибкой
else {
//расшифровка ошибки
console.log (result.error.message);
}
}
})
Собственно, вот и вся магия.