做了两年的CI开发,一直使用activeRecord来操作数据库。简单,轻巧加方便。最近一个项目交给手下去做,也是采用从数据库设计入手的开发流程,现在已经上线运行。经历了理清需求,设计数据库,在CI中建立model, controller,需求变更,更改数据库,更改代码,增加需求,更改数据库等过程。回头来看,当需要了解全局代码和业务逻辑需求时,还是得从数据库入手,突然有一种厌烦的感脚:对象的属性都在数据库里,而相关的操作在代码中,觉得很分裂。回想多年前开发的C#与JAVA中都有一些好用的ORM的框架,对我来说,ORM最大的好处是隐藏数据库,项目前期设计时根据需求来设计对象,轻装上阵,不必早早地陷入增改删查中;直接利用工具将对象映射到数据库中;数据库的增改删查也都是面向对象的。

可能存在的两点顾虑:

  1. 既然要由对象自动映射到数据库,自然要遵守一套metaData规则才行。
  2. 性能问题,由ORM自动生成sql语句,性能可能不如以前。但对比框架的可读性/可维护性与少许的硬件性能成本,还是选择框架优先。另外,相信ORM的90%的性能影响不大,少许的实在ORM解决不了的问题也能提供原生的sql来解决,总体来说,是利大于弊。

(官方参考文档:http://doctrine-orm.readthedocs.org/en/latest/tutorials/getting-started.html

开始吧,我们的目的是什么,没有蛀牙!好吧,这只是我们的一个目的,还在其它的目的:

  • 根据建立的对象生成数据库;
  • 新增对象持久化到数据库中;
  • 能使用entity来方便查询数据里的信息并达到更改。

1. 在CI下安装doctrine

     a. 最新的CI 3.0已支持composer。在application文件夹下建立composer.son文件如下。(不是在CI根目录下)。 注意autoload参数(不是官方例子中的/src/文件夹) 

          

{
    "require": {
        "doctrine/orm": "2.4.*",
        "symfony/yaml": "2.*"
    },
    "autoload": {
        "psr-0": {"": "models/entities"}
    }
}

 

notes: 上面autoload参数很重要,因为doctrine的启动需要指明entity目录,原始例子中给定的是/src,这里我们放在CI的model/entities目录下,另外,同时创建model/generated 与 models/proxies目录,generated目录用来由数据库生成entity,proxies目录用来存放lazy load需要生成的代码.

     b. 安装doctrine: composer install. 安装后目录结构如下:

      CodeIgniter 下引入ORM Doctrine

2. 配置bootstrap与cli-config

在doctrine中,bootstrap负责创建entityManager,entityManager是整个doctrine对外提供的操作接口: 隐藏数据库接口,提供了对entity的查询,更新及持久化。

在bootstrap中,首先使用composer自带的功能对整个doctrine实现加载。(这里保留了composer功能,实现将doctrine引入到CI修改最小化)

创建基本的entityManager只需要两步:

  1. 使用setup创建config。
  2. 初始化数据库配置对象。

使用数据库连接对象创建entityManager后我们可能及不可耐就想用来从对象来逆向工程数据库了。别急,慢慢来。

 

<?php
// bootstrap.php
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
use Doctrine\Common\ClassLoader,
    Doctrine\DBAL\Logging\EchoSQLLogger,
    Doctrine\Common\Cache\ArrayCache;

date_default_timezone_set("Asia/Shanghai");

require_once "vendor/autoload.php";

// database configuration parameters
if(defined(APPPATH))
{
    require_once APPPATH.'config/database.php';
    $conn = array(
            'driver' => 'pdo_mysql',
            'user' =>     $db['default']['username'],
            'password' => $db['default']['password'],
            'host' =>     $db['default']['hostname'],
            'dbname' =>   $db['default']['database']
        );
}
else
{
    $conn = array(
    'driver' => 'pdo_mysql',
    'user' =>     'root',
    'password' => '',
    'host' =>     '127.0.0.1',
    'dbname' =>   'doctrine'
);
}
//Below can be exected in cli
/*
require_once APPPATH.'vendor/Doctrine/Common/lib/doctrine/common/ClassLoader.php';
$doctrineClassLoader = new ClassLoader('Doctrine',  APPPATH.'libraries');
$doctrineClassLoader->register();
$entitiesClassLoader = new ClassLoader('models', rtrim(APPPATH, "/" ));
$entitiesClassLoader->register();
$proxiesClassLoader = new ClassLoader('Proxies', APPPATH.'models/proxies');
$proxiesClassLoader->register();
*/

// Create a simple "default" Doctrine ORM configuration for Annotations
$isDevMode = true;
$config = Setup::createAnnotationMetadataConfiguration(array(__DIR__."/models/entities"), $isDevMode);
// or if you prefer yaml or XML
//$config = Setup::createXMLMetadataConfiguration(array(__DIR__."/config/xml"), $isDevMode);
//$config = Setup::createYAMLMetadataConfiguration(array(__DIR__."/config/yaml"), $isDevMode);

$cache = new ArrayCache;
$config->setMetadataCacheImpl($cache);
$driverImpl = $config->newDefaultAnnotationDriver(array(__DIR__.'/models/entities'));
$config->setMetadataDriverImpl($driverImpl);
$config->setQueryCacheImpl($cache);

$config->setQueryCacheImpl($cache);

// Proxy configuration
$config->setProxyDir(__DIR__.'/models/proxies');
$config->setProxyNamespace('Proxies');

// Set up logger
//$logger = new EchoSQLLogger;
//$config->setSQLLogger($logger);
$config->setAutoGenerateProxyClasses( TRUE );

// obtaining the entity manager
global $entityManager;
$entityManager = EntityManager::create($conn, $config);
View Code

相关文章: