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



上例介绍了使用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 方法,后面有时间进一步介绍。

本例下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值