CodeSmith 使用教程(3): 自动生成Yii Framework ActiveRecord

小虾米 阅读:630 2021-04-01 09:57:06 评论:0


上例介绍了使用CodeSmith编写代码模板的基本方法,本例实现一个较为实用的代码模板,通过数据库自动为Yii Framework生成所需要的ActiveRecord 类。
本例通过修改Yii Framework 开发教程(26) 数据库-Active Record示例 ,原例是手工编写Employee.php ActiveRecord。

首先为工程添加一个C#项目(任意类型,我们只是利用这个项目来包含CodeSmith项目),然后添加一个CodeSmith项目和一个CodeSmith模板。然后参考CodeSmith 使用教程(1): 概述 使用Schema Explorer 添加一个数据连接,本例连接到Chinook数据库:

20130104001

创建的代码模板 PhpActiveRecord.cst 定义个属性TableName(数据库表名),复制Yii Framework 开发教程(26) 数据库-Active Record示例中Employee.php的定义并使用属性,代码如下:

  1. <%@ Template Language="C#" TargetLanguage="PHP" Debug="False" %>  
  2.   
  3. <%@ Property Name="TableName" Type="System.String" Description="Table name" %>  
  4.   
  5. <?php  
  6.   
  7. class <%= TableName %> extends CActiveRecord  
  8. {  
  9.     public static function model($className=__CLASS__)  
  10.     {  
  11.         return parent::model($className);  
  12.     }  
  13.   
  14.     public function tableName()  
  15.     {  
  16.         return '<%= TableName %>';  
  17.     }  
  18. }  
  19.   
  20. ?>  
  21.   
  22. <script runat="template">  
  23.   public override string GetFileName() {  
  24.     return TableName + ".php" ;  
  25. }  
  26. </script>  
<%@ 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 作为主模板,使用子模板首先需要在主模板中进行注册才能使用:

  1. <%@ Register Name="ActiveRecord" Template="PhpActiveRecord.cst" MergeProperties="false"  %>  
<%@ Register Name="ActiveRecord" Template="PhpActiveRecord.cst" MergeProperties="false"  %> 

完整代码如下:

  1. <%@ CodeTemplate Language="C#" TargetLanguage="Text"  
  2.   Description="List all database tables" %>  
  3. <%@ Import Namespace="System.IO" %>  
  4. <%@ Property Name="SourceDatabase" Type="SchemaExplorer.DatabaseSchema"  
  5.   Category="Context" Description="Database containing the tables." %>  
  6.   
  7. <%@ Register Name="ActiveRecord" Template="PhpActiveRecord.cst"  
  8.  MergeProperties="false"  %>  
  9. <%@ Assembly Name="SchemaExplorer" %>  
  10. <%@ Import Namespace="SchemaExplorer" %>  
  11.   
  12. <script runat="template">  
  13. public string FirstLetterToUpper(string str)  
  14. {  
  15.     if (str != null)  
  16.     {  
  17.         if(str.Length > 1)  
  18.             return char.ToUpper(str[0]) + str.Substring(1);  
  19.         else  
  20.             return str.ToUpper();  
  21.     }  
  22.     return str;  
  23. }  
  24.   
  25. </script>  
  26.   
  27. <% for (int i = 0; i < SourceDatabase.Tables.Count; i++) { %>  
  28.    <%  string name= FirstLetterToUpper(SourceDatabase.Tables[i].Name); %>  
  29.    <%  string filename= @"../ActiveRecordDemo/protected/models/"+name+".php"; %>  
  30.      // instantiate the sub-template  
  31.     <%  ActiveRecord activeRecord = this.Create<ActiveRecord>();%>  
  32.     <%  activeRecord.TableName= name; %>  
  33.     <%  activeRecord.RenderToFile(filename,true); %>  
  34. <% } %>  
<%@ 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#函数,主要是把数据库表名的第一个字母变为大写(纯C#代码)。 SchemaExplorer 为CodeSmith提供的数据库访问库,可以用来获取数据库Schema的信息,如包含的表名,字段属性,主键外键等(后面具体介绍)
在主模板中,通过ActiveRecord 来访问子模板(名字ActiveRecord为注册子模板时定义) ,使用this.create创建子模板实例,然后传入TableName属性,调用RenderToFile 将子模板的结果写道指定的文件中。

此时在CodeSmith.csp 中添加主模板,配置数据库为Chinook,然后生成代码

  1. Rendering output 'YiiDataModel'...  
  2.   
  3.   Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Album.php  
  4.   Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Artist.php  
  5.   Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Customer.php  
  6.   Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Employee.php  
  7.   Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Genre.php  
  8.   Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Invoice.php  
  9.   Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Invoiceline.php  
  10.   Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Mediatype.php  
  11.   Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Playlist.php  
  12.   Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Playlisttrack.php  
  13.   Generated: D:\tmp\ActiveRecordDemo\ActiveRecordDemo\protected\models\Track.php  
  14.   Generated: D:\tmp\ActiveRecordDemo\CodeSmith\YiiDataModel.txt  
  15. Done rendering outputs: 1 succeeded, 0 failed, 0 skipped (1111ms).  
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 (1111ms). 

刷新项目可以看到自动生成的代码文件

20130104002

本例只是为每个数据表生成最简单的ActiveRecord,如果需要生成关联ActiveRecord,可以进一步根据表之间的关系为每个ActiveRecord 生成所需的relations 方法,后面有时间进一步介绍。

本例下载

声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号