CodeIgniter での ORM Doctrine の導入
は 2 年間 CI 開発を行っており、データベースの操作に activeRecord を使用してきました。シンプルで軽くて便利です。最近のプロジェクトも私の部下に引き継がれ、データベース設計から始まる開発プロセスが採用され、現在はオンラインで稼働しています。要件の明確化、データベースの設計、CIでのモデルとコントローラーの確立、要件の変更、データベースの変更、コードの変更、要件の追加、データベースの変更などのプロセスを経てきました。振り返ってみると、グローバル コードとビジネス ロジックの要件を理解する必要があるとき、依然としてデータベースから始めなければならないことに、突然退屈を感じます。オブジェクトの属性はすべてデータベース内にあり、関連する操作はコード内にあります。 、非常に断片的に感じられます。何年も前に C# と JAVA で開発された便利な ORM フレームワークがいくつかあったことを思い出します。私にとって ORM の最大の利点は、プロジェクトの初期段階で、ニーズに応じてオブジェクトを設計できることです。変更、削除、クエリは進行中であり、データベースへのオブジェクトの追加、変更、削除、クエリも直接使用されます。オブジェクト指向。
考えられる 2 つの懸念事項:
(公式参考ドキュメント: http://doctrine-orm.readthedocs.org/en/latest/tutorials/getting-started.html)
始めましょう、私たちの目標は何ですか、虫歯をなくしましょう!これは目的の 1 つにすぎず、他にも目的があります。
a. 最新の CI 3.0 はすでに Composer をサポートしています。 次のようにアプリケーションフォルダーに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>
注: doctrine の起動ではエンティティ ディレクトリを指定する必要があるため、上記の autoload パラメータは非常に重要です。元の例は /src です。ここでは、これを CI の model/entities ディレクトリに置きます。さらに、model/generated ディレクトリと models/proxies ディレクトリを同時に作成します。生成されたディレクトリは、データベースからエンティティを生成するために使用されます。プロキシ ディレクトリは、遅延ロードによって生成される必要があるコードを保存するために使用されます。
b. doctrine をインストールします: インストール後のディレクトリ構造は次のとおりです:
>2. ブートストラップと cli-config を設定する
doctrine では、ブートストラップは、entityManager によって提供される外部操作インターフェイスを作成します。教義全体: データベース インターフェイスを非表示にし、エンティティ、更新、永続性に対するクエリを提供します。基本的な EntityManager の作成には、次の 2 つのステップのみが必要です:
セットアップを使用して構成を作成します。
<?<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);
要让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呢。
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并将其插入数据(持久化),你就会发现如何面向对象,隐藏数据库操作的了。
<?<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了。
$<span style="color: #000000;"> php createproduct.php ORM </span>$ php createproduct.php DBAL
查看数据库,是不是发现了新的数据已经插入了,ok大功告成。