我正在构建一个微小的MVC框架,用于学习/实验和小项目目的。我需要找出模型内部的基础知识,因为完整的MVC框架和ORM对于几个数据库调用来说是过度的。
Class Model
{
}
使用空类,我必须在哪里调用new PDO
对象进行数据库调用?
在模型中调用查询的内容是什么?
此外,我在哪里可以找到初学者的网络/书籍资源到MVC(有很多示例代码)?我听过很多术语,比如业务逻辑和数据库逻辑。我记得在某处你应该将业务逻辑和数据库逻辑分开。我可以在某种程度上理解这个概念,我只是想知道它在代码本身中的含义或含义。我很困惑业务逻辑和数据库逻辑应该如何分离,但仍然在模型中。
我主要是寻找代码/逻辑示例作为答案,除了后一段。
答案 0 :(得分:21)
警告:
这篇文章中的信息极度过时。它代表了我对MVC模式的理解,因为它超过了2年前。当我接触它时它会更新。可能本月(2013.09)。
该死的! (2017.11)。 子>
Model
本身不应包含任何 SQL。永远。它仅用于包含域业务逻辑。
我建议的方法是将责任(不是严格的“业务逻辑”)分成另外两组构造:Domain Objects和Data Mappers。
例如,如果您正在制作博客,那么该模型将不会发布。相反,模型很可能是博客,这个模型将处理多个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 --- */
来自/framework/classes/ModelFactory.php
档案 档案 我希望这可以帮助您理解数据库逻辑和业务逻辑之间的分离(实际上,也就是表示逻辑) 模型永远不应该扩展数据库或ORM,因为模型不是它们的子集。通过扩展一个类,您声明它具有超类的所有特征,但有一些例外。 除了明显的逻辑问题之外,如果你的模型与底层数据库紧密结合,它会使代码极难测试(谈论Unit Testing (video))。 我个人认为,ORM在大型项目中毫无用处 - 甚至是有害的。问题源于ORM正在尝试桥接两种完全不同的方法来解决问题:OOP和SQL。 如果您使用ORM启动项目,那么在经过短暂的学习曲线后,您可以非常快速地编写简单查询。但是当你开始点击 ORM的局限性和问题时,你已经完全投资于ORM的使用(甚至可能招聘了新人,他们真的很擅长你的选择,但是在平原上很糟糕SQL)。最终,每个新的数据库相关问题都需要花费越来越多的时间来解决。如果你一直在使用基于ActiveRecord模式的ORM,那么这些问题会直接影响你的模型。 Uncle Bob称之为“技术债务”。 与主题松散相关/* --- 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('FooBar');
$mapper = $this->_mapper_factory('FooMapper');
$something->set_type( $param );
$mapper->use_filter( $filter )->fetch( $something );
return $something;
}
/* --- snip --- */
很少注意到
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
很少有书
答案 1 :(得分:1)
根据我的经验,不同的框架会稍微松散地解释MVC,并且通常会有一些偏差。然而,他们通常同意MVC如下划分:
我经常使用Symfony,可以给你一些小例子。请注意,这些都非常简单。 :P
class MyUnitTable extends Doctrine_Table
{
// .. various other pieces of code added by Symfony ... //
public function getForAccount( Account $_account ) {
$q = $this
->createQuery('e')
->leftJoin('e.User u')
->leftJoin('u.Profile p')
->leftJoin('p.Account a')
->where('a.accountid = ?', $_account->getAccountid());
return $q->execute();
}
}
class myUnitActions extends sfActions
{
public function executeIndex(sfWebRequest $request)
{
$this->units = Doctrine_Core::getTable('MyUnit')->getForAccount($foo);
}
}
<div id="my-unit-list-container">
<ul>
<?php foreach( $units as $unit ): ?>
<li><?php echo $unit->getName(); ?></li>
<?php endforeach; ?>
</ul>
</div>
控制器是处理请求的地方。它将分析请求并找出应该调用的模型中的哪个动作(例如,来自上面的myUnitActions :: executeIndex())。
我确信你可以看到上面的代码中发生了什么(ORM增加了很多便利)。您让控制器向模型分派请求,模型使用您的问题域运行,实际上从数据库中提取数据,最后是显示数据的视图。
作为开发人员,这对您有很多好处,因为它允许更简单,更可靠的测试等。
优秀的读者将是来自Symfony背后的人的21 Days With Jobeet指南。这是一件很棒的工作。
您还应该查看Symfony和Zend的代码。他们都是出类拔萃的。还可以查看一些ORM,例如Doctrine和Propel。
另见MVC上的维基百科文章。
答案 2 :(得分:0)
您可以查看Zend framework model手册
引用的数据映射器模型方法然后你有一个包含属性的模型,并有一个映射器,它执行实际的数据库交互以填充模型。
答案 3 :(得分:0)
显然,您不希望每次创建新模型时都创建新连接,因此您需要单独初始化PDO对象。 (一旦Model扩展了他们的数据库类,我确实碰到了一个内部MVC框架!你可以想象它并不快......)
也许这样的东西是你想要的?
abstract class Model
{
protected $db = NULL;
public function __construct (PDO $db)
{
$this -> db = $db;
}
}
使用示例
class Article extends Model
{
public $props = array ();
private function getPage ($id)
{
$q = $this -> db -> prepare ('select * from pages where pageId = :pageId');
$q -> execute (array ('pageId' => $id));
$ret = $res -> fetchAll ();
return ($this -> props = $ret);
}
}
$db = new PDO ('dsn goes here');
$page = new Article ($db);
$page -> getPage (1234);
至于寻找例子?尝试谷歌搜索“php mvc”并查看出现的文章