Laravel 5 AJAX 排序数据(jQuery 可排序)没有 HTML 形式

Laravel 5 AJAX Sort Order data (jQuery Sortable) with no HTML form

我正在尝试使用 Laravel 5 为我的新站点的帮助中心内的每篇文章存储排序顺序,但在使其正常工作时遇到了一些麻烦。我正在使用 jQuery UI 的 .sortable 来排列页面上的元素,并且由于整个站点将有多个区域可排序,所以我的 jQuery 脚本是为了 'one script for all' 目的而构建的。因此使用 data-* 属性和路由名称引用。

这是我目前得到的代码:

routes.php

Route::post('admin/help-centre/category/{category_id}/section/{section_id}/article/sort-order', 'AdminHelpCentreArticleController@sortOrder');

AdminHelpCentreArticleController.php

public function sortOrder($category_id, $section_id)
{
    /* Return ------------------------------------- */
        return [
            'category_id' => $category_id,
            'section_id' => $section_id
        ];
}

show.blade.php(管理员文章列表)

<ul id="help-center-articles-sort" class="sortable">
    @foreach ($helpCentreArticles as $helpCentreArticle)
        <li class="sortable-element" data-sortable-element-id="{{ $helpCentreArticle->id }}">
            <a href="{{ action('AdminHelpCentreArticleController@show', array($helpCentreCategory->id, $helpCentreSection->id, $helpCentreArticle->id)) }}" target="_self">{{ $helpCentreArticle->title }}</a>
        </li>
    @endforeach
</ul>

<a href="{{ $helpCentreSection->id }}/article/sort-order" target="_self" class="button bm-remove w-full sortable-save" data-sortable-id="help-center-articles-sort">Save Order</a>

scripts.js(包括 CSRF 令牌 _token

var csrfToken = $('meta[name="csrf-token"]').attr('content');

$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
    if (options.type.toLowerCase() === 'post')
    {
        options.data += options.data?'&':''; // add leading ampersand if `data` is non-empty
        options.data += '_token=' + csrfToken; // add _token entry
    }
});

$(document).ready(function() {
    $('.sortable').sortable();

    $('.sortable-save').on('click', function(e) {
        e.preventDefault();

        var route = $(this).attr('href'),
            sortableID = $(this).attr('data-sortable-id');

        var data = $('#' + sortableID + ' .sortable-element').map(function() { 
            return $(this).attr('data-sortable-element-id');
        }).get();

        $.ajax({
            type: 'POST',
            url: route,
            dataType: 'json',
            data: { id_array: data },
            success: function(data) {
                console.log(data);
            }, error: function(data) {
                console.log(data);
            },
        });
    });
});

到目前为止一切都在控制台中的 return 响应方面正常工作,即 Object {category_id: "1", section_id: "1"}。但是无论我尝试什么,我似乎都无法通过 data 映射到控制器来使用它。

我尝试了很多猜测,因为我在 Laravel 5 中的任何地方都找不到关于 AJAX 的一个像样的教程,我已经尝试过添加 $data 之类的东西sortOrder() 方法的参数,我已经尝试了 Input::all()Request::all 但它们都是 return 错误(我猜是因为它不是实际形式?)。

一旦我获得要传递给控制器​​的数据,我就可以很容易地将排序顺序保存到数据库中。但是我还没到那个阶段,有什么想法吗?

编辑

我可能应该注意到我确实有一个 HelpCentreArticle 模型和一个 HelpCentreArticleRequest 请求,这里是每个文件中的一些代码,以备不时之需:

HelpCentreArticle.php

class HelpCentreArticle extends Model {
    protected $fillable = [
        'category_id',
        'section_id',
        'title',
        'content',
        'excerpt',
        'is_visible',
        'sort_order',
        'created_by',
        'updated_by',
    ];
}

HelpCentreArticleRequest.php

class HelpCentreArticleRequest extends Request {        

    /* Authorization ------------------------------ */
        public function authorize()
        {
            return true;
        }


    /* Validation rules --------------------------- */
        public function rules()
        {
            $rules = [
                'title' => 'required|min:3',
                'content' => 'required|min:10',
            ];

            return $rules;
        }

}

我不确定是否需要添加 HelpCentreSectionRequest $request 作为 sortOrder() 方法的最后一个参数,所以我可以使用 $request->all() 但它只是 return控制台日志中有 422 (Unprocessable Entity)

所以看起来正确的方法是使用 Input::get('id_array'); 而不是 $_POST['id_array'];,我试过了,但是当我最初尝试这个时,我没有包括 use Input;在我的控制器顶部,因为我认为这已经可以访问了,但事实并非如此。

添加 use Input; 并使用 Input::get(); 现在可以正常工作了。

这是更新后的代码:

AdminHelpCentreArticleController.php

public function sortOrder($category_id, $section_id)
{

    /* Query Select ------------------------------- */
        $helpCentreCategory = HelpCentreCategory::findOrFail($category_id);
        $helpCentreSection = HelpCentreSection::findOrFail($section_id);


    /* Variables ---------------------------------- */
        $id_array = Input::get('id_array');
        $sort_order = 1;


    /* Query Update ------------------------------- */
        foreach($id_array as $id) {
            $helpCentreArticle = HelpCentreArticle::where('id', $id)->first();

            $helpCentreArticle->sort_order = $sort_order;
            $helpCentreArticle->save();

            $sort_order++;
        }


    /* Return ------------------------------------- */
        return ['success' => true];

}

然后您显然可以访问 success 以获得 jQuery 中的 if else 语句来操作页面。

我的 UI 实现可以用 Laravel

排序

index.blade.php

...
@foreach($photos as $photo)
<tr data-sortable="{{ $photo->pivot->position }}" data-id="{{ $restaurant->id }}" data-photo-id="{{ $photo->pivot->photo_id }}">
    <td>
        <i class="fa fa-sort" aria-hidden="true"></i>
    </td>
...
</tr>
@endforeach
<script type="text/javascript">
$("#sortable-ui tbody").sortable({
    helper: fixHelper,
    update: function(event, ui) {
        $("#sortable-ui tbody tr").each(function(index){
            console.log($(this).data('id')+', '+(index+1));
            $.ajax({
                url: '{{ route('owner.photo.update.position') }}',
                type: 'POST',
                data: 'restaurant_id='+$(this).data('id')+'&photo_id='+$(this).data('photo-id')+'&position='+(index+1)
            })
            .done(function (response) {
                console.log(response);
            })
            .fail(function (jqXhr) {
                console.log(jqXhr);
            });
        });
    }
}).disableSelection();
</script>

scripts.js

$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});

AjaxController.php

public function updatePhotoPosition(Request $request)
{
    $restaurant = $this->restaurantRepository->getById($request->get('restaurant_id'));
    $photoId = $request->get('photo_id');
    $photo = $restaurant
        ->photos()
        ->wherePivot('photo_id', $photoId)
        ->first();

    $photo->pivot->position = $request->get('position');
    $photo->pivot->save();
}