我正在创建一个食物菜单,管理员可以通过拖放来订购/排序.此菜单包含多个类别(ProductCategory)和产品(Product).
我在客户端使用HTML5Sortable来允许嵌套的d&d.标记非常简单:
@foreach($categories as $category)@foreach($category->products as $product)@endforeach@endforeachid }}"> {{ $product->name }}
和相应的javascript:
$('.categories').sortable({ items: '.category' }); $('.products').sortable({ items: '.product' }); // Will be called when the user is done repositioning the products and categories function getOrderedList() { var data = {}; $('.categories').find('.category').map(function(i) { var category = $(this); data[i] = {}; data[i].id = category.data('id'); data[i].products = category.find('.product').map(function() { return $(this).data('id'); }).get(); }); data = JSON.stringify(data); // Send data to server }
该函数getOrderedList
将一个JSON字符串发送回Laravel,其中包含已排序的类别ID和产品ID:
{"0":{"id":1,"products":[2,3,1,4,5,6,7,8,9,10]},"1":{"id":2,"products":[11,12,13,14]},"2":{"id":3,"products":[15,16,17,18]}}
我如何在后端进行这项工作?我想我必须将这个数组存储在数据库的某个地方,然后通过id找到并订购模型?
简而言之:什么是分类(嵌套)模型(在Laravel中)的清晰灵活的解决方案?
常见的约定是权重,在产品表上添加一个名为(Int)Weight的字段,用于定义项目的顺序.
一旦订单发生变化,您只需更新权重字段.
检索项目时,按权重对其进行排序.
它变得类似于数组
Id Name Weight 01 'product 1' 2 02 'product 2' 0 03 'product 3' 1
当你按重量订购时,你会得到
product 2 product 3 product 1
它类似于数组,因为
$products[0] = 'product 2' $products[1] = 'product 3' $products[2] = 'product 1'
请注意,如果要使其更具动态性,可以创建一个可满足多个模型的多态模型.
请参阅https://laravel.com/docs/5.1/eloquent-relationships#many-to-many-polymorphic-relations
多态关系的例子
创建表权重(迁移示例)
$table->increments('id'); $table->integer('value'); $table->integer('weightable_id')->unsigned(); $table->string('weightable_type');
创建模型权重
class Weight extends Eloquent { public function weightable() { return $this->morphTo(); } }
现在与任何其他模型
class Products extends Eloquent { ... public function weight() { return $this->morphOne(Weight::class); } }
这样您就可以将该方法添加到您想要的任何模型中,然后您可以使用它对模型进行排序.
PS确保使用它的任何模型在创建模型后立即创建该关系
我不建议使用这种方法,如果你在Products表中明确定义权重字段会更好,我知道你希望你的代码有多大动态,但是一切都需要付出代价
性能下降,一旦建立多态关系,可视化代码并不容易,更像是开始使用Jumps而不是函数