1

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

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

我想使用干净的 URL,所以现在我有 1 个(只有一个)控制器(index.php),它将 URL 分成段并分析它们,为每个段调用特定的方法和视图,或者(如果需要) ) 将用户重定向到正确的 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';
}
4

3 回答 3

1

我认为对于控制器的实际作用发生了一些误解。

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

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

  1. 经典控制器,负责改变模型层和视图的状态;
  2. 页面控制器,它初始化模型层结构,创建视图,将模型层元素绑定到所述视图,然后渲染它

PS至于 MVC 的其余部分,您可能会发现thisthis comment 很有用。

于 2012-07-18T00:36:03.930 回答
0

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

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

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

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

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

于 2012-07-18T01:49:25.990 回答
0

这不是 MVC 的实现方式!

  • 首先,您必须为每个控制器、模型或视图创建一个类。
  • 每个类必须在一个单独的文件中。
  • 文件必须根据其类类型分组在不同的目录中。

考虑你有一个订单表,那么你有:

/index.php
/controller/order.php
/model/order.php
/view/order/grid.php
/view/order/form.php

在索引中,您必须只路由程序。您必须实例化控制器,调用所需的函数。控制器必须从模型中获取所需的对象并将它们放在视图中并将视图返回给索引。index 将在视图上调用渲染并输出结果。

于 2012-07-18T00:35:29.420 回答