PHP使用Slim处理来自Actions的AJAX

2022-06-13 00:00:00 php ajax slim

我有一个关于php和带有超薄框架的AJAX的问题

我创建了一些路由将我路由到一个控制器,现在我想用AJAX提交一个简单的表单。这可以很好地工作,但问题是,如果我要在没有AJAX的情况下提交表单,我会向服务器发送POST请求,这将调用控制器中的createAction而不是form renderAction方法(请参见代码)。 但我需要调用formRender,因为当表单无效时,我必须再次向用户显示具有值的表单。

注意:我尚未实现任何验证代码。

这里是我提交表单的JS代码:

 $('#reservation').on('submit', function (ev) {
        ev.preventDefault();
        var data = $(this).serialize();
        var keyVal = data.split("&");
        var values = [];
        keyVal.forEach(function (element) {
            values[element.split("=")[0]] = element.split("=")[1];
        });
        $.post("/admin/reservation/create", data).done(function (data) {
            console.log(data);
        }).error(function (err) {

        });
    });

这里是我的控制器的代码:

 public function formRender(Request $request, Response $response)
{
    $formData = $request->getParams();
    return $this->view->render($response, '/reservations/form.twig', [
        'formData' => $formData]);
}


public function createAction(Request $request, Response $response)
{
    $formData = $request->getParams();
    $response = $response->withJson($formData);
    return $response;
}

我的路线:

    $app->get('/reservation/create', 'ReservationController:formRender');
    $app->post('/reservation/create', 'ReservationController:createAction');

这里是视图代码(使用twig):

 <form class="col s6" id="reservation" method="post">
        <div class="row">
            <div class="input-field col s6">
                <input placeholder="Titel" id="title" name="title" type="text" class="validate"
                       value="{{ formData.title }}">
                <label for="title">Titel</label>
            </div>
            <div class="input-field col s12 m6">
                <select class="icons" multiple>
                    <option value="" disabled selected>Choose Rooms</option>
                    <option value="" data-icon="images/sample-1.jpg" class="circle">example 1</option>
                    <option value="" data-icon="images/office.jpg" class="circle">example 2</option>
                    <option value="" data-icon="images/yuna.jpg" class="circle">example 1</option>
                </select>
                <label>Rooms</label>
            </div>
        </div>
        <div class="row">
            <div class="input-field col s6">
                <input value="{{ formData.startDate }}" id="startDate" name="startDate" type="date" class="validate">
            </div>
            <div class="input-field col s6">
                <input value="{{ formData.endDate }}" id="endDate" name="endDate" type="date" class="validate">
            </div>
        </div>

        <button type="submit" class="waves-effect waves-light btn">button</button>
    </form>

我该如何解决这个问题...所以我希望能够按AJAX发送数据,并且我希望能够在没有js的情况下提交我的表单。我正在寻找一个干净的解决方案..不是用隐藏的领域或其他东西快速而肮脏的修复。 针对此类情况的最佳实践是什么?


解决方案

我建议您命名您的路由来解决这个问题:

$app->get('/reservation/create', 'ReservationController:formRender')->setName('reservationFormRenderer');
$app->post('/reservation/create', 'ReservationController:createAction')->setName('reservationFormAjaxProcessor');

由于您使用的是Twig作为模板引擎,请使用path_for方法将角色注入到表单:

<form class="col s6" id="reservation" method="post" action="{{ path_for('reservationFormRenderer') }}" data-ajax-processor="{{ path_for('reservationFormAjaxProcessor') }}">

剩下的工作就是在您的JS代码中选择动态路由:

$('#reservation').on('submit', function (ev) {
    ev.preventDefault();
    var data = $(this).serialize();
    var keyVal = data.split("&");
    var values = [];
    keyVal.forEach(function (element) {
        values[element.split("=")[0]] = element.split("=")[1];
    });
    // here we pass the value of data-ajax-processor attribute of the form
    $.post(($this).data('ajax-processor'), data).done(function (data) {
        console.log(data);
    }).error(function (err) {

    });
});

现在,如果表单不是动态提交的(即ajax-way),则处理程序的URL将位于表单的action属性中。

您实际上可以在不命名路由的情况下完成此操作,但这种方式将保持代码的可维护性,因为您只需在一个地方更改实际的URL--即在路由声明中。

相关文章