Class Model { }
另外,在哪里可以找到一个初学者的web / book资源到MVC(有很多示例代码)?我听说过很多术语,如业务逻辑和数据库逻辑.我记得阅读某个地方你应该分离业务逻辑和数据库逻辑.我可以理解这个概念,我只是想知道它的外观或代码本身的含义.我很困惑如何将业务逻辑和数据库逻辑分开,但仍然在模型中.
我主要寻找代码/逻辑示例作为答案,除了后面的段落.
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).
模型本身不应该包含任何sql.永远.这意味着只包含域业务逻辑.
我建议的方法是把不是严格的“业务逻辑”的责任分成另外两套其他的组合:Domain Objects和Data Mappers.
例如,如果您正在制作博客,则模型不会被发布.相反,该模型最有可能是博客,并且该模型将处理多个域对象:Post,Comment,User和其他对象的多个实例.
在您的模型中,域对象不应该知道如何将自己存储在数据库中.或者甚至意识到任何形式的存储的存在.这是Data Mappers的责任.所有你应该在模型中做的是调用$mapper-> store($comment);.数据映射器应该知道如何存储一个特定类型的域对象,并且赢取哪个表放置信息(通常单个域对象的存储实际上会影响多个表).
一些代码
(仅文件相关的片段):
>我假设你知道如何写一个好的构造函数..如果你有疑问,请阅读this article
没有什么是命名的例子,但它应该是
>以示例中的_开头的任何东西都被保护
来自/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实例都使用相同的DB连接,不需要Global State (video).
文件/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 --- */
>域对象负责验证给定的参数
>视图接收并决定如何呈现
> mapper将对象放入存储器中(它不一定是DB ..它可以从一些文件或外部REST API中获得)所需的所有信息
我希望这将有助于您了解数据库逻辑与业务逻辑之间的分离(实际上也是演示逻辑)
很少的笔记
模型不应该扩展数据库或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
除了明显的逻辑问题,如果您的模型与底层数据库紧密结合,它使得代码非常难以测试(谈论Unit Testing (video)).
我个人认为,ORM是无用的,在大型项目中 – 甚至是有害的.问题起因于ORM正试图跨接两种完全不同的方式来解决问题:OOP和sql.
如果您使用ORM启动项目,那么在短暂的学习曲线之后,您可以很快地编写简单的查询.但是当您开始打击ORM的限制和问题时,您已经完全投入使用ORM(即使是新人也被雇用,他们真的擅长您的选择,但是在纯sql中吸引人).您最终会遇到每个新的DB相关问题需要越来越多的时间来解决的情况.如果您已经使用基于ActiveRecord模式的ORM,那么问题会直接影响到您的模型.
Uncle Bob称这是“技术债务”.
几本书
与主题松散相关
> Patterns of Enterprise Application Architecture
> Agile Software Development,Principles,Patterns,and Practices
> SQL Antipatterns: Avoiding the Pitfalls of Database Programming
> PHP Object-Oriented Solutions
> PHP in Action