如何在没有'胖'控制器的情况下实现干净的URL?

时间:2012-07-18 00:02:32

标签: php model-view-controller clean-urls

最近我一直在学习如何在我的应用程序中实现MVC结构。我计划在不久的将来使用PHP框架,但现在它只是纯PHP。我已经知道控制器应该是“瘦”的,模型应该是“胖”的,但似乎无法理解这是如何与干净的URL同时进行的。

在我正在实习的公司,我正在开发一个基于Web的应用程序,以便在数据库中的3个不同表上执行CRUD操作。每个表都有自己的特定字段,这意味着每个表都需要4个视图(每个CRUD操作1个)。

我想使用干净的URL,所以现在我有1个(只有一个)控制器(index.php),它将段拆分并分析它们,调用每个段的特定方法和视图,或者(如果需要)将用户重定向到正确的URL。

现在控制器包含近1000行代码。我总是读到控制器应该是“瘦”的,并且看到人们在一个应用程序中讨论多个控制器。我似乎无法理解如何结合干净的URL实现这一点......

非常感谢任何帮助。在公司,我正在实习,只是一个网页设计师,所以我不能问他任何与编程相关的问题......

以下是我的控制器的基本表示(index.php)

// Check if user is logged in
if (isset($_SESSION['username']) AND isset($_SESSION['loggedIn'])) {

    // Get URL from $_SERVER
    $url = $_SERVER['REQUEST_URI'];

    // Split URL and assign values to $url
    $url = trim($url, "/");
    $url = explode('/', $url);

    // Remove first url segment (index.php) for convenience
    array_shift($url);

    // Check if 1st URL segment (category) is set
    if (isset($url[1])) {
        $category = $url[1];

        // Check if category is 'apples'
        if ($category == 'apples') {

            // Check if 2nd URL segment (action) is set
            if (isset($url[2])) {
                $action = $url[2];

                // Check if action is 'add'
                if ($action == 'add') {
                    // Calls to Model
                    // Include Presentation (form to add new record to 'apples' category)
                }

                // Check if action is 'view'
                elseif ($action == 'view') {
                    // Calls to Model
                    // Include Presentation (list of all records in the 'apples' table)
                }

                // Check if action is 'edit'
                elseif ($action == 'edit') {

                    // Check if 3d URL segment (id) is set
                    if (isset($url[3])) {
                        $id = $url[3];

                        // Calls to Model
                        // Include Presentation (form to edit record of the 'apples' category);
                    }

                    // If 3d URL segment (id) is not set then redirect
                    else {
                        header('Location: index.php/$category/view');
                    }
                }

                // Check if action is 'delete'
                elseif ($action == 'delete') {

                    // Check if 3d URL segment (id) is set
                    if (isset($url[3])) {
                        $id = $url[3];

                        // Calls to Model
                        // Include Presentation (form to edit record of the 'apples' category);
                    }

                    // If 3d URL segment (id) is not set then redirect
                    else {
                        header('Location: index.php/$category/view');
                    }
                }

                // If 2nd URL segment (action) is invalid then assume user wants to view and redirect
                else {
                    header("Location: index.php/$category/view");   
                }
            } 

            // If 2nd URL segment (category) is not set then assume user wants to view and redirect
            else {
                header("Location: index.php/$category/view");
            }

        }

        // Check if category is 'pineapples'
        elseif ($category == 'pineapples') {
            // same here as in 'apples' code block
        }

        // Check if category is 'pears'
        elseif ($category == 'pears') {
            // same here as in 'apples' code block
        }

        // If 1st URL segment (category) is invalid then redirect to index.php
        else {
            header('Location: index.php')
        }
    }

    // If 1st URL segment (category) is not set then show category overview
    else {
        include 'presentation/category_overview.php';
    }
}

// If user is not logged in then check if login form got submitted
elseif($_POST['formSubmit'] == 'submit') {
    // Calls to Model (form and user credentials validation)
    // Include Presentation (category overview)
}

// If user is not logged in and did not submit login form then include view (login form)
else {
    include 'presentation/login.php';
}

3 个答案:

答案 0 :(得分:1)

我认为在控制器的实际操作方面发生了一些误解。

拆分URL不是控制器的责任。它通常是单独的路由机制。有时称为front controller。通常使用正则表达式(有时在APC的帮助下)实现。

在基于Web MVC的模式中,您基本上有两种选择:

  1. 经典控制器,负责改变模型层和视图的状态;
  2. page controllers,用于初始化模型图层结构,创建视图,将模型图层元素绑定到所述视图然后呈现它
  3. P.S。至于其余的MVC,您可能会发现有用的thisthis评论。

答案 1 :(得分:0)

这不是MVC的实施方式!

  • 首先,您必须为每个控制器,模型或视图设置一个类。
  • 每个班级必须在一个单独的档案中。
  • 文件必须根据类类别分组到不同的目录中。

考虑你有一张订单表,然后你有:

/index.php
/controller/order.php
/model/order.php
/view/order/grid.php
/view/order/form.php
索引中的

你必须只是路由程序。你必须实例化控制器,调用所需的功能。控制器必须从模型中获取所需的对象并将它们放在视图中并将视图返回到索引。 index将在视图上调用render,它将输出结果。

答案 2 :(得分:0)

除了实现前端控制器模式之外,真正的MVC应用程序还应展示出良好的面向对象设计的所有特性:模块化,松散耦合,内聚,关注点分离,DRY等。

显然,所有模型,视图和控制器都将具有许多应该封装在基本模型/视图/控制器类中的共享功能。这些基类(以及行为,帮助程序,组件等)以及必要的实用程序库(路由引擎,DAL等)将构成MVC框架的基础。

应将每个应用程序重用的框架库与构建在每个应用程序框架之上的特定于应用程序的代码区分开来。这是“瘦模控制器,胖模型”中引用的特定于应用程序的模型和控制器

您的基本控制器必须包含用于协调应用程序流,实例化模型,触发模型验证,实例化视图,触发回调,在模型和视图之间传递数据,执行会话处理,实现脚手架等的代码。所以很自然它会是有点大。

但是,您的应用程序控制器只需继承基本控制器类就可以获得所有这些功能,从而允许它们只包含定义控制器设置和操作所需的最少代码。

相关问题