在MVC应用程序中从Model正确调用数据库? [英] Properly calling the database from Model in an MVC application?

查看:164
本文介绍了在MVC应用程序中从Model正确调用数据库?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个用于学习/实验和小项目目的的小型MVC框架。我需要找出模型的内部基础知识,因为一个完整的MVC框架和ORM是overkill只是几个数据库调用。

 类模型
{
}

使用空类我必须为数据库调用调用新的PDO 对象?



在模型中调用查询?



此外,我在哪里可以找到一个初学者的web / book资源MVC(有很多示例代码)?我听说过很多术语,如业务逻辑和数据库逻辑。我记得读某处,你应该分离业务逻辑和数据库逻辑。我可以理解一些概念,我只是想知道它是什么样子或它们在代码本身意思。我很困惑如何分离业务逻辑和数据库逻辑,但仍然在模型中。



我主要寻找代码/逻辑示例作为答案,除了可能

警告:




>此帖子中的信息非常过时。它代表我对MVC模式的理解,因为它是在2年前。它会更新,当我到达它。可能是本月(2013.09)。


模型不包含任何 SQL。永远。它只是用来包含域的业务逻辑。



我建议的方法是将责任分离,这不是严格的业务逻辑分成另外两组构造:域对象数据Mappers



例如,如果您正在制作博客,那么模型不会是帖子。相反,模型很可能是Blog,这个模型将处理多个域对象:Post,Comment,User和其他对象的多个实例。



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






一些代码



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





/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 --- * /

}








>文件 /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 ');
$ mapper = $ this-> _mapper_factory('FooMapper');

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

return $ something;
}

/ * --- snip --- * /




  • 域对象负责验证给定的参数

  • 视图接收并决定如何呈现

  • 获取对象并将其中存储的所有必需信息(不必是DB ..它可以从某个文件或外部REST API获取)






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






很少注意



模型不应扩展数据库或ORM,它们的子集。通过扩展一个类,你声明具有超类的所有特征,但有少量例外。

  {} 
类Forest Duck extends Duck {}
//这是确定

类扩展数据库{}
类Person扩展表{}
/ /这是有点蠢和有点侮辱

除了明显的逻辑问题,加上数据库底层,它使代码极难测试(谈论单元测试(视频))。






我个人认为,ORM是无用的,在大项目中 - 甚至是有害的。问题源于这样的事实,即ORM试图桥接两种完全不同的方法来处理问题:OOP和SQL。



如果您使用ORM启动项目,那么在短时间的学习曲线之后,您就能够非常快速地编写简单的查询。但是当你开始打开ORM的限制和问题时,你已经完全投资于使用ORM了(甚至可能是新员工被雇佣了,谁真的擅长你选择的, SQL)。你最终在每一个新的数据库相关问题需要越来越多的时间来解决的情况。如果你一直使用基于ActiveRecord模式的ORM,那么问题直接影响你的模型。



叔叔叔叔称之为技术债务。






少量书籍



与主题有轻微关系




I'm building a tiny MVC framework for learning/experimenting and small project purposes. I needed to find out the basics of the internals of the Model since a full MVC framework and ORM is overkill for just a few database calls.

Class Model
{
}

Using an empty class where would I have to call a new PDO object for database calls?

What would calling a query look like inside the Model?

Additionally, where can I find a beginner's web/book resource to MVC (with lots of example code)? I've heard a lot of terms such as business logic and database logic. I remember reading somewhere that you should separate business logic and database logic. I can understand the concept somewhat, I just wonder what it looks like or what they mean in code itself. I'm confused how business logic and database logic should be separated but still be inside the Model.

I'm mostly looking for code/logic examples as answers, except maybe the latter paragraph.

解决方案

Warning:
The information in this posts is extremely outdated. It represents my understanding of MVC pattern as it was more then 2 years ago. It will be updated when I get round to it. Probably this month (2013.09).

Model itself should not contain any SQL. Ever. It is meant to only contain domain business logic.

The approach i would recommend is to separate the responsibilities, which are not strictly "business logic" into two other other sets of constructs : Domain Objects and Data Mappers.

For example, if you are making a blog, then the Model will not be Post. Instead most likely the model will be Blog , and this model will deal with multiple Domain Objects: multiple instances of Post, Comment, User and maybe other objects.

In your model, the domain objects should not know how to store themselves in database. Or even be aware of the existence of any form of storage. That is a responsibility of Data Mappers. All you should do in the Model is to call $mapper->store( $comment );. And the data mapper should know how to store one specific type of domain objects, and win which table to put the information ( usually the storage of of single domain object actually affects multiple tables ).


Some code

(only relevant fragments from files):

  • I assume that you know how to write a good constructor .. if you have doubts, read this article
  • nothing is namespaced in example, but it should be
  • anything that begins with _ in example is protected

from /application/bootstrap.php

/* --- snip --- */

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

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

/* --- snip --- */

$controller->{$action}();

/* --- snip --- */

  • controller does not need to be aware of database connection.
  • if you want to change DB connection for whole application, you need to change single line
  • to change the way how Model's are made, you create different class which implements same interface as ModelFactory

from /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 --- */

}

  • only data mappers will use database , only mapper factory need connection
  • all the dependencies of Model are injected in constructor
  • every DataMapper instance in the application uses same DB connection, no Global State (video) required.

file /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 --- */

  • controller is unaware of model creation details
  • controller is only responsible for wiring and changing the state of elements

file /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 --- */

  • domain object is responsible for validating the given parameters
  • view receives and decides how to present it
  • mapper takes the object and puts in it all the required information from storage ( it doesn't have to be DB .. it could be taken from some file, or an external REST API )

I hope this will help you understand the separation between DB logic and business logic ( and actually , presentation logic too )


Few notes

Model should never extend Database or ORM, because Model is not a subset of them. By extending a class, you are declaring that has all the characteristics of the superclass, but with minor exceptions.

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

Besides the obvious logic-issues, if your Model is tightly coupled with underlaying Database, it makes the code extremely hard to test (talking about Unit Testing (video)).


I personally think, that ORMs are useless and in large project - even harmful. Problem stems from the fact that ORMs are trying to bridge two completely different ways of approaching problems : OOP and SQL.

If you start project with ORM then, after short learning curve, you are able to write simple queries very fast. But by the time you start hitting the ORM's limitations and problems, you are already completely invested in the use of ORM ( maybe even new people were hired , who were really good at your chosen , but sucked at plain SQL ). You end up in situation where every new DB related issue take more and more time to solve. And if you have been using ORM based on ActiveRecord pattern, then the problems directly influence your Models.

Uncle Bob calls this "technical debt".


Few books

loosely related to subject

这篇关于在MVC应用程序中从Model正确调用数据库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆