【问题标题】:How to Implement MVC in PHP如何在 PHP 中实现 MVC
【发布时间】:2012-01-12 21:00:59
【问题描述】:

简介

模型-视图-控制器方法从假期开始就在我的脑海中,我真的需要在我的 Web 应用程序中将它归结为一个 tee,它是用 PHP 创建的。

到目前为止,我了解了一般的 MVC 概念以及为什么这样做,但我需要一些帮助。这是一个大学项目,当我询问有关 MVC 的问题时,我的项目顾问并不是很有帮助。

应用程序

这是一个任务管理系统,或者一个待办事项列表。目标是一个非常简单的界面,用户可以使用他们的 Facebook 帐户登录,创建、修改或删除任务,以及使用 Javascript 和 PHP 创建的注销。

事实

我有一个静态 PHP 页面 here 包含像“top_div”和“main_div”这样的 div。目的是让“controller.php”包含在视图和模型之间(我还没有创建)。

重要提示:页面上的所有内容都使用 jQuery,因此用户永远不会看到页面刷新。我有一个函数可以淡出 div 中的内容,抓取新需要的内容,将其放入 div(隐藏,因为 div 已经淡出),然后再次淡入 div。

目的是让控制器向模型请求,然后将 Facebook 登录按钮(例如)发送回视图。这个 Facebook 登录按钮是 HTML。内容会有文本和html之类的其他内容,如果用户已经登录,“欢迎”将被发送到#main_div 使用PHP、jQuery和cURL

我正在使用对象,所以据我了解,我需要实例化一个对象来进行数据库连接和查询。我在哪里实例化对象?我读到它们应该在控制器中创建,但是从我读过的所有其他内容来看,控制器的目的很简单,它告诉模型视图想要什么,只充当中间人。我对模型实例化对象的印象(对我来说更有意义)。

1) 所以,请向我解释在模型中实例化对象是不正确的。如果不是这种情况,就我对 MVC 方法的理解而言,那就太好了。

假设用户已登录。我将在视图 (index.php) 上显示他们的姓名和他们的 Facebook 图片。如果您通过上面的链接访问该站点,您可能会在右侧看到该图片所在的一个小白框。 PHP中用户图片的代码如下:

<img src="https://graph.facebook.com/'.$fbid.'/picture" width="79" height="64" align="center" style="opacity:0.8;">';

2) 由于此 HTML 将通过上述 jQuery 函数传递给视图以显示到 DIV 中,因此我的控制器可以输出此类信息吗?我的控制器可能有类似(伪代码)的内容:

if(user is logged in(from checking via model)) then { send to #main_div the html above };

我可能会在此过程中想到更多问题,但请有人帮助我了解更多关于我在做什么的信息吗?

【问题讨论】:

  • 您将在此处获得广泛的回复。问题是,MVC 是一种相当简单的模式,可以用一百万种不同的方式实现。

标签: php model-view-controller design-patterns


【解决方案1】:

1) 所以,请向我解释实例化是如何不正确的 模型中的对象。

这完全没有错。然而,目标是瘦控制器和胖模型,所以我在控制器中创建对象并让模型/服务完成繁重的工作。

警告:最好在其他地方创建对象,也许是在引导程序中,并使用dependency injection 将这些对象提供给您的控制器。话虽如此,我的大部分对象创建都根据需要在控制器中进行。

2) 因为这个 HTML 将被传递给视图以显示为 DIV 使用上面描述的jQuery函数,对我来说可以吗 控制器有这样的信息出去?

是的,是的。控制器会将数据从模型传递到视图。

MVC 框架建议

除非您只是想或必须这样做,否则不要推出自己的 MVC。选择一个框架,做一点研究,然后赢。

【讨论】:

  • 啊,我记得写过这个,但我不知道,现在我自己写了,更好地理解 MVC,使用 Symfony 和真正的自动装配依赖注入容器,如 Auryn .我现在有你暗示的胜利,干杯! :)
  • 不喜欢你关于胖模特的说法。模型根本不应该太胖,它们只是代表数据,没有别的......
  • 完全取决于模型的含义,这通常是一个滑溜溜的词。当模型被定义为数据的表示时,我 100% 同意你的看法。然而,使用 Model 来包含应用程序的业务逻辑并不是不合适的。创建瘦控制器和胖模型的警告仅仅意味着应该将业务逻辑排除在控制器之外。当我说“模型/服务”应该做“繁重的工作”时,我试图传达这一点。
  • 呃,模型是一个。你没有“模型”。你确实有一个胖模型和瘦控制器,因为控制器只是模型层中单元测试对象的粘合剂 - 因此你实际上不需要测试控制器。
【解决方案2】:

通常,您的所有代码都应该是基于对象的。 “控制器”部分将根据用户请求进行操作。所以假设一个人请求“www.you.com/?login”,控制器应该得到“登录”的请求。控制器(有时称为路由器)将实例化适当的“模型”对象来处理登录。在这种情况下,它可能只是创建模型(登录)对象,没有告诉控制器显示“视图登录”的数据。然后控制器转到视图对象代码并为其提供要显示的正确视图,并且视图对象返回呈现的带有登录表单的 HTML 页面。

用户提交凭据后,请求将是“POST:action=login,username=blah,password=12345”。然后控制器会看到它需要调用登录对象并将参数用户名/密码传递给登录“模型”。登录模型逻辑将处理参数,然后发送到控制器显示“view-login,success”。然后控制器会告诉视图对象显示带有附加参数的视图,视图对象将呈现页面并输出它。

这可以在您的应用编码期间继续扩展。使用自动加载功能,您甚至可以让控制器扫描目录以查找模型/视图,并动态实例化请求的对象或在默认对象不存在时回退。这样你就不需要在每次添加模型/视图逻辑时修改你的控制器。另一个好处是应用程序的单一入口点,例如所有 URL 将是 www.you.com/?login 或 www.you.com/?task=2&action=delete ... 等等。多读书,写自己的书时不要感到沮丧。在您真正了解您希望 MVC 的行为方式之前,您可能会废弃您的工作几次。

好读: http://oreilly.com/php/archive/mvc-intro.html

【讨论】:

    【解决方案3】:

    首先,您的静态 php 页面不包含控制器。反过来说,您的控制器包含您的静态 php 页面(视图)。

    对于 KISS,添加一些

    <!--parsableTags!-->
    

    到您的视图并加载相应的模型以填充这些标签。让控制器将结果返回给调用浏览器。

    补充:

    控制器中的数据库逻辑与否?这里没有绝对的真理,您的应用程序可能主要与 LDAP 对话,那么为什么还要加载 db-service?您想要的可能是一个配置,由控制器在启动时读取以加载初始组件。

    有些人认为只有视图应该生成 html,这是一个很好的原则,但可能会让你在 1 点发疯。

    但最终有很多不同的方法可以做到这一点。

    【讨论】:

      【解决方案4】:

      我建议查看现有的一些其他库,以便更轻松地在 PHP 中使用 MVC(至少作为一个示例,让您了解其他人是如何做的)。想到的几个是:

      • Zend 框架
      • CakePHP

      ...那么当您准备好真正改进您的代码时;)查看这些 Ruby 库:

      【讨论】:

        【解决方案5】:

        控制器类应处理所有传入服务器的请求,然后根据请求,对所需的任何模型对象执行任何操作,然后将所需的任何数据传递给视图对象,然后呈现页面。

        您可以通过一百万种方式进行设置。基本思想是将业务逻辑与视图呈现 (HTML) 分开。

        一些提示:

        在许多人看来,您不应该让模型自己加载其他模型。相反,您将使用依赖注入模式来减少强耦合。这基本上意味着通过构造函数或方法参数插入任何所需的对象。

        很多人会使用所谓的依赖注入容器。这通常是一个具有一个公共方法的类,用于实例化除 Controller 类之外的所有其他类。在 PHP 5.3 中,您将使用闭包来帮助延迟加载从 di 容器请求的任何类。如果对象是一个将被共享的对象(如单例),则 dic 类还可以存储对象以供以后重用,但无论如何,您总是会以相同的方式从 dic 请求该类。重点是,如果您需要更改类的实例化方式,或者想将其与扩展类或使用相同接口的其他类交换,则可以在代码中的一个位置,而不是多个位置。它还有助于让您的控制器保持“轻便”。

        【讨论】:

          【解决方案6】:

          关注点分离。

          将呈现 html 的逻辑放入 php 视图文件中。

          把javascript和css放在自己的文件里,对外引用

          放上你的巴士。 DAO 中的逻辑(数据访问对象) - 只有它们与 db 对话,而不是 VIEW 文件。

          将您的控制器创建为普通的 php 页面,如果您愿意,可以使用 index.php 或 controller.php。每个请求都通过索引或控制器文件。控制器文件将包含对 javascript 和 css 文件的外部引用。

          每个对控制器的回调都将包含一个参数和变量,用于确定将控制权传递到何处。控制器可能会有一个 swich-case 或 if-else 结构来处理特定的请求。像这样的:

          <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
          <script src="assets/ajax.js" type="text/javascript"></script>
          
          <link rel="stylesheet" type="text/css" href="assets/adminApp.css" media="screen" />
          <link rel="stylesheet" href="assets/print.css" type="text/css" media="print" />
          
          <?php
            require_once('../../config.php');
            require_once('../connect_db.php');
            require_once('../custom_boces_dao.php');
            require_once('../custom_boces_gateway.php');
          
            if(isset($_REQUEST['action'])){
              $action = $_REQUEST['action'];  
            }else{
              $action = "viewUserAttributes";
            }
          
           echo "<div id='leftNav'>";
             require_once('views/global_navigation.php');
           echo "</div>";
          
           echo "<div id='mainArea'>";
          
              switch ($action) {
          
                case 'home':
                  echo "something to say";
                break;
          
                case 'viewCourseAttributes':
                  require_once('views/course/frmCourses.php');
                break;
          
                case 'editCourseAttributes':
                  require_once('views/course/frmCourses.php');
                  require_once('views/course/frmCourseAttributes.php');
          
                 break;
                .
                .
                .
           }      
          
           echo "</div>";
          
          ?>          
          

          【讨论】:

            【解决方案7】:

            让我们从基础开始。要首先构建一个体面的 MVC 框架,您需要一个引导程序。一个程序,它将确定您的应用程序需要做什么。在它完成之后,它需要将数据传递给适当的函数(类)。一个好的方法是建立某种路由表,例如,使用正则表达式和一些默认值来指向表达式不匹配的时间。例如,它可以是:/module/controller/action/params。引导程序应该负责所有的初始化,读取配置,弄清楚要传递到哪里。为了简化编码,您可以创建一个带有命名空间的结构。例如,您需要在一个地方使用控制器,而在其他地方需要模型和视图。由于 PHP

            【讨论】:

            • 另一种方法是让 Apache 处理路由并让控制器自行“启动”。然而,许多“框架”通过单个前端控制器运行每个请求,该前端控制器根据请求路由到适当的控制器。
            猜你喜欢
            • 2020-04-11
            • 1970-01-01
            • 2013-05-28
            • 1970-01-01
            • 2016-10-01
            • 1970-01-01
            • 2011-01-20
            • 2017-04-30
            • 1970-01-01
            相关资源
            最近更新 更多