免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 25157 | 回复: 53
打印 上一主题 下一主题

[原创]Kiss - 用Php扩展实现的简单框架- v0.3.6 - (F25:源码 & .dll & fixed) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-01-22 17:07 |只看该作者 |倒序浏览
完整版本: Kiss - 用Php扩展实现的简单框架

    自从在公司的项目中引入Zend框架,一直对Php实现的框架的效率不太满意,这也是我前段时间学习开发Php扩展的原因之一-其附加结果就是翻译了编写扩展 系列文章。此后就一直忙于制作下面要介绍的Kiss框架。我的目标是简化、高效、比较通用和好用,所以使用Zend框架之前就对她进行了简化,抽取其中的类加载和控制器部分,并且由于本人具有Java背景(做了2年),也引入了一些Tomcat的特点,比如forward跳转方式和监听器......不废话了,进入v0.1的代码吧。

    代码简介:
  • 我使用php v5.2.3,主要在64位的Ubuntu 7.10中开发,使用Apache 2.2.4,Php编译为Apache的模块;
  • 同时在Windows XP Pro中使用VC6编译成功并测试可用;
  • 由于不会用libtool,所以不知道如何将代码拆分到多个文件编译,请不要见笑我的代码管理方式^_^;
  • 代码文件:
  • php_kiss.h - 模块头文件;
  • kiss.c - Php扩展相关代码;
  • kiss_inner.c - 实现基本功能,为kiss.c所#include;
  • kiss_const.c - 声明了太多的Php常量及相关macro,所以单放在此,为kiss.c所#include;

......



[ 本帖最后由 hshq_cn 于 2008-2-18 13:41 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2008-01-22 17:12 |只看该作者

特性说明

特性说明

  • 线程安全;
  • 在模块中存储通用数据,不用每次请求都处理(以后考虑使用全局存储);
  • 请求内缓存控制器对象和监听器对象,节省处理时间;
  • 记录已经执行的监听器,避免同一forward链中重复调用相同的监听器;
  • forward采用函数调用方式,而非管道方式(以后考虑支持);
  • 支持CLI模式测试代码;
  • 暂时只在Apache中测试过......
  • 待续......


[ 本帖最后由 hshq_cn 于 2008-1-24 11:32 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2008-01-22 17:20 |只看该作者
希望大家多提意见,^_^

[ 本帖最后由 hshq_cn 于 2008-1-24 17:07 编辑 ]

论坛徽章:
0
4 [报告]
发表于 2008-01-24 09:59 |只看该作者

v0.2.2

v0.2:
重新梳理并改善了部分代码,例如提取复杂函数各路退出分支的内存释放码,放在一处;
修改了几处以保证行为的一致性,例如kiss_request_get()中得到的$_GET和$_POST原来是引用,现在改为得到一份拷贝。
代码放在附件中,并且后面一节会有详细的使用介绍和样例。

v0.2.2:
修改缺省模块为""时的bug,以及一个内存初始化的疏忽。
增加测试代码附件。

[ 本帖最后由 hshq_cn 于 2008-1-24 17:08 编辑 ]

kiss_v0.2.2.zip

19.35 KB, 下载次数: 170

web.zip

3.73 KB, 下载次数: 135

论坛徽章:
0
5 [报告]
发表于 2008-01-24 10:32 |只看该作者

详细的使用介绍 - 预定义常量(全是整型)

预定义常量(全是整型)
用于kiss_eval(),区别同eval()、include和require:
KISS_EVAL
KISS_INCLUDE
KISS_INCLUDE_ONCE
KISS_REQUIRE
KISS_REQUIRE_ONCE


用于kiss_status()对框架进行设定:
KISS_STATUS_PREFIX_CTL    是否使用模块作为控制器类名的前缀,缺省-是;
KISS_STATUS_SHARE_GP      框架中维护的get和post参数是否是zend系统中的引用,缺省-是;
KISS_STATUS_USE_PORT      是否在在路由规则中使用端口,缺省-否;
KISS_STATUS_USE_CACHE     是否缓存输出,暂未实现;
KISS_STATUS_DISPATCH_TYPE    分发类型(见下);
KISS_STATUS_CLI_ROOT      设定用于CLI测试的基目录;
KISS_STATUS_EXT_PROC      设定控制器文件的扩展名,缺省-.php;
KISS_STATUS_EXT_PATH      设定应被转发的url的扩扎名,缺省-无;
KISS_STATUS_DEFAULT_MDL  设定缺省模块,缺省-空字符串;
KISS_STATUS_DEFAULT_CTL  设定缺省控制器,缺省-index;
KISS_STATUS_DEFAULT_ACT  设定缺省Action,缺省-index;
KISS_STATUS_POSTFIX_CTL  设定控制器类名后缀,缺省-Controller;
KISS_STATUS_POSTFIX_ACT  设定Action后缀,缺省-Action;


分发类型:
KISS_DISPATCH_FUNCTION    分发到控制器文件中的函数,即面向过程的;
KISS_DISPATCH_METHOD      分发到控制器类中的方法;


监听器类型,用于kiss_set_listener():
KISS_LS_PRE_DISPATCH     在分发前执行;
KISS_LS_POST_DISPATCH     分发后执行;


异常编号:
KISS_E_READFILE    读文件异常;
KISS_E_ONLYCLI     必须CLI模式,只用于kiss_cli_test();
KISS_E_NEEDURI     需要提供URI,只用于kiss_cli_test();
KISS_E_CFGFILE     配置文件解析;
KISS_E_INITREQ     初始化请求;
KISS_E_ROUTE        路由;
KISS_E_DISPATCH    分发;
KISS_E_CLSFILE     类文件读取;
KISS_E_INSTANCE    类实例化;
KISS_E_CALLFUNC    调用函数;
KISS_E_CALLMTD     调用方法;
KISS_E_EVAL         kiss_eval();
KISS_E_NEEDROOT    需要基目录,只用于kiss_cli_test();


请求的信息,用于kiss_request_get(),用法:KISS_REQ_CONTROLLER|KISS_REQ_ACTION:
KISS_REQ_ALL        全部;
KISS_REQ_METHOD    请求的方法;
KISS_REQ_HOST      请求的域名;
KISS_REQ_MODULE    模块;
KISS_REQ_CONTROLLER    控制器;
KISS_REQ_ACTION    Action;
KISS_REQ_FRAGMENT [请求参数]后面的"#"后的东东;
KISS_REQ_QUERY    get参数;
KISS_REQ_POST     post参数;
KISS_REQ_PARAMS   get和post参数;

论坛徽章:
0
6 [报告]
发表于 2008-01-24 10:40 |只看该作者

详细的使用介绍 - class说明

详细的使用介绍 - class说明

KissAction
控制器父类,只定义了空参无操作的构造函数;


KissListener
监听器父类,定义了构造函数、preDispatch()和postDispatch(),
都是空参无操作,
后二者分别用于分发前和分发后;

论坛徽章:
0
7 [报告]
发表于 2008-01-24 11:09 |只看该作者

详细的使用介绍 - 函数说明

kiss_eval
包含并执行文件,参考include。
proto mixed kiss_eval(string src[, long type])
arg1 - 文件或PHP代码,
arg2 - eval的类型,缺省是KISS_REQUIRE,
return - 参考include,如有问题则返回NULL,
throw Exception(文件不存在)


kiss_status
设定运行状态,必须在kiss_front_start之前调用。
proto mixed kiss_status(long key[, zval * value])
arg1 - 代表状态字段的常量,
arg2 - 新值,
return - 旧值。


kiss_set_rule
手工设定模块分发目录,推荐在配置文件中写定分发规则。
proto bool kiss_set_rule(string ctl_dir[, string mdl])
arg1 - 控制器目录,
arg2 - 模块名,不提供或NULL表示缺省(全局)模块(空字符串表示),
return - 是否成功。


kiss_front_start
启动前端控制器。
proto bool kiss_front_start(void)
      throws Exception
return - 是否成功,
throws - 配置文件解析或路由或分发失败,


kiss_cli_test
用于CLI调试,其他似kiss_front_start。
proto bool kiss_cli_test(string uri)
      throws Exception
arg1 - 用于测试的uri,
return - 是否成功,
throws - 配置文件解析或路由或分发失败或CLI相关的异常。


kiss_set_listener
设定Action或控制器的监听器。
因为使用当前模块,所以需要在控制器文件中调用,例如构造函数中。
proto bool kiss_set_listener(string listener[, string item[, long type]])
arg1 - 监听器类的名字,
arg2 - 监听目标,应是Action,空表示对整个控制器,
arg3 - 监听器类型(现在只有分发前和分发后),缺省是分发前,
return - 是否成功。


kiss_forward
服务器内跳转到其他的Action。
因为是函数调用方式,所以会返回调用点。
proto bool kiss_forward(string action[, string controller[, string module[, array params]]])
      throws Exception
arg1 - Action,
arg2 - Controller,缺省为当前的控制器,
arg3 - Module,缺省为当前模块,
arg4 - 参数数组,
return - 是否成功,
throws - Action初始化或分发失败。


kiss_redirect
重定向到其他的地址。
proto bool kiss_redirect(string action[, string controller[, string module[, long code]]])
      throws Exception
arg1 - Action或绝对路径,
arg2 - Controller,缺省为当前的控制器,
arg3 - Module,缺省为当前模块,
arg4 - 响应代码,
return - 是否成功,
throws - Action初始化或分发失败。


kiss_request_query
获取查询参数。
proto mixed kiss_request_query([string key])
arg1 - 参数的键,不提供则返回全部参数数组,
return - 键对应的值。


kiss_request_post
获取POST参数。
proto mixed kiss_request_post([string key])
arg1 - 参数的键,不提供则返回全部参数数组,
return - 键对应的值。


kiss_request_params
获取请求(QUERY+POST)参数,QUERY优先。
proto mixed kiss_request_params([string key])
arg1 - 参数的键,不提供则返回全部参数数组,
return - 键对应的值。


kiss_request_get
获取请求相关信息。
proto mixed kiss_request_query([long type])
arg1 - 所需信息的类型常量,可组合,
return - 信息的数组,如需要的项不存在则为空字符串或空数组。

论坛徽章:
0
8 [报告]
发表于 2008-01-24 13:06 |只看该作者

详细的使用介绍 - 样例

详细使用示例

    可借鉴Zend的使用:

*nix和Windows平台的编译方法可参考我的blog的其他文章;

修改Php的配置文件,加入相关条目,只需要指定配置文件的路径:
extension=php_kiss.so

[kiss]
kiss.cfg_file = "/web/kiss_test/conf/kiss.cfg_file.cfg"


假如我们的项目kiss_test的域名是"test.dev",缺省80端口,
目录结构:
/web/kiss_test/htdocs/ - 基目录是,以下用$root表示,
  ├ kiss_front.php
  └ .htaccess
/web/kiss_test/controllers/ - 缺省模块的目录,
  ├ IndexController.php
  └ BlogController.php
/web/kiss_test/admin_controllers/ - "admin"模块,
  └ UserAdminController.php
/web/kiss_test/listeners/ - 监听器目录,
  ├ User.php
  └ Admin.php

配置文件kiss.cfg_file.cfg样例如下:
RW:test.dev         /web/kiss_test/controllers
RW:test.dev/admin    admin_controllers/
LS:test.dev         /web/kiss_test/listeners/

RW表示控制器文件的目录,格式:RW:HOST[:PORT][/MODULE]   PATH,
LS表示监听器文件的目录,
格式:LS:HOST   PATH,
注意
PATH可以使用相对或绝对路径;
是否使用PORT,需要kiss_status()做对应的设定;
如果
缺省模块为"",HOST后面的‘/’可以省略;

因为只作非常简单的解析,所以不要加入多余字符;



如果使用Apache,修改其配置文件激活url-rewrite,,
或者在项目目录中增加.htaccess文件,

例如:

RewriteEngine    on
RewriteRule    !\.(js|ico|gif|jpg|png|css|php|html)$    /kiss_front.php
#RewriteRule     \.kiss$     /kiss_front.php

将动态或特定的url都导向kiss_front.php(作为前端控制器);

kiss_front.php 例如:

<?php
ini_set('display_errors', true);
$br = (php_sapi_name() == "cli")? "\n":"<br>\n";
$space = (php_sapi_name() == "cli")? " ":" ";

// kiss_status(KISS_STATUS_EXT_PATH, ".kiss");
// kiss_status(KISS_STATUS_USE_PORT, 1);
// kiss_status(KISS_STATUS_PREFIX_CTL, 0);
// kiss_status(KISS_STATUS_SHARE_GP, 0);

try {
    kiss_front_start();
} catch(Exception $e) {
    // var_dump($e->getTrace());
    echo "MSG: ", $e->getMessage(), "$br";
    echo "CODE: ", $e->getCode(), "$br";
}
?>

访问http://test.dev/,则会执行controllers目录下的IndexController.php中的indexAction方法;
http://test.dev/index
http://test.dev/index/index和http://test.dev/index/index/k1/v1/k2/v2?k3=v3也是,
http://test.dev/blog/... 定向到
controllers目录下的BlogController.php,
http://test.dev/admin/userAdmin/...
定向到admin_controllers目录下的UserAdminController.php;

注意类名、文件名和URL的关系以及大小写。

如要在CLI中测试,可以增加kiss_status(KISS_STATUS_CLI_ROOT, dirname(dirname(__FILE__)));
并用kiss_cli_test($URL);代替kiss_front_start();来执行;

IndexController.php:

<?php
class IndexController extends KissAction {
    public function __construct() {
        parent::__construct();
        echo __METHOD__, "\n";
    }

    public function indexAction() {
        global $br;
        echo "I'm from ", __METHOD__, "$br";
        kiss_forward("index", "blog"); // 调用BlogController->indexAction();
    }

}
?>


BlogController.php
<?php
class BlogController extends KissAction {
    public function __construct() {
        parent::__construct();
        echo __METHOD__, "\n";

        kiss_set_listener("user", "myinfo"); // 设定
myinfoAction方法的分发前监听器
        // kiss_set_listener("user",
"myinfo", KISS_LS_POST_DISPATCH);
    }

    public function indexAction() {
        global $br;
        echo "I'm from ", __METHOD__, "$br";
        kiss_forward("myinfo");
    }


    public function myinfoAction() {
        global $br;
        echo "I'm from ", __METHOD__, "$br";
    }

}
?>


UserAdminController.php
<?php
class
AdminUserAdminController extends KissAction {
    public function __construct() {
        parent::__construct();
        echo __METHOD__, "\n";

        kiss_set_listener("admin");
// 设定所有方法的分发前监听器
        kiss_set_listener("admin", NULL
, KISS_LS_POST_DISPATCH);
    }

    public function indexAction() {
        global $br;
        echo "I'm from ", __METHOD__, "$br";
        kiss_forward("
userlist");
    }


    public function userlistAction() {
        global $br;
        echo "I'm from ", __METHOD__, "$br";
    }

}
?>


User.php:

<?php
class User extends KissListener {
    public function __construct() {
        parent::__construct();
        echo __METHOD__, "\n";
    }

    public function preDispatch() {
        $req = kiss_request_get(KISS_REQ_ACTION);
        $req = $req['action'];
        echo __METHOD__, " from [$req] <br/>\n";
    }

    public function postDispatch() {
        $req = kiss_request_get(KISS_REQ_ACTION);
        $req = $req['action'];
        echo __METHOD__, " from [$req] <br/>\n";
    }
}
?>



Admin.php:

<?php
class Admin extends KissListener {
    public function __construct() {
        parent::__construct();
        echo __METHOD__, "\n";
    }

    public function preDispatch() {
        $req = kiss_request_get(KISS_REQ_ACTION);
        $req = $req['action'];
        echo __METHOD__, " from [$req] <br/>\n";
    }

    public function postDispatch() {
        $req = kiss_request_get(KISS_REQ_ACTION);
        $req = $req['action'];
        echo __METHOD__, " from [$req] <br/>\n";
    }
}
?>


这样,简单的测试就完成了.

[ 本帖最后由 hshq_cn 于 2008-1-24 15:51 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2008-01-24 14:13 |只看该作者

改错

上面例子中的配置文件有处笔误:
test.dev/blog
应为
test.dev/admin


如果是缺省模块,HOST后面的‘/’不可省略;
改为
如果缺省模块为"",HOST后面的‘/’可以省略;

[ 本帖最后由 hshq_cn 于 2008-1-24 15:50 编辑 ]

论坛徽章:
0
10 [报告]
发表于 2008-01-24 17:09 |只看该作者
编辑帖子的时候没注意可以删除附件,
现刚发现,已经删除了v0.2的kiss.zip,
保留v0.2.2。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP