D
D
d6core2021-10-17 18:22:24
1C-Bitrix
d6core, 2021-10-17 18:22:24

How do you make AJAX architectural decisions?

There is a table with a list of orders of the form

Order number | Name of the customer | Product name | Date |

This table, for example, is displayed by the bitrix component, from the database or via the REST API, it does not matter.

<div id="#orders-block">
 $APPLICATION->IncludeComponent(
        "d6core:custom.order.list",
        "orders_list",
        Array(
           'PARAMS' => $date,
        ),

    );
</div>


To the right of the table is a filter, with fields full name, date, etc. for filtering. It can be a regular form + jquery with serialize and ajax request. Or is it a reactive component that is written in React, Vue or Svelte, which also collects data and makes a post request.

On the js side, there is always something like this (filter handler, which is to the right of the table)
$("#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);
            });
        });


Next, a file is created in the ajax folder, for example, orders_list, where the component is connected.

<?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'
    ]);


}


Helper
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;
    }
}


This solution works, BUT I'm interested in a number of questions:
How acceptable is this solution?
Are there any more correct, flexible architectural solutions? If so, which ones, the more options, the better :)

Of course, information security issues are also of interest here. Here I used my helper, where the data filtering and JSON response functions are stupidly within BitrixFW. I just noticed in the code of even apparently experienced developers that there is no data filtering...

There are also questions about BitrixFW itself. Again, when you work within the framework of some kind of framework, then in theory it is desirable to use what is under its hood, maybe then you don’t need to write any function clean. There are methods like $request->getPost('data');.
I did some digging in the kernel but didn't find out of the box filtering in getPost. Then the question is, why do such a wrapper if I can stupidly pull data from $_POST directly?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Andrey Nikolaev, 2021-10-21
@d6core

To what extent is such a decision acceptable?

Estimates vary depending on the project and time allocated.
I would rate it as "Unsatisfactory, marginally acceptable, but decisive for the original request".
Your approach may exist, however, at Code review, we would wrap it up with the mark "Redo everything".
Are there any more correct, flexible architectural solutions?

Options for taste and color, starting from the native AJAX => 'Y' parameter in the component and its operation, and ending with javascript rendering.
A great option would be:
- To have the #orders-block tag render the d6core:custom.order.list component. Those. he would be self-sufficient.
- A separate page would not be created under "ajax.php", but the controllers of the components would be used (at least)
- As little data as possible would be returned, i.e. data structures, not layout.
Of course, IS issues are also of interest here.

By default, component controllers are protected from CSRF, and you can also set checks for authorization (only from authorized users), check for the request method (POST / GET), check for the user (pass it to signedParams).
Read about controllers, a lot of interesting things are written there.
Then the question is, why do such a wrapper if I can stupidly pull data from $_POST directly?

For example, because when processing a request, the global $_POST can change any script that executes before yours, and HttpRequest contains the original information that was sent to the server.
Or because when accessing a non-existent $_POST key, a notice message is issued, and HttpRequest correctly returns null.
If your function or method works with $_POST, then in the case of an object you can specify what HttpRequest is expected and know that the request parameters will come and that there will be guaranteed getPost methods, etc., and in the case of $_POST you can be sent there anything with any keys.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question