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

问题描述 投票:0回答:2

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

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

当用户点击箭头时,它会相对于其他箭头向上/向下移动。

enter image description here

因此,在每个箭头上,有一个链接对应于我的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()

symfony sorting symfony-3.2 arraycollection
2个回答
0
投票

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

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

0
投票

@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);
}
© www.soinside.com 2019 - 2024. All rights reserved.