PHP MVC设计-对同一url/控制器执行多个操作


PHP MVC design - multiple actions to same url/controller

在MVC模式中,当一个视图可能有多个相同类型的操作(例如POST)时,最好的处理方式是什么?

例如,在TODO列表应用程序中。您可以允许用户创建多个列表。每个列表可以有多个项目。因此,用户导航到site.com/list/1,其中显示了第一个列表中的所有项目(1是GET参数)。该页面上有2个表单(POST),允许用户:

  1. 创建新项目
  2. 删除现有项目

如果引导程序创建了一个"listcontroller",请检查POST变量,然后调用类似于的适当方法

$lc = new ListController();    
if(strtolower($request->verb) === 'post'):
    if(isset($_POST['title'])) :
        $data = $lc->newItem($_POST);
        $load->view('newitem.php', $data);
    else if(isset($_POST['delete']) && isset($_POST['id'])):
        $data = $lc->deleteItem($_POST);
        $load-view('deleteitem.php', $data);                    
    endif;// End if post title
else:
    //GET request here so show view for single list
endif; //

还是只做这样的事情更好

$lc = new ListController();
if(isset($_POST)):
    //controller handles logic about what function to call
    $data =  $lc->PostAction($_POST); 
    // $data could also potentially hold correct view name based on post
    $load->view(); 
else:
    //again just show single list
endif;

我只是在纠结如何最好地让控制器处理多个不同的操作,因为可能有相当多的嵌套if/else或case语句来处理不同的场景。我知道这些东西必须放在某个地方,但哪里最干净?

我知道有很多框架,但我正在经历它背后的整个"想了解最佳实践"阶段。还是这完全是错误的做法?控制器的结构是否应该有所不同?

首先,我真的很喜欢你如何处理MVC的实现。所有这些都不像模仿,视图是在控制器内部管理的。

以下是我认为问题的根源:您仍在使用"愚蠢的视图"方法

视图不应该是"模板"的同义词。相反,它应该是一个完整的对象,具有处理多个模板的知识和能力。此外,在大多数受MVC启发的设计模式中,视图实例能够从模型层请求信息。

在您的代码中,问题可以追溯到视图的工厂($load->view()方法),它只获取控制器发送的内容。相反,控制器应该只更改视图的名称,并可能发送一些会更改视图的状态的内容。

对您来说,最好的解决方案是创建全面的视图实现。这样的视图本身可以向模型层请求数据,并根据收到的数据决定使用哪个模板以及是否需要模型层提供额外信息。

我认为后一种方法在某种程度上是正确的。但是,您不应该在引导程序中对操作调用进行硬编码。引导程序应该通过使用call_user_func_array这样的函数来解释URL并动态调用操作方法。

此外,我建议您将视图的呈现留给操作代码,以便操作逻辑是自给自足和灵活的。这将允许操作分析输入的正确性,并适当地呈现错误或视图。此外,您的控制器上有方法"deleteItem",但这实际上应该是模型的工作。也许你应该阅读更多关于MVC的知识,并在尝试实现自己的框架之前,尝试使用现有的框架来更好地理解这些概念(我建议使用Yii框架)。

下面是一个我认为您的逻辑应该如何在一个好的MVC框架中实现的例子。

class ListController extends BaseController
{
    public function CreateAction($title){
        if(ctype_alnum($title))
        {
            $list = new List();
            $list->Title = $title;
            if($list->insert())
            {
                $this->render_view('list/create_successful');
            }
            else
            {
                $this->render_view('list/create_failed');
            }
        }
        else
        {
            $this->render_view('list/invalid_title');
        }
    }
    public function DeleteAction($id){
        $list = List::model()->getById($id);
        if($list == null)
        {
            $this->render_view('list/errors/list_not_found');
        }
        elseif($list->delete())
        {
            $this->render_view('list/delete_successful');
        }
        else
        {
            $this->render_view('list/delete_failed');
        }
    }
}

这里有一个关于如何编写自己的MVC框架

的很棒的教程