Maison >développement back-end >tutoriel php >CodeIgniter 下引出ORM Doctrine

CodeIgniter 下引出ORM Doctrine

WBOY
WBOYoriginal
2016-06-13 12:26:15925parcourir

CodeIgniter 下引入ORM Doctrine

做了两年的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/文件夹) 

          

<span style="color: #000000;">{    </span>"require"<span style="color: #000000;">: {        </span>"doctrine/orm": "2.4.*"<span style="color: #000000;">,        </span>"symfony/yaml": "2.*"<span style="color: #000000;">    },    </span>"autoload"<span style="color: #000000;">: {        </span>"psr-0": {"": "models/entities"<span style="color: #000000;">}    }}</span>

 

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

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

      

2. 配置bootstrap与cli-config

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

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

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

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

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

 

<span style="color: #000000;">php</span><span style="color: #008000;">//</span><span style="color: #008000;"> bootstrap.php</span><span style="color: #000000;">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(</span>"Asia/Shanghai"<span style="color: #000000;">);require_once </span>"vendor/autoload.php"<span style="color: #000000;">;</span><span style="color: #008000;">//</span><span style="color: #008000;"> database configuration parameters</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(defined(APPPATH)){    require_once APPPATH.</span>'config/database.php'<span style="color: #000000;">;    $conn </span>=<span style="color: #000000;"> array(            </span>'driver' => 'pdo_mysql'<span style="color: #000000;">,            </span>'user' =>     $db['default']['username'<span style="color: #000000;">],            </span>'password' => $db['default']['password'<span style="color: #000000;">],            </span>'host' =>     $db['default']['hostname'<span style="color: #000000;">],            </span>'dbname' =>   $db['default']['database'<span style="color: #000000;">]        );}</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{    $conn </span>=<span style="color: #000000;"> array(    </span>'driver' => 'pdo_mysql'<span style="color: #000000;">,    </span>'user' =>     'root'<span style="color: #000000;">,    </span>'password' => ''<span style="color: #000000;">,    </span>'host' =>     '127.0.0.1'<span style="color: #000000;">,    </span>'dbname' =>   'doctrine'<span style="color: #000000;">);}</span><span style="color: #008000;">//</span><span style="color: #008000;">Below can be exected in cli</span><span style="color: #008000;">/*</span><span style="color: #008000;">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();</span><span style="color: #008000;">*/</span><span style="color: #008000;">//</span><span style="color: #008000;"> Create a simple "default" Doctrine ORM configuration for Annotations</span>$isDevMode = <span style="color: #0000ff;">true</span><span style="color: #000000;">;$config </span>= Setup::createAnnotationMetadataConfiguration(array(__DIR__."/models/entities"<span style="color: #000000;">), $isDevMode);</span><span style="color: #008000;">//</span><span style="color: #008000;"> or if you prefer yaml or XML</span><span style="color: #008000;">//</span><span style="color: #008000;">$config = Setup::createXMLMetadataConfiguration(array(__DIR__."/config/xml"), $isDevMode);</span><span style="color: #008000;">//</span><span style="color: #008000;">$config = Setup::createYAMLMetadataConfiguration(array(__DIR__."/config/yaml"), $isDevMode);</span><span style="color: #000000;">$cache </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> ArrayCache;$config</span>-><span style="color: #000000;">setMetadataCacheImpl($cache);$driverImpl </span>= $config->newDefaultAnnotationDriver(array(__DIR__.'/models/entities'<span style="color: #000000;">));$config</span>-><span style="color: #000000;">setMetadataDriverImpl($driverImpl);$config</span>-><span style="color: #000000;">setQueryCacheImpl($cache);$config</span>-><span style="color: #000000;">setQueryCacheImpl($cache);</span><span style="color: #008000;">//</span><span style="color: #008000;"> Proxy configuration</span>$config->setProxyDir(__DIR__.'/models/proxies'<span style="color: #000000;">);$config</span>->setProxyNamespace('Proxies'<span style="color: #000000;">);</span><span style="color: #008000;">//</span><span style="color: #008000;"> Set up logger</span><span style="color: #008000;">//</span><span style="color: #008000;">$logger = new EchoSQLLogger;</span><span style="color: #008000;">//</span><span style="color: #008000;">$config->setSQLLogger($logger);</span>$config-><span style="color: #000000;">setAutoGenerateProxyClasses( TRUE );</span><span style="color: #008000;">//</span><span style="color: #008000;"> obtaining the entity manager</span><span style="color: #000000;">global $entityManager;$entityManager </span>= EntityManager::create($conn, $config);
View Code

 

要让entityManager知道用哪里的对象来进行反向工程,下面这句就尤为重要了:

$config = SetupcreateAnnotationMetadataConfiguration(array(DIR."/models/entities"), $isDevMode);

(在这里也提一下,当从数据库生成entity时当然也要指明entity要放在哪个文件夹了,使用的是EntityGenerator对象,使用该对象的generate方法时指定存放的文件夹就可以了。)

官方文档中使用的是命令行的方法来进行反向工程的,我们这里也依样画葫芦,接下来创建必要的cli-config文件。这个文件相对来讲就没有bootstrap那么长了,总公只有下面两行即可:

 

requireonce "bootstrap.php"<span style="color: #000000;">;</span><span style="color: #0000ff;">return</span> DoctrineORMToolsConsoleConsoleRunnercreateHelperSet(<span style="color: #800080;">$entityManager</span>);

 

反向工程使用vendor/bin/中的doctrine命令:

 

vendor/bin/doctrine

 

其中常用的有如下:

 

vendor/bin/doctrine orm:schema-<span style="color: #000000;">tool:createvendor</span>/bin/doctrine orm:schema-tool:update --force

 

notes: 使用update命令新增字段不会影响原先的数据。

 

好吧,是不是急不可奈要试一试了,输入第一条create命令,咦,不好出现一个错误 “No Metadata Classes to process.” ,心跳加快,冷静,这是正常的,是因为我们还没建立我们想要的entity呢。

建立entity进行反向工程

     1. 在/models/entities中建立我们第一个entity: Product.php

          注意这里的每一个属性都protected属性,对应都有一对mutator(getter与setter)这是有什么用处的呢?由官方文档所说是用来方便doctrine来产生entity,而不是使用entity.field=foo的方式。具体在doctrine如何操作的有待进一步探索。对于主键Id是没有setter方法的,你懂的。

     2. 现在我们只是定义了对象,但数据库构造是需要一些数据库属性的,类名与属性前面的metadata就是来干这个的。(定义的表名,对象属性对应的数据库字段名与字段属性)

 

<span style="color: #000000;">php</span><span style="color: #008000;">//</span><span style="color: #008000;"> src/Product.php</span><span style="color: #008000;">/*</span><span style="color: #008000;">* * @Entity @Table(name="products") *</span><span style="color: #008000;">*/</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Product{    </span><span style="color: #008000;">/*</span><span style="color: #008000;">* @Id @Column(type="integer") @GeneratedValue *</span><span style="color: #008000;">*/</span>    <span style="color: #0000ff;">protected</span> <span style="color: #800080;">$id</span><span style="color: #000000;">;        </span><span style="color: #008000;">/*</span><span style="color: #008000;">* @Column(type="string") *</span><span style="color: #008000;">*/</span>    <span style="color: #0000ff;">protected</span> <span style="color: #800080;">$name</span><span style="color: #000000;">;    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> getId()    {        </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$this</span>-><span style="color: #000000;">id;    }    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> getName()    {        </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$this</span>-><span style="color: #000000;">name;    }    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> setName(<span style="color: #800080;">$name</span><span style="color: #000000;">)    {        </span><span style="color: #800080;">$this</span>->name = <span style="color: #800080;">$name</span><span style="color: #000000;">;    }}</span>

 

     3. 下面我们就可以使用下面命令来进行反向工程了,是不是很兴奋!

          

vendor/bin/doctrine orm:schema-tool:update --force --dump-sql

 

     4. 下面我们就来建立一段脚本来生成一个product并将其插入数据(持久化),你就会发现如何面向对象,隐藏数据库操作的了。

  1. <span style="color: #000000;">php </span><span style="color: #0000ff;">require_once</span> "bootstrap.php"<span style="color: #000000;">;</span><span style="color: #800080;">$newProductName</span> = <span style="color: #800080;">$argv</span>[1<span style="color: #000000;">];</span><span style="color: #800080;">$product</span> = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Product();</span><span style="color: #800080;">$product</span>->setName(<span style="color: #800080;">$newProductName</span><span style="color: #000000;">);</span><span style="color: #800080;">$entityManager</span>->persist(<span style="color: #800080;">$product</span><span style="color: #000000;">);</span><span style="color: #800080;">$entityManager</span>-><span style="color: #008080;">flush</span><span style="color: #000000;">();</span><span style="color: #0000ff;">echo</span> "Created Product with ID " . <span style="color: #800080;">$product</span>->getId() . "\n";

         5. 下面我们就要使用cli来运行这段php脚本调用ORM框架来插入product了。

    1. $<span style="color: #000000;"> php createproduct.php ORM </span>$ php createproduct.php DBAL

      查看数据库,是不是发现了新的数据已经插入了,ok大功告成。

      1楼winwill2012
      谢谢分享。,Java并发包学习:,http://qifuguang.me/categories/Java%E5%B9%B6%E5%8F%91%E5%8C%85%E5%AD%A6%E4%B9%A0/
Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn