Dismiss
Announcing Stack Overflow Documentation

We started with Q&A. Technical documentation is next, and we need your help.

Whether you're a beginner or an experienced developer, you can contribute.

Sign up and start helping → Learn more about Documentation →

Scenario:

1) I have a Menu consisting of Menu Items, each with an order_index (ranging from 0 to n), which identifies the Menu Item's position in the Menu.
2) I want to insert a new Menu Item at a specific position or change the position of an existing Element.
3) Assume that if it is a new item, I have already saved the new item in my database with order_index = null.
4) So when editing/creating a menu item, all relevant info other than the order_index gets, saved and then the following function gets called:

function reOrderItems(MenuItem $item, Integer $orderIndex)
{
    /*
    Step 1: Retrieve all the MenuItems, ordered by order_index. This means that
            If it was a new item, the item's order_index is null and would be the
            first item in the array of retrieved items.

    Step 2: Take the item ($item) and remove it from its current location in the
            array and place it at its new position, $orderIndex.

    Step 3: "Reorder" the array indexing so that it runs from 0 to
            (array.length - 1) in the order that the Menu Items are now.

    Step 4: Update all items in the database with their new order_index, ranging
            from 0 to n according to the array index.
    */
}

Example 1: Move Item in position [0] to position [3]. [1] => [0], [2] => [1], [3] => [2], [0] => [3] and all other elements stay the same.

Example 2: Move Item in position [6] to position [3]. Items in position [0],[1] and [2] remain the same. [3] => [4], [4] => [5], [5] => [6], [6] => [3], all other elements stay the same.

I would appreciate any help with an algorithm that would be able to do Steps 2 & 3 for me. Please keep in mind that true genius lies in simplicity. The simpler the algorithm to accomplish this, the better.

share|improve this question
    
Please add an example of menu by calling print_r() with your menu as the argument. – A.L Jan 21 '14 at 14:13
up vote 0 down vote accepted

You can use the built-in PHP functions array_merge() and array_splice(). I think it answers to your question, but the index of the table may be rebuilt by using these functions, I'm not sure it will be a problem for you.

<?php

$menu = array(
    0 => 'Item 1',
    1 => 'Item 2',
    2 => 'Item 3',
    3 => 'Item 4',
    4 => 'Item 5'
);

echo('Default menu:'.PHP_EOL);
print_r($menu);

$menuNewEntry = array(
    0 => 'Item 0 (new)'
);

##### add a menu entry at the beginning #####
$menu = array_merge($menuNewEntry, $menu);

echo('Default menu with new entry:'.PHP_EOL);
print_r($menu);

##### remove a menu entry #####
array_splice($menu, 2, 1);

echo('Default menu without entry at index 2:'.PHP_EOL);
print_r($menu);

##### move a menu entry #####
# remove an element from the array and keep the result (the removed element)
$menuRemovedEntry = array_splice($menu, 0, 1);

# insert this element in the array (the removed element)
array_splice($menu, 2, 0, $menuRemovedEntry);

echo('Default menu with entry 0 moved at index 2:'.PHP_EOL);
print_r($menu);

Here is the result:

Default menu:
Array
(
    [0] => Item 1
    [1] => Item 2
    [2] => Item 3
    [3] => Item 4
    [4] => Item 5
)
Default menu with new entry:
Array
(
    [0] => Item 0 (new)
    [1] => Item 1
    [2] => Item 2
    [3] => Item 3
    [4] => Item 4
    [5] => Item 5
)
Default menu without entry at index 2:
Array
(
    [0] => Item 0 (new)
    [1] => Item 1
    [2] => Item 3
    [3] => Item 4
    [4] => Item 5
)
Default menu with entry 0 moved at index 2:
Array
(
    [0] => Item 1
    [1] => Item 3
    [2] => Item 0 (new)
    [3] => Item 4
    [4] => Item 5
)
share|improve this answer

Check doctrine sortable behavior(ready-to-use solution!) or see source code for some ideas.

share|improve this answer

Have a look at reorder function from Nspl:

use function nspl\a\reorder;

$menu = array(
    0 => 'Item 0',
    1 => 'Item 1',
    2 => 'Item 2',
    3 => 'Item 3',
    4 => 'Item 4',
    5 => 'Item 5',
    6 => 'Item 6',
);

echo "Example 1\n";
print_r(reorder($menu, 0, 3));

echo "\nExample 2\n";
print_r(reorder($menu, 6, 3));

Outputs:

Example 1
Array
(
    [0] => Item 1
    [1] => Item 2
    [2] => Item 3
    [3] => Item 0
    [4] => Item 4
    [5] => Item 5
    [6] => Item 6
)

Example 2
Array
(
    [0] => Item 0
    [1] => Item 1
    [2] => Item 2
    [3] => Item 6
    [4] => Item 3
    [5] => Item 4
    [6] => Item 5
)
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.