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();
}
我正在尝试使用 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();
}