Symfony 3:如何使用路由操作重新排序数组集合?

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

我有一个 Product 实体。每个产品可以有 0 或 N 张图片。 我有一个 ProductPhoto 实体,它有一个 order 属性 (0 = 第一个)。

在一个页面上,我列出了我当前产品的所有图片。我想用 2 up/down 个箭头管理图片顺序。

当用户单击箭头时,它会 up/down 将图片相对于其他图片移动。

所以,在每个箭头上,有一个 link 对应于我 ProductController 中的一个路线动作。

只更新移动的图片的顺序不是很复杂,但是我不知道如何更新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));
}

也许使用 PHP uksort() ?

看起来您想更新两个 ProductPhoto 中相互移动的 order 字段,对吗?所以请试试这个:

/**
 * 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));
}

@Snegirekk 的解决方案非常有效(我使用它),但这是我找到的解决方案,如果它可以帮助...

/**
 * 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);

    // Current order of the photo
    $currentPos = $photo->getOrder();

    // Determine new order
    if ($direction == 'up') {
        $newPos = ($currentPos > 0) ? $currentPos - 1 : 0;

    } elseif ($direction == 'down') {
        $newPos = $currentPos + 1;

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

    $product = $em->getRepository('AppBundle:Product')->find($id);

    // Get product photos with actual order (moveElement() needs an array)
    $photos = $product->getPhotos()->toArray();

    // Reorder photos in ArrayCollection
    $this->moveElement($photos, $currentPos, $newPos);

    // Reorder photos in database (with keys of formatted ArrayCollection)
    foreach ($photos as $order => $p) {
        $p->setOrder($order);
    }

    $em->flush();

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

/**
 * Move an array element to a new index
 *
 * @param  array    $array      Array of elements to sort
 * @param  integer  $currentPos Current position of the element to move
 * @param  integer  $newPos     New position of the element to move
 * @return void
 */
public function moveElement(&$array, $currentPos, $newPos) {
    $out = array_splice($array, $currentPos, 1);
    array_splice($array, $newPos, 0, $out);
}