上例介紹了使用CodeSmith編寫代碼模板的基本方法,本例實現一個較為實用的代碼模板,通過數據庫自動為Yii Framework 生成所需要的ActiveRecord 類。
本例通過修改Yii Framework 開發教程(26) 數據庫-Active Record示例 ,原例是手工編寫 Employee.php ActiveRecord。
首先為工程添加一個C#項目(任意類型,我們只是利用這個項目來包含CodeSmith項目) ,然後添加一個CodeSmith項目和一個CodeSmith模板。然後參考CodeSmith 使用教程(1): 概述 使用Schema Explorer 添加一個 數據連接,本例連接到Chinook數據庫:
創建的代碼模板 PhpActiveRecord.cst 定義個屬性TableName(數據庫表名),復制Yii Framework 開發教程(26) 數據庫-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>
這時就可以通過定義TableName 的屬性給任意數據表生成對應的ActiveRecord PHP類了。 不過這還 是要手工來一個一個來配置表名。 本例通過一個主模板和一個從模板的方式通過連接數據庫自動為所有的表生成對應的 ActiveRecord
使用主從模板的具體用法後面再介紹,簡單的說子模板相當於子函數,主模板類似於主函數可以調用子函數, 主模板通過調用子模板,傳給子模板屬性從而可以生成多個文件。
創建一個代碼模板YiiDataModel.cst 作為主模板,使用子 模板首先需要在主模板中進行注冊才能使用:
<%@ 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); %> <% } %>