【问题标题】:Avoid similar controller actions避免类似的控制器动作
【发布时间】:2015-09-11 21:52:46
【问题描述】:

我正在为我的用户之间的私人消息构建一个捆绑包。

这是来自我的控制器的收件箱操作。它所做的是获取当前用户的消息,并将查询传递给 KNPpaginator 以显示其中的一部分。我还将在数据库中的页面上显示多少个结果。一种形式是一个下拉列表,它发送每页显示多少个结果。另一种形式由复选框和带有操作的下拉菜单组成。根据选择的操作,我将消息的 id(选中的复选框 id)传递给另一个名为 markAction 的函数(这也是一个可以通过转到特定 url 来标记单个消息的页面)

 public function inboxAction(Request $request)
    {

        $messages = $this->getDoctrine()->getRepository('PrivateMessageBundle:Message');
        $mymsg = $messages->findMyMessages($this->getUser());

        $message_settings = $this->getDoctrine()->getRepository('PrivateMessageBundle:MessageSettings');

        $perpage = $message_settings->findOneBy(array('user' => $this->getUser()));
        $pagerform = $this->createForm(new MessageSettingsType(), $perpage);


        $pagerform->handleRequest($request);
        if ($pagerform->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($perpage);
            $em->flush();
        }

        $paginator = $this->get('knp_paginator');
        $pagination = $paginator->paginate(
            $mymsg,
            $request->query->get('page', 1)/*page number*/,
            $perpage ? $perpage->getResPerPage() : 10/*limit per page*/,
            array('defaultSortFieldName' => 'a.sentAt', 'defaultSortDirection' => 'desc')
        );

        $form = $this
            ->createForm(
                new ActionsType(),
                $mymsg->execute()
            );


        $form->handleRequest($request);
        if ($form->isValid()) {
            $data = $form->getData();
            $ids = array();

            foreach ($data['checkboxes'] as $checkbox) {
                $ids[] = $checkbox->getId();
            }

            $action = $data['inboxactions'];


            $this->markAction($action, $ids);

            return $this->redirectToRoute('private_message_inbox');

        }

        return $this->render(
            '@PrivateMessage/inbox.html.twig',
            array(
                'messageList' => $pagination,
                'form' => $form->createView(),
                'pagerform' => $pagerform->createView(),
            )
        );
    }

还有我收件箱控制器中的标记操作用户。基于一个参数,我将相应的操作应用于第二个参数,如果通过路由调用页面,则该参数是一条消息,如果通过我的 inboxAction 调用,则可以是一组消息。我做了一些一致性检查,然后标记我的消息。

public function markAction($action, $msgs)
    {


        if (!$msgs) {
            $this->addFlash(
                'error',
                'Select at least one message!'
            );

            return;
        } else {
            if (!$action) {
                $this->addFlash(
                    'error',
                    'Select one action to apply to your items!'
                );

                return;
            } else {

                $messages = $this->getDoctrine()->getRepository('PrivateMessageBundle:Message');
                $em = $this->getDoctrine()->getManager();

                $msg = $messages->findBy(array('receiver' => $this->getUser(), 'id' => $msgs));

                $good = 0;


                foreach ($msg as $isforme) {

                    $good++;
                    switch ($action) {
                        case 'spam': {
                            if ($isforme->getIsSpam() == false) {
                                $isforme->setIsSpam(true);
                                if (!$isforme->getSeenAt()) {
                                    $isforme->setSeenAt(new \DateTime('now'));
                                }
                                $em->persist($isforme);

                            }
                            break;
                        }
                        case 'unspam': {
                            if ($isforme->getIsSpam() == true) {
                                $isforme->setIsSpam(false);
                                $em->persist($isforme);

                            }
                            break;
                        }
                        case 'viewed': {
                            if ($isforme->getSeenAt() == false) {
                                $isforme->setSeenAt(new \DateTime('now'));
                                $em->persist($isforme);

                            }
                            break;
                        }
                        case 'unviewed': {
                            if ($isforme->getSeenAt() != false) {
                                $isforme->setSeenAt(null);
                                $em->persist($isforme);

                            }
                            break;
                        }
                        default: {
                            $this->addFlash(
                                'error',
                                'There was an error!'
                            );

                            return;
                        }
                    }
                    $em->flush();

                }
                $this->addFlash(
                    'notice',
                    $good.' message'.($good == 1 ? '' : 's').' changed!'
                );


            }
        }

        if ($action == 'unspam') {
            return $this->redirectToRoute('private_message_spam');
        } else {
            return $this->redirectToRoute('private_message_inbox');
        }

    }

作为 symfony 的新手,我不确定我的 markAction 函数有多好。我觉得它可以更简单,但我不知道如何制作。

现在,我的实际问题。如何呈现我的捆绑包的其他页面,例如已发送或垃圾邮件?我必须更改的 inboxAction 中唯一的行是

 $mymsg = $messages->findMyMessages($this->getUser());

例如让它返回垃圾邮件或用户发送的消息。 和

return $this->render(
            '@PrivateMessage/inbox.html.twig',...

所以我实际上返回了相应页面的视图。我已经制作了其他页面并复制了其他操作中的代码,但我认为我可以做到,所以我一次编写了这段代码,但不知道如何。

其他一切都完全相同。我怎样才能不在所有其他操作中复制和粘贴此代码并使其更具可重用性?

【问题讨论】:

  • 可以创建一个抽象控制器来让你的主控制器继承而不是继承默认的 Symfony2 控制器。将这些函数放在抽象控制器中并将它们标记为受保护,或者至少将通用代码放在其中......如果您认为这是正确的路径,那么网络上有许多示例。
  • 问题是操作方法的一部分(我上面提到的两行代码)不同。因此,如果我将其声明为抽象,如何使继承的控制器在这两行上实现不同的 2 个操作?

标签: php symfony controller


【解决方案1】:

您可以开始更动态地更改路由:

# app/config/routing.yml
mailclient:
    path:      /mailclient/{page}
    defaults:  { _controller: AppBundle:Mailclient:index, page: "inbox" }

导致这条路线:

/mailclient
/mailclient/inbox
/mailclient/sent
/mailclient/trash

都会调用相同的动作。

现在你的方法(Action)会得到一个额外的参数:

public function indexAction($page, Request $request)
{
    // ...
}

通过这个参数你知道用户喜欢看什么。现在您可以开始编写更动态的代码了。您可以考虑向您的控制器类添加一些私有函数,您可以从 indexAction 或 你也可以简单地创建自己的类。

【讨论】:

  • 所以在这个 indexAction 中我所要做的就是根据页面进行切换并根据它填充这些变量。我非常喜欢这种方法,但没有其他方法吗?我想灵活一点。另一件事,我将我的 markAction 应用于 1000 条消息,它让我超时。它应该这样做吗?不是应该快吗?我在想我做错了什么。这就是为什么我一直在寻找替代品,以使其正常工作。
  • 总是有其他方法,但我认为这会对你有很大帮助:-)。看一下 KNP paginatorBundle (github.com/KnpLabs/KnpPaginatorBundle) 将消息分成多个页面。
  • 我已经这样做了。我所有页面上的消息每页拆分 10 条。我在问如何不重复收件箱、已发送、垃圾邮件页面的代码。
  • 嗯,有时候这些问题并不那么容易理解。我想我应该只对一页应用操作(在你的情况下是 10 条消息)。否则控制器应该拒绝该操作。
  • 但是如果我想让用户将他的所有问题都标记为已读怎么办?这将检查每条消息的状态,并在未标记的情况下对其进行标记。对于 1000 条消息超时,所以我认为我做错了什么,因为我认为它应该很快。我已经标记了从当前页面(10 个)中选择的消息,但我希望有一个单独的按钮让它们标记所有消息。
猜你喜欢
  • 2018-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-23
  • 1970-01-01
  • 2015-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多