Php 在MVC应用程序中从模型正确调用数据库?

Php 在MVC应用程序中从模型正确调用数据库?,php,database,model-view-controller,design-patterns,model,Php,Database,Model View Controller,Design Patterns,Model,我正在构建一个微型MVC框架,用于学习/实验和小型项目。我需要了解模型内部的基本知识,因为一个完整的MVC框架和ORM只需要几个数据库调用就太过复杂了 Class Model { } 使用空类时,我必须在何处为数据库调用调用新PDO对象 在模型内部调用查询会是什么样子 另外,我在哪里可以找到MVC的初学者web/book资源(有很多示例代码)?我听过很多术语,比如业务逻辑和数据库逻辑。我记得在某个地方读到,您应该将业务逻辑和数据库逻辑分开。我可以理解这个概念,我只是想知道它看起来像什么,或者它

我正在构建一个微型MVC框架,用于学习/实验和小型项目。我需要了解模型内部的基本知识,因为一个完整的MVC框架和ORM只需要几个数据库调用就太过复杂了

Class Model
{
}
使用空类时,我必须在何处为数据库调用调用
新PDO
对象

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

另外,我在哪里可以找到MVC的初学者web/book资源(有很多示例代码)?我听过很多术语,比如业务逻辑和数据库逻辑。我记得在某个地方读到,您应该将业务逻辑和数据库逻辑分开。我可以理解这个概念,我只是想知道它看起来像什么,或者它们在代码本身意味着什么。我不明白业务逻辑和数据库逻辑应该如何分开,但仍然在模型内部


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

您可以看看手册中提到的数据映射器模型方法


然后,您有一个包含属性的模型,还有一个映射器,它执行实际的数据库交互来填充模型。

显然,您不希望每次创建新模型时都创建新连接,因此您希望单独初始化PDO对象。(我曾经遇到过一个内部MVC框架,其中Model扩展了他们的数据库类!正如你们所想象的,它并不快…)

也许这就是你想要的

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”并查看出现的文章,根据我的经验,不同的框架对mvc的解释有些松散,而且通常有一些偏差。然而,他们通常同意MVC的划分如下:

  • 模型-业务逻辑+数据存储/检索/结构化
  • 视图-数据的表示
  • 控制器-分析请求后对模型调用方法
我用了很多,可以给你几个小例子。请注意,这些都非常简单p

模型: 视图(此处仅显示一个片段):

控制员: 控制器是处理请求的地方。它将分析请求,并找出模型中应该调用的操作(如上面的myUnitActions::executeIndex()

最后一点: 我相信您可以看到上面代码中发生了什么(ORM增加了很多便利)。您让控制器向模型发送请求,模型在您的问题域中运行,并实际从数据库中提取数据,最后是显示数据的视图

作为开发人员,这对您有很多好处,因为它允许更简单、更可靠的测试

Symfony背后的人会给你一本精读的书。这是一件很好的作品

您还应该查看和的代码。他们俩都很优秀。还可以看看ORM的一些类似和

另请参阅维基百科上的文章

警告:
这些帖子中的信息非常过时。它代表了我对MVC模式的理解,就像两年前一样。我一有空就会更新的。可能是本月(2013.09)。

该死的!(2017.11).

模型
本身不应包含任何SQL。曾经它只包含域业务逻辑

我建议的方法是将责任(严格来说不是“业务逻辑”)分离为另外两组构造:和

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

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


一些代码 (仅文件中的相关片段):

  • 我想你知道如何写一个好的构造函数。。如果你有疑问,请阅读
  • 示例中没有名称空间,但应该是
  • 在示例中,任何以
    \uuu
    开头的内容都是
    受保护的
来自
/application/bootstrap.php

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

来自
/framework/classes/ModelFactory.php

  • 只有数据映射器将使用数据库,只有映射器工厂需要连接
  • 模型的所有依赖项都注入到构造函数中
  • 应用程序中的每个DataMapper实例都使用相同的DB连接,不需要

文件
/application/controllers/SomeController.php

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

文件
/application/models/FooModel.php

  • 域对象负责验证给定的参数
  • 查看接收和
    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>
    
    /* --- snip --- */
    
    $connection = new PDO( 'sqlite::memory:' );
    $model_factory = new ModelFactory( $connection );
    
    $controller = new SomeController( $request , $model_factory );
    
    /* --- snip --- */
    
    $controller->{$action}();
    
    /* --- snip --- */
    
    /* --- 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 --- */
    
    }
    
    /* --- 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 --- */
    
    /* --- 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