当前位置: 首页 > 面试题库 >

在MVC应用程序中从Model正确调用数据库?

归明诚
2023-03-14
问题内容

我正在建立一个用于学习/实验和小型项目目的的小型MVC框架。由于完整的MVC框架和ORM对于仅几个数据库调用来说就算过头了,因此我需要了解模型内部的基础知识。

Class Model
{
}

使用空类,在哪里我必须调用new PDO对象才能进行数据库调用?

在模型内部调用查询会是什么样子?

另外,在哪里可以找到MVC的初学者Web
/书籍资源(包含许多示例代码)?我听说过很多术语,例如业务逻辑和数据库逻辑。我记得在某处读过,您应该将业务逻辑和数据库逻辑分开。我对这个概念有些了解,我只是想知道它是什么样子,或者它们在代码本身中的含义。我很困惑应该如何分离业务逻辑和数据库逻辑,但是仍然将它们包含在模型中。

我主要是在寻找代码/逻辑示例作为答案,除了后一段。


问题答案:

警告:
这些帖子中的信息 已经过时了 。它代表了我对2年前的MVC模式的理解。当我解决它时,它将被更新。大概是本月(2013.09)。

该死的!(2017.11)。

Model本身不应包含 任何 SQL。曾经 它仅包含域业务逻辑。

我建议的方法是将职责(不是严格的“业务逻辑”)划分为另外两个其他结构集:域对象和数据映射器。

例如,如果您正在创建博客,则“模型”将不是“发布”。相反,最有可能的模型是Blog,并且该模型将处理多个Domain Objects:Post,Comment,User以及其他对象的多个实例

在模型中,域对象不应该知道如何将其存储在数据库中。甚至要知道存在 任何 形式的存储。这是的责任Data Mappers。您在模型中应该做的就是调用$mapper->store( $comment );。并且数据映射器应该知道如何存储一种特定类型的域对象,并赢得要放入哪个表的信息(通常单个域对象的存储实际上会影响多个表)。

一些代码

(仅来自文件的相关片段):

  • 我假设您知道如何编写一个好的构造函数..如果您有疑问,请阅读本文。
  • 在示例中,什么都没有命名空间,但应该是
  • _以示例开头的是protected

/application/bootstrap.php

/* --- snip --- */

$connection = new PDO( 'sqlite::memory:' );
$model_factory = new ModelFactory( $connection );

$controller = new SomeController( $request , $model_factory );

/* --- snip --- */

$controller->{$action}();

/* --- snip --- */
  • 控制器不需要知道数据库连接。
  • 如果要更改整个应用程序的数据库连接,则需要更改单行
  • 要更改制作模型的方式,您可以创建不同的类,该类实现与ModelFactory相同的接口

/framework/classes/ModelFactory.php

/* --- snip --- */

class ModelFactory implements ModelBuilderInterface
{
   /* --- snip --- */

   protected function _prepare()
   {
      if ( $this->_object_factory === null  )
      {
         $this->_object_factory = new DomainObjectFactory;
      }
      if ( $this->_mapper_factory === null )
      {
         $this->_mapper_factory = new DataMapperFactory( $this->_connection );
      }
   }

   public function build( $name )
   {
      $this->_prepare();
      return new {$name}( $this->_object_mapper , $this->_data_mapper );
   }

   /* --- snip --- */

}
  • 仅数据映射器将使用数据库,仅映射器工厂需要连接
  • 所有Model的依赖项都注入到构造函数中
  • 应用程序中的每个DataMapper实例都使用相同的数据库连接,不需要全局状态(视频)。

文件/application/controllers/SomeController.php

/* --- snip --- */

   public function get_foobar()
   {
      $factory = $this->_model_factory;
      $view = $this->_view;

      $foo = $factory->build( 'FooModel' );
      $bar = $factory->build( 'BarModel' );

      $bar->set_language( $this->_request->get('lang') );

      $view->bind( 'ergo' , $foo );

      /* --- snip --- */

   }

/* --- snip --- */
  • 控制器不知道模型创建的详细信息
  • 控制器仅负责接线和更改元件的状态

文件/application/models/FooModel.php

/* --- snip --- */

   public function find_something( $param  , $filter )
   {
      $something = $this->_object_factory('FooBar');
      $mapper = $this->_mapper_factory('FooMapper');

      $something->set_type( $param );
      $mapper->use_filter( $filter )->fetch( $something );

      return $something;
   }

/* --- snip --- */
  • 域对象负责验证给定的参数
  • 视图接收并决定如何呈现它
  • 映射器获取对象并将其从存储中放入所有必需的信息(它不一定是DB ..可以从某些文件或外部REST API中获取)

我希望这将帮助您了解DB逻辑和业务逻辑之间的分离(实际上,也可以是表示逻辑)

很少注意

模型永远都不能扩展数据库或ORM,因为模型不是它们的子集。通过扩展类,您在声明它具有超类的所有特征,但有少数例外。

class Duck extends Bird{}
class ForestDuck extends Duck{}
// this is ok

class Table extends Database{}
class Person extends Table{}
// this is kinda stupid and a bit insulting

除了明显的逻辑问题外,如果您的模型与底层数据库紧密结合,那么它会使代码极难测试(谈论单元测试(视频))。

我个人认为,ORM无用且在大型项目中-甚至有害。问题源于一个事实,那就是ORM试图桥接两种完全不同的解决问题的方式:OOP和SQL。

如果您从ORM开始项目,那么经过短暂的学习之后,您将能够非常快速地编写简单的查询。但是,当您开始 遇到
ORM的局限性和问题时,您已经完全投入了ORM的使用(也许甚至雇用了新手,他们真的很擅长选择,但是对普通的SQL却很反感)。您最终会遇到与数据库相关的每个新问题都需要花费越来越多的时间来解决的情况。而且,如果您一直在使用基于ActiveRecord模式的ORM,那么这些问题将直接影响您的模型。



 类似资料:
  • 问题内容: 我正在使用ReactJS + Redux,以及Express和Webpack。有一个内置的API,我希望能够从客户端进行REST调用- GET,POST,PUT,DELETE。 使用Redux架构的方式和正确方法是什么?就简化程序,动作创建者,存储和反应路线而言,任何有关流程的良好示例都将非常有帮助。 先感谢您! 问题答案: 最简单的方法是使用package进行操作。这个软件包是一个r

  • 问题是,从性能上看,这些选项中的哪一个(显然,可能还有第三个我们没有考虑)是最好的。我认为第二种选择我看到了几个缺陷,但我不确定。就延迟和速度而言,遍历数组(如果添加了服务,或者由于用户首先使用了service2,然后使用了Service1),遍历数组的次数会更多)比选项1要高得多。此外,一个用户在一个服务下,这意味着要遍历整个数组,寻找并消除它。我不知道你是专家,你有什么建议吗?所有这些都将上传

  • 我知道Java应用程序可以捆绑为Mac应用程序,带有JavaSwing或JavaFX驱动的用户界面,以及捆绑的Java运行时(JRE)。但是我想用Swift编写的Xcode构建一个本机应用程序,带有Cocoa用户界面,可以调用Java库来处理一些数据。 我需要调用捆绑的JRE,调用所需的库(JAR文件),传递对Mac存储中文件的引用(或者该文件的内容作为内存中的大字符串),并取回字符串(XML或C

  • 问题内容: 我正在尝试使用Spring MVC创建一个Web应用程序,并将Hibernate作为其ORM层。但是,由于我对这两个框架的经验不足,所以我很努力。 以下代码将正确显示我要查找的所有记录,但仍将堆栈跟踪信息放入日志中。我在查找有关集成Hibernate和SpringMVC的详尽文档时遇到了麻烦(我查看了springsource.org并阅读了Internet上的各种文章)。谁能指出我在这

  • 问题内容: 我有一个Java应用程序,当我使用它时,它会正确关闭,Java应用程序会在关闭之前保存所有数据。现在,我尝试使用来从C#控制台应用程序中关闭该Java应用程序,但是当我使用它时应用程序不保存任何数据,我也尝试过使用但什么也没有发生,并且使用了该过程只是在没有任何挽救的情况下将其杀死了。 。 我如何从C#控制台应用程序引发Java应用程序的关机钩子? 问题答案: 关闭钩子不能由另一个应用

  • 在我的环境中,我有JSF 2.2 CDI Spring 4 Wildfly 9 Spring Data在野生服务器中,我配置了两个数据源: 示例(来自工厂) OracleDS(我创建的这个) 在persitence.xml,我有: 我的applicationContext.xml: http://www . spring framework . org/schema/beans/spring-be