PHP MVC设计 - 对同一个url / controller的多个动作

时间:2012-07-22 08:25:28

标签: php model-view-controller controller

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

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

  1. 创建新项目
  2. 删除现有项目
  3. 如果引导程序创建了“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语句来处理不同的场景。我知道这些必须坐在某个地方,但哪里最干净?

    我知道那里有很多框架,但我正在经历整个“想要了解最佳实践”的背后阶段。或者这完全是错误的做法吗?控制器实际上应该采用不同的结构吗?

2 个答案:

答案 0 :(得分:2)

首先,我真的很喜欢,你是如何处理MVC的实现的。这些类似于轨道的模仿,都是在控制器内管理视图的。

以下是我认为问题的根源:您仍在使用“哑视图”方法。

View不应该是“template”的同义词。相反,它应该是一个完整的对象,它具有处理多个模板的知识和能力。此外,在大多数MVC-inspired设计模式中,视图实例都能够从model layer请求信息。

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

最适合您的解决方案是创建全面的视图实现。这样,视图本身可以从模型层请求数据,并根据收到的数据决定使用哪些模板以及是否需要模型层中的其他信息。

答案 1 :(得分:1)

我认为你采用后一种方法有点走上正轨。但是,您不应该在引导程序中对操作的调用进行硬编码。引导程序应解释URL并通过使用call_user_func_array之类的函数动态调用操作方法。

另外,我建议您将视图渲染保留到操作代码中,以便操作逻辑自给自足且灵活。这将允许操作分析输入的正确性并适当地呈现错误或视图。另外,你的控制器上有'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');
        }
    }
}

here is a great tutorial on how to write your own MVC framework