TFAPI框架属于共享型框架,也就是说多个项目可以共享一套框架。
所以,我们安装部署需要分两步,先安装框架,再部署项目。
部署多个项目可重复项目部署操作步骤,框架不用反复安装。
加入QQ群 263806521(TFAPI框架PHP技术)
在群共享文件内找到最新版本 TFAPI-1.9.5-Beta2-GBK.zip 或 TFAPI-1.9.5-Beta2-UTF8.zip
下载下来上传到服务器上
我们假定Apache根目录在 /var/www/html/ 下,我们下载的是 UTF-8 版本的框架。
建立新目录 /var/www/html/tongfuapi,将压缩包内的内容解压到该目录下
我们假定我们要建立的项目名称为 project1。
复制 /var/www/html/tongfuapi/UTF-8/TFAPI/sample/ 到 /var/www/html/project1/
复制 /var/www/html/tongfuapi/UTF-8/TFAPI/etc/jtongfu/ 到 /var/www/html/project1/jtongfu/ 下面
授权 /var/www/html/project1/WEB-APP/ 目录可写权限
授权 /var/www/html/project1/WEB-APP/smarty/coms/ 目录可写权限
这样就完成了项目的安装部署!
---- UTF-8 --------- TFAPI -------------- api -------------- cache -------------- common -------------- data -------------- datetime -------------- db -------------- dbj -------------- driver -------------- etc -- 第三方资源 -------------- excel -------------- html -------------- image -------------- ini -------------- io -------------- lang -------------- library -------------- payment_method -------------- sample -- 最简项目 -------------- socket -------------- text -------------- xml ---- GBK --------- TFAPI -------------- (结构同UTF-8)
sample ---- api -- 接口 ---- css -- 样式表 ---- fonts -- 字体 ---- images -- 图片 ---- js -- 脚本 ---- WEB-APP -- 系统目录(非用户访问目录) --------- classes -- 用户自定义模块 -------------- cache_source -- 缓存 ------------------- cache_src_test.inc.php -- 缓存示例 -------------- cache_source.inc.php -- 缓存入口 -------------- route -- 路由目录 -------------- view -- 视图目录 -------------- sample_system.inc.php -- 系统模块 -------------- keywords.inc.php -- 字典库 --------- smarty -- 模板目录 -------------- tpls -- 模板源目录 -------------- coms -- 模板编译目录 --------- detector.php -- 探针(用于自动生成配置信息) --------- web.inc.php -- 配置文件 ---- .htaccess -- Apache配置文件 ---- .root.php -- 根文件(每个含有php脚本的目录都应该有这个文件,且统一指向这个文件) ---- baseRouteUrlMap.php -- 路由控制器 ---- index.php -- 索引文件
文件名称为 模型名称_action.inc.php,例如:user_action.inc.php
类名称为 tf_模型名称_action,例如:tf_user_action
类必须继承父类 tf_common_action
模型文件必须存在 WEB-APP/classes/ 下面,例如:WEB-APP/classes/user_action.inc.php
目前引入模型的方法是通过函数 using('模型名称'),今后会使用 autoload 实现
项目采用 Smarty 作为模板引擎,Smarty 模板分为两个主要部分,一个是模板文件,一个是编译文件
这里我们只对模板文件和编译文件的存储位置进行了限制
模板文件必须存储到 WEB-APP/smarty/tpls/ 下面
编译文件必须存储到 WEB-APP/smarty/coms/ 下面(只需授权可写权限即可)
启用路由功能后,视图程序需要放入对应的目录下
请求路径
/user/list?pn=1
业务程序存放路径
WEB-APP/classes/view/user/list.inc.php
模板存放路径
WEB-APP/smarty/tpls/user/list.html
业务程序代码,必须有对象名称为 请求资源_page 的class定义
class list_action extends table_action_ctl {
    public function __construct($name){
        parent::__construct($name);
    }
}
class list_page extends form_action3{
    public $loginUser;
    public $actionObj;
    protected function process(){
    }
}模板代码,没有任何硬性规范
<% include file="header.htm" %> <h1 style="text-align:center;">你好!TFAPI!!!</h1> <% include file="footer.htm" %>
路由功能基于Web服务器的地址重定向,我们以 apache 的 rewrite 模块举例
# enable rewrite for base route service
RewriteEngine On
# make base route api
RewriteCond %{REQUEST_URI} !(\.(js|css|jpg|jpeg|pjpeg|png|gif))$ [NC] ### resource extension
RewriteCond %{REQUEST_URI} !(jtongfu|js|css|fonts|images|files|uplaods|extends)\/ [NC] ### resource directories
RewriteCond %{REQUEST_URI} !(baseRouteUrlMap|server\-status|server\-info) [NC] ### route script and server special
# page
RewriteRule ^(.*)$ baseRouteUrlMap.php?$1 [NC]路由配置文件是 baseRouteUrlMap.php,通过Web服务器的重定向我们已经将所有模块功能请求都转入了这个 PHP 程序,接下来就是在这个 PHP 程序里面配置我们的路由规则
// import route
define('WEB_DOC_ROOT', dirname(__FILE__). "/");
define('WEB_APP_ROOT', WEB_DOC_ROOT. "WEB-APP/");
require(WEB_APP_ROOT. "router.php");
// start route
$myRouteParserObj = new tfapi_baseRoute_parser();
if($myRouteParserObj->matchUri("api")){
    $myRouteParserObj->map("api");
}
else if($myRouteParserObj->matchUri("admin")){
    $myRouteParserObj->map("admin");
}
else{
    $myRouteParserObj->map("default");
}没有条件的 map 方法调用就是默认入口路由,匹配所有URI地址
我们可以设置多个入口,通过 URI 的前缀匹配进行部署,通过路由对象的 matchUri 方法进行测试,通过路由对象的 map 方法进行部署多入口路由
启用路由功能后,请求地址的响应程序需要安装映射视图的要求进行设置。
请参考视图大类下面的映射视图子类的介绍。
旧版本的框架没有路由支持,需要 1.9.5+ 版本才能使用!!!
入口其实就是一个基类,这个基类继承于系统对象,根据不同的用途分为如下几类:
入口程序文件名称为 入口名称.inc.php,存放在如下目录下
WEB-APP/classes/route/
入口程序对象名称为 入口名称_route,且扩展于 html_frame、api_frame 之一的基类
视图类入口继承系统对象 html_frame,简单理解就是基于 html_frame 的对象是支持视图渲染的
我们使用的模板是 Smarty,对象会包含 $this->smarty 对象实例
对象有处理 HTML 头信息的函数,用来选择 JS 引擎,载入 JS,载入 CSS,输出 META 等等
示例
require(WEB_DOC_ROOT. ".root.php");
require(WEBAPP_ROOT);
linking('html.form_action3');
class demo_route extends html_frame{
    public function __construct($prefixUri, $mapUri){
        // init page
        $this->init_page($prefixUri, $mapUri, array(
        ));
    }
    public function load(){
        // load page
        $this->load_page();
    }
}接口类入口基础系统对象 api_frame,简单理解急速基于 api_frame 的对象只用来输出数据的
接口类不包括模板,HEAD处理,JS处理,CSS处理等等
示例
require(WEB_DOC_ROOT. ".root.php");
require(WEBAPP_ROOT);
class demo_route extends api_frame{
    public function __construct($prefixUri, $mapUri){
        // init page
        $this->init_api($prefixUri, $mapUri, array(
        ));
    }
    public function load(){
        // load page
        $this->load_api();
    }
}我们还有 ajax_frame,用来输出 xml 数据的对象
现在主流是 json,因此我们暂时不做介绍
配置数据源需要在 WEB-APP/web.inc 里配置,示例如下
env_ctl::adddbs("mysql","driver=mysql2;server=localhost;uid=root;pwd=abcdef;database=test;charset=LATIN1;tbl_prefix=;tbl_lastfix=;");旧版本代码需要在 config.inc 里通过 define 常量的方法定义
define(MYSQL_CFG, "driver=mysql;server=localhost;uid=root;pwd=abcdef;database=test;charset=LATIN1;tbl_prefix=;tbl_lastfix=;");
同时需要在下面的 $_CFG 里绑定,示例如下
$_CFG['DBS_mysql'] = MYSQL_CFG;
系统对象提供了一个属性 $this->dbo,这个属性是对象 adodb 的实例,用来操作数据库
如果系统包括多个数据库源,则 $this->dbo 指向的是第一个数据源,其他数据源要通过 $this->dbo->others['数据源名称'] 访问
这个属性在前面提供的模板里被指向了属性 $this->dbObj,理论上你在任何地方都可以访问到这个对象
一般情况下我们的开发的项目都会有开发环境、测试环境、灰度环境、生成环境这样几个不同的环境。这些环境下的代码是一样的,而数据库等外部资源是不同的。
我们为了使用同一套配置代码,就需要在 WEB-APP/web.inc 里通过switch分开不同环境下的参数设定。
环境控制参数 env_ctl::getenv('mode') 在 WEB-APP/config.inc 里设定,WEB-APP/config.inc 是系统自动生成的不会受项目代码影响。
switch (env_ctl::getenv('mode')){
    case 'develop':
        env_ctl::adddbs("mysql","driver=mysql2;server=localhost;uid=root;pwd=abcdef;database=fj;charset=GBK;tbl_prefix=;tbl_lastfix=;");
        break;
    default:
        env_ctl::adddbs("mysql","driver=mysql2;server=localhost;uid=root;pwd=abcdef;database=fj;charset=GBK;tbl_prefix=;tbl_lastfix=;");
        break;
}这里面的 switch 交换语句设定了两个数据源,一个是 develop 一个是默认的,通过 env_ctl::getenv('mode') 控制。
develop 用于开发环境,默认设定用于生产环境,控制变量在 WEB-APP/config.inc 配置文件当中指定。
env_ctl::setenv('mode','develop');数据源设定好了以后,就可以在代码当中使用 $this->dbObj 这个数据库操作对象来进行数据库的实际操作了。
下面我们逐一介绍数据库操作对象ADODB的各种方法:
语法:
$this->dbObj->table($Sql)
说明:
该命令可将查询语句选择的所有记录数据全部提取出来,放入一个二维数组当中,每一个子数组就是一行数据。
示例:
$userInfos = $this->dbObj->table("select uId, uName from users");
/*
$userInfos = array(
        0=>array('uId'=>123, 'uName'=>"Zhang 3"),
        1=>array('uId'=>456, 'uName'=>"Li 4"),
        2=>array('uId'=>789, 'uName'=>"Wang 5"),
    );
*/假设 users 表只有3行数据,这个操作会将全部数据取出来放入 $userInfos 数组内,其数据格式为
语法:
$this->dbObj->row($Sql);
说明:
该命令可将查询语句选择的记录集的第一行数据提取出来,放入一个一维数组当中,该一维数组就是第一行数据。
示例:
$userInfo = $this->dbObj->row("select uId, uName from users");
/*
$userInfo = array('uId'=>123, 'uName'=>"Zhang 3");
*/假设 users 表只有3行数据,这个操作只会将第一行数据取出来放入 $userInfo 数组内,其数据格式为
语法:
$this->dbObj->scalar($Sql);
说明:
该命令可将查询语句选择的记录集的第一行数据的第一个字段的值提取出来,返回给一个变量。
示例:
$userId = $this->dbObj->scalar("select uId, uName from users");
/*
$userId = 123;
*/假设 users 表只有3行数据,这个操作只会将第一行数据的第一个字段取出来放入 $userId 变量,其数据格式为
语法:
$this->dbObj->to_array($Sql);
说明:
该命令可将查询语句选择的所有记录查询出来,并使用第一个字段的值作为数组键,使用第二个字段的值作为数组的值,拼凑成一个一维数组。第三个及后面的字段会被忽略。
示例:
$userArr = $this->dbObj->to_array("select uId, uName from users");
/*
$userArr = array(
        123=>"Zhang 3",
        456=>"Li 4",
        789=>"Wang 5",
    );
*/假设 users 表只有3行数据,这个操作会将全部数据取出来该规则放入 $userArr 数组内,其数据格式为
语法:
$this->dbObj->to_list($Sql);
说明:
该命令可将查询语句选择的所有记录查询出来,并使用第一个字段的值拼凑成一个以逗号分隔的序列。类似 [数字1], [数字2], [数字3]... [数字n] 的序列。第二个及后面的字段会被忽略。
示例:
$userIdList = $this->dbObj->to_list("select uId from users");
/*
$userIdList = "123, 456, 789";
*/假设 users 表只有3行数据,这个操作会将全部数据取出来该规则放入 $userIdList 变量内,其数据格式为
语法:
$this->dbObj->execute($Sql);
说明:
该命令用于提交所有更改性质的Sql语句,包括Create、Drop、Insert、Update、Delete、Grant等等。执行失败的情况下返回 false。
语法:
$this->dbObj->insert_builder($insertTableName, $insertDataArr);
说明:
该命令用于拼凑一个标准的 INSERT 语句。
示例:
$instSql = $this->dbObj->insert_builder("users", array('uId'=>null, 'uName'=>"ZhangSanFeng"));
/*
$instSql = "INSERT INTO users (uId, uName) VALUES (null, 'ZhangSanFeng')";
*/语法:
$this->dbObj->update_builder($updateTableName, $updateDataArr, $whereStr);
说明:
该命令用于拼凑一个标准的 UPDATE 语句。
示例:
$updSql = $this->dbObj->update_builder("users", array('uName'=>"LiMoChou"), "uId = 123");
/*
$updSql = "UPDATE users SET uName = 'LiMoChou' WHERE uId = 123";
*/注意事项:
可以使用在字段名称前面加‘@’的方式提交特殊内容,例如:array('@datetime'=>"now()"),这个时候会解析为 datetime = now() 而不会给 now() 加引号。
可以使用在字符名称前面加数学运算符的方式提交特殊内容,例如:array('+readCount'=>1),这个时候会解析为 readCount = readCount+1 实现自增目的。
语法:
$this->dbObj->sql_builder($mainSql, $param1, $pram2...);
该命令用于拼凑一个标准的 SELECT 语句。
示例:
$sql = $this->dbObj->sql_builder("select * from users where uId = @int", 123);
/*
$sql = "select * from users where uId = 123";
*/注意事项:
可用的内部变量名称有:@int、@dcm、@str、@lstr、@llstr、@lrstr。
@int会被替换为整数
@dcm会被替换为浮点数
@str会被替换为字符串。
安全模式下可以有效的防止SQL注入攻击,需要大家在编写sql语句的时候使用安全模式传递参数(param)
单行提取 row 对应 sr
单值提取 scalar 对应 ss
数组提取 to_array 对应 sta
序列提取 to_list 对应 stl
更改语句 execute 对应 se
插入语句 insert_builder 对应 ib
更新语句 update_builder 对应 ub
查询语句 sql_builder 对应 sb
示例:
$uId = 123;
$uName = "Zhang 3 (we set a danger char...) '; delete from users;";
$sql = $this->dbObj->sb("select * from users where uId = @int and uName = @str", $userId, $userName);
/*
$sql = "select * from users where uId = 123 and uName = 'Zhang 3 (we set a danger char...) \'; delete from users;'";
look, we converted the danger code.
*/好了,到此为止,数据库操作对象的常用功能方法介绍就全都说完了!多多练习吧~~
对象名称 tf_模型名称_action,例如:tf_user_action
构造器内引用 tf_common_action 的构造器的参数。第一个是数据库操作对象 $dbObj,第二个是模型对应的数据表名称,第三个是模型对应的数据表的主键字段名称
linking('common.common_action');
class tf_user_action extends tf_common_action 
{
    public function __construct($dbObj)
    {
        parent::__construct($dbObj, "user", "uId");
    }
}获取一行数据
参数是数据表主键字段值
$myActObj = new tf_user_action($this->dbObj); $userInfo = $myActObj->get_row($userId);
创建一行数据
参数是数据表字段列表对应数据的数组
$myActObj = new tf_user_action($this->dbObj); $newInsertId = $myActObj->create_row(array( 'userName'=>"蕾蕾", 'userFlag'=>2, )); if($newInsertId > 0) echo "Create succ"; else echo "Create failed";
modify_row
修改一行数据
参数1是数据表主键字段值
参数2是数据表欲修改的字段对应数据的数组
$myActObj = new tf_user_action($this->dbObj); $updRet = $myActObj->modify_row(12345, array( 'userName'=>"蕾蕾", 'userFlag'=>2, )); if($updRet == 0) echo "Modify succ"; else echo "Modify failed";
删除一行数据
参数是数据表主键字段值
$myActObj = new tf_user_action($this->dbObj); $delRet = $myActObj->remove_row(12345); if($delRet == 0) echo "Remove succ"; else echo "Remove failed";
创建一行多个关联表的连动数据
参数1是多个数据表名称的数组
参数2是多个数据表对应的字段对应的数据的二维数组
引用前面数据表插入的自增列值的方法,使用 ~数据表数组下标 作为字段值,例如:~0
$myActObj = new tf_user_action($this->dbObj); $ret = $myActObj->add_new(array( 'user', 'userDetail', ), array( array( 'userName'=>"蕾蕾", 'userFlag'=>2, }, array( 'userId'=>"~0", // user 表的新插入数据的自增列值 'gender'=>2, 'birth'=>"1980-6-8", 'description'=>"我喜欢画画!", ), ); if($ret == 0) echo "succ"; else if($ret == 1) echo "表数量和字段数组数量不一致"; else if($ret == 2) echo "部分表插入失败";
创建一行关联数据
参数1是数据表名称
参数2是多个字段对应的数据的数组
参数3是关联键字段对应的数据的数组。参数3数组字段会自动检查唯一性,保证不会写入重复数据。
$myActObj = new tf_user_action($this->dbObj);
$crtRet = $myActObj->create_relation_record("#user_industry#", array('userId'=>12345, 'industryId'=>10, 'showDetail'=>1), array('userId'=>12345, 'industryId'=>10));
if($crtRet) { echo "succ"; } else { echo "failed"; }
$crtRet = $myActObj->create_relation_record("#user_industry#", array('userId'=>12345, 'industryId'=>12, 'showDetail'=>1), array('userId'=>12345, 'industryId'=>12));
if($crtRet) { echo "succ"; } else { echo "failed"; }
$crtRet = $myActObj->create_relation_record("#user_class#", array('userId'=>12345, 'classId'=>10));
if($crtRet) { echo "succ"; } else { echo "failed"; }删除一行关联数据
参数1是数据表名称
参数2是关联键字段对应的数据的数组。参数2完全匹配的数据才会被删除。
$myActObj = new tf_user_action($this->dbObj);
$delRet = $myActObj->drop_relation_record("#user_class#", array('userId'=>12345, 'classId'=>10));
if($delRet) { echo "succ"; } else { echo "failed"; }检查数据表是否有子级
参数1是父级字段名称,参数2是父级字段值
$myActObj = new tf_user_action($this->dbObj);
$numSubItems = $myActObj->has_subitems_check("parentClassId", 10);唯一性检查
参数1是字段名称
参数2是字段测试值
参数3是当前行数据的字段值(可选)
参数4是附加条件(可选)
// 新建数据的时候检查重复
var_dump( $myActObj->duplicate_check("userName", $formUserName) );
// 编辑数据的时候检查重复
var_dump( $myActObj->duplicate_check("userName", $formUserName, $currEditUserId) );
// 携带更多附加条件的情况
var_dump( $myActObj->duplicate_check("userName", $formUserName, null, $this->dbObj->sb(" userGroup = 'NORMAL')) );
var_dump( $myActObj->duplicate_check("userName", $formUserName, $currEditUserId, $this->dbObj->sb(" userGroup = 'NORMAL')) );获取列表查询SQL语句
参数1是SQL的select部分
参数2是SQL的where部分
$myActObj->get_list_sql("userId, userName, userFlag", "userStat = 1");创建区间查询条件
// make a date distence condition
$myActObj->make_distence_condition("createDatetime", $gvs->crtDateBegin, $gvs->crtDateEnd, true, true);
// make a number distence condition
$myActObj->make_distence_condition("amount", $gvs->lowOrderAmount, $gvs->highOrderAmount, true, true);创建列表匹配查询条件
// the field 'userIdList' maybe equal to a string like '123,234,456,789'
$myActObj->make_matchlist_condition("userIdList", $userId);测试列表匹配查询条件
// $userIdList maybe equal to a string like '123,234,456,789' var_dump($myActObj->test_matchlist($userId, $userIdList));
修改一行数据,参数是where条件SQL语句
$myActObj = new tf_user_action($this->dbObj);
$updRet = $myActObj->modify_row_by_where($this->dbObj->sb(" userName = @str", $userName), array(
'userName'=>"蕾蕾",
'userFlag'=>2,
));
if($updRet == 0) echo "Modify succ";
else echo "Modify failed";获取一行数据,参数是where条件SQL语句
$myActObj = new tf_user_action($this->dbObj);
$userInfo = $myActObj->get_row_by_where($this->dbObj->sb(" userName = @str", $userName));
if($userInfo != null) echo "succ";
else echo "failed";获得新插入数据行的自增列字段的值
// 获取单表插入后的自增列的值( create_row ) $myActObj->get_new_id(); // 获取多表同时插入后的自增列的值( add_new ) $myActObj->get_new_id($tableIndex); // $tableIndex 从 0 开始
好了,以上就是 tf_common_action 对象支持的便携方法,利用这些方法可以大大简化开发模型的效率和质量!
此版本还没有设计遵循MVC规范,数据操作均在视图逻辑内完成。实例地址 https://tongfu.net/home/35/blog/406726 仅供参考
此版本已经遵循了MVC规范,数据操作转到了模型对象内,不过暂时还不支持路由和AJAX。实例地址 https://tongfu.net/home/35/blog/406727 仅供参考
此版本遵循了MVC规范,同时将URI遵循RESTFul规范,同时支持AJAX处理,对应主流开发方式。实例地址 https://tongfu.net/home/35/blog/406728 仅供参考 
和一般的框架不同的是,我们的入口对象的初始化工作需要自己在视图里面完成
我们为了给开发者提供更多的便利,将视图做出了若干模型
使用这些模型可以快速地开发出各种功能
大家可以通过复制、粘贴下面的模板代码,稍加修改即可完成复杂功能的开发
适用于注册、登录等页面
require('.root.php');
require(WEBAPP_ROOT);
linking('html.form_action3');
class demo_action extends table_action_ctl {
    public function __construct($name){
        parent::__construct($name);
        $this->defaultAction = true;
    }
}
class demo_page extends form_action3{
    public $loginUser;
    public $actionObj;
    protected function validator(){
        $frmvObj = new form_validator_action3();
        return $frmvObj;
    }
    protected function form(){
        $frmObj = new form_maker_action3($this->tableConfig, $this->pageObj, "demo");
        $frmObj->set_target();
        $frmObj->add_button("btnSubmit",1,"提交");
        return $frmObj;
    }
    protected function form_show_arg(&$arg){
        $arg['class'] = "ctongfuTableForm";
    }
    protected function form_error($err){
        $this->pageObj->alertBack(implode("\n", $err));
    }
    protected function process($arr, &$err){
        
    }
    protected function default_process(){
        
    }
}
class demo extends sample_system{
    private $actionPage;
    public $actionObj;
    public function __construct($args){
        parent::__construct($args);
        $this->smartyFile = "demo";
        $this->regPublicKey = "demo";
        $this->page->title = "Title of 'demo'";
        //
        $this->tableConfig = new table_maker_config("demo");
        $this->actionObj = new demo_action("demo");
        $this->actionPage = new demo_page($this->tableConfig, $this->page, $this->smarty, $this->dbo, $this->actionObj->get_keys(), $this->actionObj->defaultAction);
        $this->actionPage->set_no_methods($this->actionObj->get_no_methods());
        $this->actionPage->loginUser = $this->loginUser;
        $this->actionPage->actionObj = $this->actionObj;
    }
    public static function main($args){
        $myPg = new demo($args);
        $myPg->actionPage->action_process();
        $myPg->done_smarty();
    }
}
demo::main(array(
    'mysql'
));适用于各种模块的列表页面,可以添加增、删、改、查功能
require('.root.php');
require(WEBAPP_ROOT);
linking('html.form_action3');
class demo_action extends table_action_ctl {
    public function __construct($name){
        parent::__construct($name);
        $this->add_usr_action("mod","修改");
        $this->add_usr_action("del","删除");
    }
}
class demo_table extends table_action3 {
    public $loginUser;
    public $actionObj;
    protected function filter_row(&$row){
        $this->actionObj->set_action_link($row,"mod",$row['pmId']); // pmId - primary key id
    }
    protected function get_sql(&$sql){
        $ws = "";
        $joins = "";
        $sql = "select * from demo"; 
    }
    protected function get_table_show_argv(table_action3_argv &$argv){
        $argv->actions = $this->actionObj->get_actions();
    }
}
class demo_page extends form_action3{
    public $loginUser;
    public $actionObj;
    protected function process(){
        $tablePage = new demo_table("demo", $this->tableConfig, $this->pageObj, $this->smartyObj, $this->dbObj,
            array('ID'));
        $tablePage->loginUser = $this->loginUser;
        $tablePage->actionObj = $this->actionObj;
        $tablePage->make_table();
    }
}
class demo extends sample_system{
    private $actionPage;
    public $actionObj;
    public function __construct($args){
        parent::__construct($args);
        $this->smartyFile = "demo";
        $this->regPublicKey = "demo";
        $this->page->title = "Title of 'demo'";
        //
        $this->tableConfig = new table_maker_config("demo");
        $this->actionObj = new demo_action("demo");
        $this->actionPage = new demo_page($this->tableConfig, $this->page, $this->smarty, $this->dbo, $this->actionObj->get_keys(), $this->actionObj->defaultAction);
        $this->actionPage->set_no_methods($this->actionObj->get_no_methods());
        $this->actionPage->loginUser = $this->loginUser;
        $this->actionPage->actionObj = $this->actionObj;
    }
    public static function main($args){
        $myPg = new demo($args);
        $myPg->actionPage->action_process();
        $myPg->done_smarty();
    }
}
demo::main(array(
    'mysql'
));适用于首页,频道首页等综合页面,里面可以单独添加表单,表格等等元素
require('.root.php');
require(WEBAPP_ROOT);
linking('html.form_action3');
class demo_action extends table_action_ctl {
    public function __construct($name){
        parent::__construct($name);
    }
}
class demo_page extends form_action3{
    public $loginUser;
    public $actionObj;
    protected function process(){
        
    }
}
class demo extends sample_system{
    private $actionPage;
    public $actionObj;
    public function __construct($args){
        parent::__construct($args);
        $this->smartyFile = "demo";
        $this->regPublicKey = "demo";
        $this->page->title = "Title of 'demo'";
        //
        $this->tableConfig = new table_maker_config("demo");
        $this->actionObj = new demo_action("demo");
        $this->actionPage = new demo_page($this->tableConfig, $this->page, $this->smarty, $this->dbo, $this->actionObj->get_keys(), $this->actionObj->defaultAction);
        $this->actionPage->set_no_methods($this->actionObj->get_no_methods());
        $this->actionPage->loginUser = $this->loginUser;
        $this->actionPage->actionObj = $this->actionObj;
    }
    public static function main($args){
        $myPg = new demo($args);
        $myPg->actionPage->action_process();
        $myPg->done_smarty();
    }
}
demo::main(array(
    'mysql'
));适用于开发接口
require('.root.php');
require(WEBAPP_ROOT);
class $variable_page {
    protected $dbObj;
    protected $pageObj;
    public function __construct(&$dbObj, &$pageObj){
        $this->dbObj = $dbObj;
        $this->pageObj = $pageObj;
    }
    public function process(){
        $gvs = $this->pageObj->get;
        // here coding statement
    }
}
class $variable extends sample_system{
    private $actionPage;
    public function __construct($args){
        parent::__construct($args);
        //
        $this->actionPage = new $variable_page($this->dbo, $this->page);
    }
    public static function main($args){
        $myPg = new $variable($args);
        $myPg->actionPage->process();
    }
}
$variable::main(array(
    'mysql'
));为前面使用的表格模板增加“事件”,可以实现增、删、改、查等等针对表格数据的操作
在 demo_page 对象下面增加如下五个方法,俗称:五件套
protected function validator_add(){
    $frmvObj = new form_validator_action3();
    return $frmvObj;
}
protected function form_add(){
    $frmObj = new form_maker_action3($this->tableConfig, $this->pageObj, "add");
    $frmObj->set_target();
    $frmObj->add_button("btnSubmit",1,"提交");
    return $frmObj;
}
protected function form_show_arg_add(&$arg){
    $arg['class'] = "ctongfuTableForm";
    $arg['formTitle'] = "";
    $arg['labels'] = array();
    $arg['notes'] = array();
}
protected function form_error_add($err){
    $this->pageObj->alertBack(implode("\n", $err));
}
protected function process_add($arr, &$err){
    
}独立的表单对象,使用POST方法提交数据
class demo_act extends form_action_item3{
    protected function create_validator(){
        $this->validator = new form_validator_action3();
    }
    protected function create_form(){
        $this->form = new form_maker_action3($this->tableConfig, $this->pageObj, "demo_act");
        $this->form->set_target();
        $this->form->add_button("btnSubmit",1,"提交");
    }
    protected function get_arg(&$arg){
        $arg['class'] = "ctongfuTableForm";
    }
    protected function form_error($err){
        $this->pageObj->parentAlertBack(implode("\n", $err));
    }
    protected function process($arr, &$err){
    }
}引用独立的表单对象
$toolPage = new form_act("form", $this->smartyObj, $this->dbObj,
    array(), "事件", $this->pageObj);
$toolPage->tableConfig = $this->tableConfig;
$toolPage->action_process();独立的表格对象
请将模板内的 demo_std_action 替换为 实例名称_std_action
请将模板内的 demo_table 替换为 实例名称_table
请将模板内的 tf_demo_action 替换为 tf_模型名称_action
请在模型对象 tf_模型名称_action 内实现方法 make_sql,返回查询数据列表的SQL语句。SQL的SELECT部分的字段就是显示到表格上的列数据字段,可以使用concat组合,可以使用as虚出来字段再用PHP改值。
class demo_std_action extends table_action_ctl {
    public function __construct($name){
        parent::__construct($name);
        $this->add_usr_action("mod","修改");
        $this->add_usr_action("del","删除");
    }
}
class demo_table extends table_action3 {
    public $loginUser;
    public $actionObj;
    protected function filter_row(&$row){
        $this->actionObj->set_action_link($row,"mod",$row['pmId']); // pmId - primary key id
    }
    protected function get_sql(&$sql){
        $myActObj = new tf_demo_action($this->dbObj);
        $sql = $myActObj->make_sql($this->pageObj);
    }
    protected function get_table_show_argv(table_action3_argv &$argv){
        $argv->actions = $this->actionObj->get_actions();
    }
}引用独立表格对象
请将模板内的 demo_table 替换为 实例名称_table
请将模板内的 "demo" 替换为 "实例名称"
请将模板内的 array('ID') 数组替换为表格上的列标题名称
$tablePage = new demo_table("demo", $this->tableConfig, $this->pageObj, $this->smartyObj, $this->dbObj,
    array('ID'));
$tablePage->loginUser = $this->loginUser;
$tablePage->actionObj = $this->actionObj;
$tablePage->make_table();将上面的模板复制到一个 php 文件里,保存到项目目录下,直接访问即可!!!