@d6core

Как вы делаете архитектурные решения AJAX?

Есть таблица со списком заказов вида

Номер заказа | ФИО заказчика | Название товара | Дата |

Эту таблицу к примеру выводит bitrix компонент, из БД или через REST API, не важно.
<div id="#orders-block">
 $APPLICATION->IncludeComponent(
        "d6core:custom.order.list",
        "orders_list",
        Array(
           'PARAMS' => $date,
        ),

    );
</div>


Справа от таблицы располагается фильтр, с полями фио, дата и тд для фильтрации. Это может быть обычная форма + jquery c serialize и ajax запросом. Или это реактивный компонент, которые написан на React, Vue или Svelte, которые тоже собирает данные и делает post запрос.

На стороне js всегда что то примерно такое (обработчик фильтра, котрый справа от таблицы)
$("#orders-filter-form").submit(function (e) {

            e.preventDefault(); 

            var form = $(this);
            var url = form.attr('action');

            $.ajax({
                type: 'POST',
                url: url,
                dataType: 'json',
                data: form.serialize(),
                beforeSend: function () {
                    $('#orders-block').html('Прелоадер....');
                },
            }).done(function (response) {
                $("#orders-block").html(response);

            }).fail(function (jqXHR, textStatus) {
                console.log(jqXHR, textStatus);
            });
        });


Далее создается файлик в папке ajax, например orders_list, где идет подключение компонента.

<?php require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php");

use Bitrix\Main\Context;

$request = Context::getCurrent()->getRequest();

if ($request->isPost() && $request->isAjaxRequest() && $GLOBALS['USER']->IsAuthorized()) {

    $data  = json_decode($request['data'] ,true);
    $date = Helper::clean($data['date']);

    ob_start();
    $APPLICATION->IncludeComponent(
        "d6core:custom.order.list",
        "orders_list",
        Array(
           'PARAMS' => $date,
        ),

    );
    $view = ob_get_contents();
    ob_end_clean();

    Helper::jsonResponse([
        'view' =>$view,
        'type' => 'ok'
    ]);


}


Хелпер
class Helper {

    //json ответ
    static function jsonResponse(array $result)
    {
        $response = new \Bitrix\Main\Engine\Response\Json($result);
        $response->send();
    }

    //фильтрует данные
    static function clean($value = "")
    {
        $value = trim($value);
        $value = stripslashes($value);
        $value = strip_tags($value);
        $value = htmlspecialchars($value);

        return $value;
    }
}


Такое решение работает, НО меня интересует ряд вопросов:
На сколько такое решение приемлимо?
Есть ли какие то более правильные, гибкие архитектурные решения? Если да то какие, чем больше вариантов, тем лучше:)

Конечно интересует здесь и вопросы ИБ. Здесь я использовал свой хелпер, где тупо функции фильтрации данных и ответа JSON в рамках BitrixFW. Просто замечал в коде даже вроде бы опытных разрабов, что никакой фильтрации данных нет...

Также есть вопросы и по самому BitrixFW. Опять же, когда работаешь в рамках какого то фреймворка, то по идее желательно использовать то, что у него под капотом, может тогда и никаких function clean не нужно писать. Есть же методы вроде $request->getPost('data');.
Я немного покопался в ядре, но не нашел фильтрации из коробки в getPost. Тогда вопрос, зачем делать такую обертку если я могу тупо тянуть данные из $_POST напрямую?
  • Вопрос задан
  • 989 просмотров
Решения вопроса 1
gromdron
@gromdron
Работаю с Bitrix24
На сколько такое решение приемлимо?


В зависимости от проекта и выделенного времени варьируется и оценка.
Я бы оценил его как "Неудовлетворительный, находящийся на гране допустимного, но решающий исходный запрос".
Ваш подход может существовать, однако на Code review у нас бы его завернули с пометкой "Все переделать".

Есть ли какие то более правильные, гибкие архитектурные решения?


Вариантов на вкус и цвет, начиная от родного AJAX => 'Y' параметра в компоненте и его работы и заканчивая javascript rendering.
Замечательным вариантом было бы:
- Чтобы тег #orders-block рендерил компонент d6core:custom.order.list. Т.е. он был бы самодостаточным.
- Не создавалась бы отдельная страница под "ajax.php", а использовались бы контроллеры компонентов (хотя бы)
- Возвращалось как можно меньше данных, т.е. структуры данных, а не верстка.

Конечно интересует здесь и вопросы ИБ.


Контроллеры компонентов по-умолчанию имеют защиту от CSRF, а так же можно установить проверки на авторизацию (только от авторизованных пользователей), проверку на метод запроса (POST/GET), проверку на пользователя (передавать его в signedParams).
Почитайте про контроллеры, там много интересного написано.

Тогда вопрос, зачем делать такую обертку если я могу тупо тянуть данные из $_POST напрямую?


Например потому что при обработке запроса глобальный $_POST может поменять любой скрипт выполняющий до вашего, а HttpRequest содержит исходную информацию которая была отправлена на сервер.
Или потому что при обращении к несуществующему ключу $_POST выдается notice-сообщение, а HttpRequest корректно возвращает null.
Если ваша функция или метод работает с $_POST, то в случае объекта вы можете указать что ожидается HttpRequest и знать что придет именно параметры запроса и что там будут гарантированно методы getPost и т.п., а в случае с $_POST вам могут направить туда что угодно с какими угодно ключами.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы