Search code examples
symfonysortingsymfony-3.2arraycollection

Symfony 3 : how to reordering an array collection with route action?


I have a Product Entity. Each product can have 0 or N pictures. I have a ProductPhoto Entity which has a order property (0 = first).

On a page, I list all the pictures of my current product. I would like to manage pictures order with 2 up/down arrows.

When the user clicks on an arrow, it moves up/down the picture compared to the others.

enter image description here

So, on each arrow, there is a link that corresponds to a route action in my ProductController.

It's not very complicated to update only the order of the picture that moved, but I don't know how to update the order of other pictures in the ArrayCollection...

/**
 * Manage picture order
 *
 * @Route("/products/{id}/photos/{idphoto}/move-{direction}", name="prod_move_photo")
 */
public function movePhotoAction($id, $idphoto, $direction, Request $request) {
    $em     = $this->getDoctrine()->getManager();
    $photo  = $em->getRepository('AppBundle:ProductPhoto')->find($idphoto);

    if ($direction == 'up') {
        $order = $photo->getOrder() - 1;

        if ($order >= 0)
            $photo->setOrder($order);
        else
            $photo->setOrder(0);

    } elseif ($direction == 'down') {
        $order = $photo->getOrder() + 1;
        $photo->setOrder($order);

    } else {
        throw $this->createNotFoundException("The type of ordering '" . $direction . "' doesn't exist.");
    }

    $em->flush();

    // redirection
    return $this->redirectToRoute('prod_photos', array('id' => $id));
}

Maybe using PHP uksort() ?


Solution

  • It looks like you want to update order fields in two ProductPhotos moved by each other, right? So please try this:

    /**
     * Manage picture order
     *
     * @Route("/products/{id}/photos/{idphoto}/move-{direction}", name="prod_move_photo")
     */
    public function movePhotoAction($id, $idphoto, $direction, Request $request) {
        $em     = $this->getDoctrine()->getManager();
        $photo  = $em->getRepository('AppBundle:ProductPhoto')->find($idphoto);
    
        $order = $photo->getOrder();
    
        switch($direction) {
    
            case 'up':
                $newOrder = ($order >= 1) ? ($order - 1) : (int) 0;
                break;
    
            case 'down':
                $newOrder = $order + 1;
                break;
    
            default:                
                throw $this->createNotFoundException("The type of ordering '" . $direction . "' doesn't exist.");
        }
    
        $anotherPhoto = $em->getRepository('AppBundle:ProductPhoto')->findOneByOrder($newOrder);
    
        $photo->setOrder($newOrder);
        $anotherPhoto->setOrder($order);
    
        $em->flush();
    
        // redirection
        return $this->redirectToRoute('prod_photos', array('id' => $id));
    }