XanderLaravel's avatar

Laravel Order Categories on user input

I have a list of categories with a field called 'order.' In this field, there is a digit that determines the ordering like 1, 2, 3, 4, 5, etc. Now, when I want to edit the order, I am able to move an item from the bottom to the top just as I want. For instance, I can place item 5 in the 2nd position, and then item 2 will become the 3rd, item 3 will become the 4th, and so on. However, when I try to place, for example, item 2 at the 5th order, it breaks, and I get 1, 3, 4, 5, 6, instead of the expected sequence 1, 2, 3, 4, 5, with only the 5th value moving to the 2nd position and all other values incrementing by 1. Could someone take a quick peek at my code and help me understand how I can resolve this issue?

        $highest = Category::max('order');
        $lowest = Category::min('order');
        $same = Category::where('order', $this->order)->first();

        $change = Category::where('order', '>=', $this->order)->orderBy('order', 'ASC')->get();

        if($this->order == $same->order) {
            foreach($change as $item) {
                Category::whereId($item->id)->update([
                    'order' => $item->order + 1,
                ]);
            }
        }
        
        $this->category->update([
            'user_id' => auth()->user()->id,
            'order' => $this->order,
            'name' => $this->name,
            'description' => $this->description
        ]);
0 likes
2 replies
HeyJanny's avatar
HeyJanny
Best Answer
Level 1

Essentially u want to reindex orders of categories that have their 'order' greater than the modified category order AFTER modification and have their 'order' less than modified category pre-modification and vice versa depending whether you are increasing or decreasing the order. So like...:

public function modifyCategoryOrder(Category $category, int $newOrder){
$currentOrder = $category->order;
//reorder
    if ($currentOrder < $newOrder) {
        Category::whereBetween('order',[$currentOrder + 1, $newOrder])->decrement('order');
    } 
elseif ($currentOrder > $newOrder) {
        Category::whereBetween('order', [$newOrder, $currentOrder - 1])->increment('order');
    }
//update
$category->order=$newOrder;
$category->save();
}
1 like
XanderLaravel's avatar

@HeyJanny Yes, this code does work perfectly. I made small changes to make it work with Livewire, and now it works even better. Thank you so much! Not only did you help me solve this problem, but I also understand now how to solve a problem like this in the future!

Please or to participate in this conversation.