上例介紹了使用 CodeSmith 編寫代碼模板的基本方法,本例實(shí)現(xiàn)一個(gè)較為實(shí)用的代碼模板,通過數(shù)據(jù)庫自動(dòng)為 Yii Framework 生成所需要的 ActiveRecord 類。
本例通過修改 Yii Framework 開發(fā)教程(26) 數(shù)據(jù)庫-Active Record 示例,原例是手工編寫 Employee.php ActiveRecord。
首先為工程添加一個(gè) C# 項(xiàng)目(任意類型,我們只是利用這個(gè)項(xiàng)目來包含 CodeSmith 項(xiàng)目),然后添加一個(gè) CodeSmith 項(xiàng)目和一個(gè) CodeSmith 模板。然后參考 CodeSmith 使用教程(1): 概述 使用Schema Explorer 添加一個(gè)數(shù)據(jù)連接,本例連接到 Chinook 數(shù)據(jù)庫:
創(chuàng)建的代碼模板 PhpActiveRecord.cst 定義個(gè)屬性 TableName(數(shù)據(jù)庫表名),復(fù)制 Yii Framework 開發(fā)教程(26) 數(shù)據(jù)庫-Active Record 示例中 Employee.php 的定義并使用屬性,代碼如下:
<%@ Template Language="C#" TargetLanguage="PHP" Debug="False" %>
<%@ Property Name="TableName" Type="System.String" Description="Table name" %>
<?php
class <%= TableName %> extends CActiveRecord
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return '<%= TableName %>';
}
}
?>
<script runat="template">
public override string GetFileName() {
return TableName + ".php" ;
}
</script>
這時(shí)就可以通過定義 TableName 的屬性給任意數(shù)據(jù)表生成對(duì)應(yīng)的 ActiveRecord PHP 類了。 不過這還是要手工來一個(gè)一個(gè)來配置表名。 本例通過一個(gè)主模板和一個(gè)從模板的方式通過連接數(shù)據(jù)庫自動(dòng)為所有的表生成對(duì)應(yīng)的 ActiveRecord
使用主從模板的具體用法后面再介紹,簡單的說子模板相當(dāng)于子函數(shù),主模板類似于主函數(shù)可以調(diào)用子函數(shù),主模板通過調(diào)用子模板,傳給子模板屬性從而可以生成多個(gè)文件。
創(chuàng)建一個(gè)代碼模板 YiiDataModel.cst 作為主模板,使用子模板首先需要在主模板中進(jìn)行注冊(cè)才能使用:
<%@ Register Name="ActiveRecord" Template="PhpActiveRecord.cst" MergeProperties="false" %>
完整代碼如下:
<%@ CodeTemplate Language="C#" TargetLanguage="Text"
Description="List all database tables" %>
<%@ Import Namespace="System.IO" %>
<%@ Property Name="SourceDatabase" Type="SchemaExplorer.DatabaseSchema"
Category="Context" Description="Database containing the tables." %>
<%@ Register Name="ActiveRecord" Template="PhpActiveRecord.cst"
MergeProperties="false" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
<script runat="template">
public string FirstLetterToUpper(string str)
{
if (str != null)
{
if(str.Length > 1)
return char.ToUpper(str[0]) + str.Substring(1);
else
return str.ToUpper();
}
return str;
}
</script>
<% for (int i = 0; i < SourceDatabase.Tables.Count; i++) { %>
<% string name= FirstLetterToUpper(SourceDatabase.Tables[i].Name); %>
<% string filename= @"../ActiveRecordDemo/protected/models/"+name+".php"; %>
// instantiate the sub-template
<% ActiveRecord activeRecord = this.Create<ActiveRecord>();%>
<% activeRecord.TableName= name; %>
<% activeRecord.RenderToFile(filename,true); %>
<% } %>
FirstLetterToUpper 為C#函數(shù),主要是把數(shù)據(jù)庫表名的第一個(gè)字母變?yōu)榇髮懀?C# 代碼)。
SchemaExplorer 為 CodeSmith 提供的數(shù)據(jù)庫訪問庫,可以用來獲取數(shù)據(jù)庫 Schema 的信息,如包含的表名,字段屬性,主鍵外鍵等(后面具體介紹)
在主模板中,通過 ActiveRecord 來訪問子模板(名字 ActiveRecord 為注冊(cè)子模板時(shí)定義) ,使用 this.create 創(chuàng)建子模板實(shí)例,然后傳入 TableName 屬性,調(diào)用 RenderToFile 將子模板的結(jié)果寫道指定的文件中。
此時(shí)在 CodeSmith.csp 中添加主模板,配置數(shù)據(jù)庫為 Chinook,然后生成代碼
Rendering output 'YiiDataModel'...
Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Album.php
Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Artist.php
Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Customer.php
Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Employee.php
Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Genre.php
Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Invoice.php
Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Invoiceline.php
Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Mediatype.php
Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Playlist.php
Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Playlisttrack.php
Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Track.php
Generated: D:\tmp\ActiveRecordDemo\CodeSmith\YiiDataModel.txt
Done rendering outputs: 1 succeeded, 0 failed, 0 skipped (1
刷新項(xiàng)目可以看到自動(dòng)生成的代碼文件
本例只是為每個(gè)數(shù)據(jù)表生成最簡單的 ActiveRecord,如果需要生成關(guān)聯(lián) ActiveRecord,可以進(jìn)一步根據(jù)表之間的關(guān)系為每個(gè) ActiveRecord 生成所需的 relations 方法,后面有時(shí)間進(jìn)一步介紹。
本例下載
更多建議: