Warning: curl_exec() has been disabled for security reasons in /pub/host/sunboyu/sunboyu/www/wp-includes/http.php on line 1022

Warning: Cannot modify header information - headers already sent by (output started at /pub/host/sunboyu/sunboyu/www/wp-includes/http.php:1022) in /pub/host/sunboyu/sunboyu/www/wp-includes/feed-rss2.php on line 8
一个程序猿 » PHP http://www.sunboyu.cn 时光不会倒流,脚步总要前进 Tue, 31 Jan 2012 10:50:34 +0000 http://wordpress.org/?v=2.7 en hourly 1 Tokyo Cabinet table表的jsp接口 http://www.sunboyu.cn/2011/08/16/tokyo-cabinet-table%e8%a1%a8%e7%9a%84jsp%e6%8e%a5%e5%8f%a3.shtml http://www.sunboyu.cn/2011/08/16/tokyo-cabinet-table%e8%a1%a8%e7%9a%84jsp%e6%8e%a5%e5%8f%a3.shtml#comments Tue, 16 Aug 2011 06:50:22 +0000 admin http://www.sunboyu.cn/?p=1436 终于完成了Tokyo Cabinet的jsp接口,在tomcat下性能不是那么出众,看来性能还是得用c。

部署方法看上一偏配置说明。

代码 api.tar.gz

信息插入与修改:

  1. $data['database'] = "sunboyudata2";
  2. $jsondata = array();
  3. while($row = mysql_fetch_array($query,MYSQL_ASSOC)){
  4. $jsondata[] = $row;
  5. }
  6. $data['jsondata'] = json_encode($jsondata);
  7. $url= http_build_query($data );
  8. $postdate = array (
  9. 'http' => array (
  10. 'method' => 'POST',
  11. 'header'=> "Content-type: application/x-www-form-urlencoded\r\n" .
  12. "Content-Length: " . strlen($url) . "\r\n",
  13. 'content' => $url
  14. ),
  15. );
  16. $postcontent = stream_context_create($postdate);
  17. $return= file_get_contents('http://192.168.138.29:8080/api.jsp', false, $postcontent );

查询:

http://192.168.138.29:8080/search.jsp?database=sunboyudata2&query=fid:QCNUMEQ:1604&skip=20000&max=10

database:数据库文件名[无扩展名]
query:查询条件 每组查询条件三个部分 字段:规则:值 每组之间用|分割
skip:记录起始
max:返回的记录条数

缺点:在频繁大数据量提交的时候,tomcat总是影响失败。性能没有预期那么好,tc需要优化。

]]>
http://www.sunboyu.cn/2011/08/16/tokyo-cabinet-table%e8%a1%a8%e7%9a%84jsp%e6%8e%a5%e5%8f%a3.shtml/feed
使用PHP来生成二维码 http://www.sunboyu.cn/2011/08/11/%e4%bd%bf%e7%94%a8php%e6%9d%a5%e7%94%9f%e6%88%90%e4%ba%8c%e7%bb%b4%e7%a0%81.shtml http://www.sunboyu.cn/2011/08/11/%e4%bd%bf%e7%94%a8php%e6%9d%a5%e7%94%9f%e6%88%90%e4%ba%8c%e7%bb%b4%e7%a0%81.shtml#comments Thu, 11 Aug 2011 13:55:44 +0000 admin http://www.sunboyu.cn/?p=1430 二维码是什么?

看这里:百度百科:二维码

二维码我用的最多的就是利用android手机的二维码扫描功能扫描网址,当然这种方法还大量应用在货物标签,比如我们去超市结账的条码扫描。

二维码利用近距离的光线进行数据传输,打破了网络数据线的依赖,可以说是一种打破常规的非常方便的应用。尤其在各种设备并不那么兼容的情况下,用二维码交换少量信息是非常便利的。

二维码的算法是通用的,二维码PHP的生成,我发现了以下几种方式:
1、某日本作者写的PHP http://www.swetake.com/qr/qr_cgi.html
2、开源社区上的PHP程序 http://phpqrcode.sourceforge.net/
3、google提供的一个接口 http://code.google.com/intl/zh-CN/apis/chart/

这里我尝试了第二种方法:下载软件包后,使用里边的方法:QRcode::png

我写了个代码是这样:

require_once(APP_PATH.'/include/phpqrcode/qrlib.php');
QRcode::png("http://www.sunboyu.cn");

这样就可以输出二维码图形了,可以用手机尝试一下。

]]>
http://www.sunboyu.cn/2011/08/11/%e4%bd%bf%e7%94%a8php%e6%9d%a5%e7%94%9f%e6%88%90%e4%ba%8c%e7%bb%b4%e7%a0%81.shtml/feed
discuz论坛大表优化 http://www.sunboyu.cn/2011/01/11/discuz%e8%ae%ba%e5%9d%9b%e5%a4%a7%e8%a1%a8%e4%bc%98%e5%8c%96.shtml http://www.sunboyu.cn/2011/01/11/discuz%e8%ae%ba%e5%9d%9b%e5%a4%a7%e8%a1%a8%e4%bc%98%e5%8c%96.shtml#comments Tue, 11 Jan 2011 15:15:17 +0000 admin http://www.sunboyu.cn/?p=1365 通过观察,大部分的dz论坛在数据量发展到一定程度,在线人数逐渐提高后,首先锁表的是sessions,这个表我已经写过多种优化的方式,不外乎寻找一些比mysql负载性能好的程序来代替这部分工作。但时间长了,随着在线人数继续增加,那个附加的程序也会面临瓶颈。提高硬件性能和软件性能固然能提高负载,但一旦到瓶颈,必须想其他的方案。

硬件和简约的程序能提高性能,在大数据量下,算法的优势就能体现出来了。

顺便提一下主从:很多人认为主从可以解决问题,其实未必。设想一主多从结构,假如主库写压力很大,那同样压力会同步到从库,会造成N个从库压力同时很大。事实上从库压力会小于主库,因为主库是多进程写,而从库是单进程写, 但总的来说,执行的语句不会少。所以,主从这种结构在一定情况下也就失去了优势。(在硬件资源充裕,压力不是很大的环境下,这种问题发生较少,在硬件条件比较差的一些环境下,这种瓶颈很容易表现出来)

这里拿discuz7的posts表举例,摆脱主从结构,硬件比较差,表很大,10G以上。

一个负载大的dz论坛,在线人数多,又比较活跃,那posts表的压力肯定不会小。在一个回复比较频繁,存储引擎使用myisam的posts表,锁表是经常发生的,我所遇见的问题发生的环境为:数据库单点,无主从,io压力中等。posts表频繁锁表,而造成查询排队,查询速度骤然下降。

在不提升硬件的情况下,要想提速,显然是比较困难的,大量的文本数据装入memcached显然也不合适。所以,这个问题我用优化数据存储的角度对数据表进行了改造。

TIPS:同样100M带宽的集线器和交换机,交换机的吞吐性能远远高于集线器,原因在于:交换机建立专有通道,避免了冲突。

而在mysql中,锁表可以形象描述为冲突了,读写冲突了。但如果我们分表,把读写分散,也许会好点。

分表规则:按照tid进行hash,分散到16个表中。

假设,一读一写,两个操作,同时进行,那么他们撞在一起的几率就是1。如果分为两个表,那么他们撞在一起的几率就是1/2 = 0.5,用一个函数来表示,就是F(x)=1/x ,显然,分的表越多,冲突的机会越小,锁表的几率就越少。即时锁表,影响的也只是1/x的数据,不会对所有的用户造成影响。

数据模型解释:如果是绝对同步发生,几率应该是 F(x)=1/((x-1)*x),但在计算机里,无论两个操作时间间隔多小,在cpu时间片上都是顺序执行,因为,函数我认定为:F(x)=1/x。

以上用数学的方式解释了算法优化对性能的提升。实际上,通过对逍遥论坛的用户行为统计:posts表95%以上的操作都是在读写,搜索和管理占小部分。

补充一种分表算法:在discuzX里,后台启用了分表,我没有细看,大概是把表按照时间段或者其他条件分开。我猜测,作者本意是拆分老数据,主表只留最新数据和一些命中高的数据。这种方式可以起到一定效果,但根据统计,大部分用户习惯浏览回复最新帖子,因此,大部分的读写还是定位到了一张表,也就是没有彻底解决读写冲突的问题。
还有一个朋友使用的是顺序分表,500w个pid一张表,但这个方法同上个方法,没解决冲突问题。
所以,在他的基础上,我考虑出按照tid进行hash分表的方案。

说到这里,分表又给我们带来了麻烦,有些查询并不能用tid主键进行定位,这里我用了mysql合并表,这个合并表可以合并16个分表,成为一个大表进行查询,而表名依然用原始的表明,这样,dz中原来的功能就不受影响了。

此方案已经实现,我用的新老数据+分别hash的方式,即32张表存储posts数据的方式。但未做压力测试。最近努力学习loadrunner使用,这个压测马上就可以进行了。

]]>
http://www.sunboyu.cn/2011/01/11/discuz%e8%ae%ba%e5%9d%9b%e5%a4%a7%e8%a1%a8%e4%bc%98%e5%8c%96.shtml/feed
discuz全文检索lucene解决方案图例 http://www.sunboyu.cn/2010/12/17/discuz%e5%85%a8%e6%96%87%e6%a3%80%e7%b4%a2lucene%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88%e5%9b%be%e4%be%8b.shtml http://www.sunboyu.cn/2010/12/17/discuz%e5%85%a8%e6%96%87%e6%a3%80%e7%b4%a2lucene%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88%e5%9b%be%e4%be%8b.shtml#comments Fri, 17 Dec 2010 03:17:12 +0000 admin http://www.sunboyu.cn/?p=1347 discuz论坛搜索方案

已经全部调试通过,正在往一个线上环境上部署。文档也在敢写之中,谢谢关注。

]]>
http://www.sunboyu.cn/2010/12/17/discuz%e5%85%a8%e6%96%87%e6%a3%80%e7%b4%a2lucene%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88%e5%9b%be%e4%be%8b.shtml/feed
discuz优化心得 http://www.sunboyu.cn/2010/12/14/discuz%e4%bc%98%e5%8c%96%e5%bf%83%e5%be%97.shtml http://www.sunboyu.cn/2010/12/14/discuz%e4%bc%98%e5%8c%96%e5%bf%83%e5%be%97.shtml#comments Tue, 14 Dec 2010 07:16:41 +0000 admin http://www.sunboyu.cn/?p=1330 自从09年10月份接到公司论坛改造升级任务到现在,逍遥论坛 http://bbs.xoyo.com 在性能和负载方面相对稳定,修改了原来的结构,单程序可以支持多论坛(模仿5d6d http://www.5dforum.com/ )。有几个参数可以参考:

平时在线人数:5000~10000人 峰值:50000+(超过5w后,统计表性能明显下降,关闭了统计)

之前每逢峰值论坛常挂,改造之后有充足的预案防止出问题,保证论坛用户能及时在论坛传达必要消息。

在论坛改造过程中,我写了很多文章来表述改造中的一些心得,也认识了很多朋友一起讨论dz的优化。其中最宝贵的经验,是一些无能为力的站长把他们的服务器交给我,让我亲手在一个大负载的服务器上去做优化,在这个过程中学到了很多系统优化方面的知识,更宝贵的是获得了大负载下dz的一些瓶颈点的数据。

由于考虑用户群的问题,很多技术没有办法用开源的软件实现,也无法找到替代品,考虑实际,很多dz站长自己并没有实力去涉入维护一个更改很多的论坛,所以我的方案并没有大量去应用。

在帮朋友优化的过程中,提到更多的是技术实力与维护、需求的增删与性能的平衡。

所以,我得出这样的结论供大家参考:

1、每个功能都会吃系统资源,充分考虑每个功能是否必须,不必须的功能一定要砍。

2、找系统压力点:根据我对逍遥论坛用户日志的分析,90%的压力集中在 forumdisplay.php viewthread.php上,而这些脚本的压力主要体现在表联查而造成的锁表上,最主要的表就是sessions表。sessions表集合了很多用户统计相关功能,因为,优化此表,结合上条原则,合理增删功能,达到压力减小。

3、硬件的优化。硬件优化也是我最近考虑的一个方案,想对于开发人员,硬件的开销还是很小的。合理升级硬件也是一个不错的方案。

以上结论是针对中小型网站已经碰到瓶颈的dz程序做出的建议。

而对于一个负载很大,并且有实力的团队,那在discuz上要做的文章就太多了。

1、拆表是必然的,而对于一些数据量不大但经常变动的表,完全可以全cache。

2、根据需求删改功能。discuz很强大, 但不是每个功能都是你必须使用的。

3、开源产品会给你很多灵感。

推荐的一些开源技术方案:

memcached(不用说了)

Tokyo Cabinet DBM:性能极佳的持久存储的keyvalue数据库

mysql udf http http://blog.s135.com/mysql-udf-http/ 让tt变成从库?

lucene 必须要替换discuz默认的搜索

你还有什么想法?

一时兴起,写此文。欢迎有兴趣的朋友加 discuz性能优化讨论群 qq:41886598

]]>
http://www.sunboyu.cn/2010/12/14/discuz%e4%bc%98%e5%8c%96%e5%bf%83%e5%be%97.shtml/feed
设计模式研究 http://www.sunboyu.cn/2010/12/02/%e8%ae%be%e8%ae%a1%e6%a8%a1%e5%bc%8f%e7%a0%94%e7%a9%b6.shtml http://www.sunboyu.cn/2010/12/02/%e8%ae%be%e8%ae%a1%e6%a8%a1%e5%bc%8f%e7%a0%94%e7%a9%b6.shtml#comments Thu, 02 Dec 2010 14:47:27 +0000 admin http://www.sunboyu.cn/?p=1317 研究PHP设计模式其实很久,不过真正在使用上却用的不是很多。但凡设计模式都用在大型负载的商业软件商,而对于web开发,尤其一些短平快的产品,设计模式显得不是那么重要。而只有一些非常核心和通用的部分,我们加以封装,主要是方便复用。

通过最近做一些项目,松散的设计明显不能满足项目的需求,随意的代码虽然能加快项目进度,但也造成很严重的技术透支。

重新认识框架,可以得出以下体会:

框架的确是限制人的,但不是技术的限制,不是思想的限制,而是规范合作的限制。

项目的设计规划人员要付出更多,其设计了框架的核心后,开发人员在你的思路下进行开发,你的一点点错误会在几个人身上得到成倍的放大。

坚持一种设计思路,即使已经走了很多弯路,但起码保证这些弯路要走踏实,而不是一条泥泞的弯路。

一个优化的框架不仅是完成基本功能,更要让开发人员感觉爽,这是最重要的(很难实现)。

最后,继续琢磨我的框架吧。

—————————-题外话——————————–

最新学了一段时间的C,包括我以前也提倡,用写C的态度来写PHP。写C语言,每个变量,每块内存都要完全规划在你的脑子里,处理不好,程序是绝对跑不动的。做PHP项目,也要注意这些细节,虽然PHP是弱类型的语言。当然,做一个项目,也要去考虑方方面面。

]]>
http://www.sunboyu.cn/2010/12/02/%e8%ae%be%e8%ae%a1%e6%a8%a1%e5%bc%8f%e7%a0%94%e7%a9%b6.shtml/feed
学习PHP开发的一些资源 http://www.sunboyu.cn/2010/11/09/%e5%ad%a6%e4%b9%a0php%e5%bc%80%e5%8f%91%e7%9a%84%e4%b8%80%e4%ba%9b%e8%b5%84%e6%ba%90.shtml http://www.sunboyu.cn/2010/11/09/%e5%ad%a6%e4%b9%a0php%e5%bc%80%e5%8f%91%e7%9a%84%e4%b8%80%e4%ba%9b%e8%b5%84%e6%ba%90.shtml#comments Tue, 09 Nov 2010 14:42:26 +0000 admin http://www.sunboyu.cn/?p=1304 http://blog.csdn.net/alexdream/archive/2008/03/24/2213344.aspx

http://devzone.zend.com/node/view/id/1022

http://blog.csdn.net/alin0725/archive/2007/04/08/1556460.aspx

http://devzone.zend.com/article/1024-Extension-Writing-Part-III-Resources 这篇文章不错,讲PHP如果管理连接符

http://www.phpbbchina.com/wiki/index.php/%E7%BC%96%E5%86%99PHP%E6%89%A9%E5%B1%95 中文教程

]]>
http://www.sunboyu.cn/2010/11/09/%e5%ad%a6%e4%b9%a0php%e5%bc%80%e5%8f%91%e7%9a%84%e4%b8%80%e4%ba%9b%e8%b5%84%e6%ba%90.shtml/feed
使用Lucene 构建强大的discuz 论坛搜索模块 http://www.sunboyu.cn/2010/07/27/discuz_lucene.shtml http://www.sunboyu.cn/2010/07/27/discuz_lucene.shtml#comments Tue, 27 Jul 2010 06:21:18 +0000 admin http://www.sunboyu.cn/?p=1263 在我搞完公司的论坛优化后,我一直想写一个圈套的dz性能优化的方案。当时的全文检索使用的是公司内部某人开发的检索系统,没有开源,所以我做此方案来实现。
此文刚打完草稿,处于调试通过的状态。没有形成具体可用的用户文档。希望在这个底稿的基础上,朋友能给予测试和支持,以鼓励我做出一套完整的方案。

下载:lucene_dz

欢迎加入QQ讨论群:41886598

]]>
http://www.sunboyu.cn/2010/07/27/discuz_lucene.shtml/feed
关于一些网站登录穿越(账号改变|登录变成他人)的问题研究 http://www.sunboyu.cn/2010/03/30/discuz%e8%b4%a6%e5%8f%b7%e6%b7%b7%e4%b9%b1%e9%97%ae%e9%a2%98%e7%a0%94%e7%a9%b6.shtml http://www.sunboyu.cn/2010/03/30/discuz%e8%b4%a6%e5%8f%b7%e6%b7%b7%e4%b9%b1%e9%97%ae%e9%a2%98%e7%a0%94%e7%a9%b6.shtml#comments Tue, 30 Mar 2010 06:13:47 +0000 admin http://www.sunboyu.cn/?p=1199 最近论坛发生了一些问题,某用户A登录后变成了某用户B。此事在某阶段频繁发生。在排除了账号服务器的问题、程序自身问题后,在网上又发现类似现象:
淘宝账号诡异事件:
http://diybbs.it168.com/viewthread.php?tid=593134&extra=&page=1

我点到我自己的淘宝里面,进入了一个陌生女子的界面
不过这个bug只出现了一次
这个人我已经加上了,是个卖魔方的

卡巴斯基中文官网论坛账号诡异事件:
http://bbs.kaspersky.com.cn/viewthread.php?tid=15891

有登录论坛出现别人信息的会员请进这个问题,论坛上已经有不少会员碰到。管理员正在设法解决这个问题。凡是出现这种情况的,请在下面回帖,向管理员详细说明以下情况,帮助管理员更快解决问题
1、出现问题的频率和条件
2、进入论坛的方式(例如是收藏夹进入、直接输入网址进入……)
3、论坛登录名和密码的保存方式(每次输入,不保存;按照多少时间保存)
4、有无别人和你共用电脑
5、使用的浏览器,及其版本
6、有无采取清除缓存文件,清除Cookies的措施,效果如何?
7、除以上措施外,有没有采取过其他措施,效果如何?

GMAIL账号诡异事件:
http://www.gseeker.com/50226711/aecceaecgmaileaeieie_139265.php

看到这个标题,你可能会认为这是天方夜谭。但事实上,这是完全有可能发生的。某天,你在登录Gmail时,尽管你100%正确地输入了自己的用户名及密码,但出现在你眼前的却是别人的Gmail邮箱。如果你第一时间怀疑自己的眼睛,那你就冤枉它了。因为至少在科威特,部分Gmail用户本周就经历了这样的怪事。

通过这些事件的观察,和对一些论坛账号发生错误的账户主人的询问,基本确定了以下几个可能点:

1、缓存的错误。因为discuz使用cookie进行身份认证,而一些代理缓存了cookie头,造成一个cache多人使用造成的问题。http://bbs.chinaunix.net/viewthread.php?tid=837214

2、依然是缓存的问题。只不过这个缓存可以存在于cn大局域网,或者某些ISP,比如google的例子,或者某些地区的服务商,抑或……

您是通过什么网络上的淘宝,据我所知,移动的浙江固网宽带出现过类似的严重安全隐患。宽带网络运营商的问题很大(强制建立缓存代理服务器,缓存不该缓存的网页),网站的问题是其次的。或者说,在那种情况下,绝大多数网站用户都会出现“穿越”现象。
如果被你穿越的人和你斗处在同一城市,基本上就是这个原因了。

解决方法,且听下次分解。

如果您的网站出现类似问题,欢迎加我qq176300676一起收集数据样本进行分析

亦可加入msn讨论群 lampper@live.cn

]]>
http://www.sunboyu.cn/2010/03/30/discuz%e8%b4%a6%e5%8f%b7%e6%b7%b7%e4%b9%b1%e9%97%ae%e9%a2%98%e7%a0%94%e7%a9%b6.shtml/feed
discuz论坛sessions表最终优化方案 http://www.sunboyu.cn/2010/01/17/discuz%e8%ae%ba%e5%9d%9bsessions%e8%a1%a8%e6%9c%80%e7%bb%88%e4%bc%98%e5%8c%96%e6%96%b9%e6%a1%88.shtml http://www.sunboyu.cn/2010/01/17/discuz%e8%ae%ba%e5%9d%9bsessions%e8%a1%a8%e6%9c%80%e7%bb%88%e4%bc%98%e5%8c%96%e6%96%b9%e6%a1%88.shtml#comments Sun, 17 Jan 2010 15:00:29 +0000 admin http://www.sunboyu.cn/?p=1163 最近一直在折腾dz的sessions表优化。经过某群好友的各种方法提示和一些高数据量用户论坛的鼎力支持,总结以下优化方案。部分方案是在某些论坛正在使用的,部分方案是我发散思维总结的,没有经过大数据量和大负载下的应用,只是作为一个备选的方案,当然欢迎朋友们拿去实践。

1、分库

这个方法至少两三个注册用户百万级至千万级的论坛在使用。实施也比较简单,只需要把sessions表放在其他的库中,跟论坛主库分离,这样,就可以用多台服务器来分担论坛压力。sessions表查询的地方,如果直接查询,则连sessions表所在的库,如果是联查,则分别查询后,合并插叙结果。

2、砍功能

这个方法虽然不实用,但的确有效。仔细看看dz的一些sql语句,就知道砍掉某些功能摆脱sessions表的约束,性能会有多大的提高。砍功能,最终还是为了提升性能。但如果不砍功能又提升性能,才是终极目的。此方法适用于对某些统计功能要求不高的论坛使用。

3、memcached存储sessions,异步统计用户的在线数据

此方法其实还是砍掉了论坛的用户在线统计功能而独立开发一套统计系统。此思路来源于我们的统计服务器。如果统计服务器已经统计了部分信息,就没必要再去耗费大量的sql效率去进行统计。当时我们负责统计的吴同学正好也要开发一套针对不同系统的统计代码,我可以直接把要统计的数据提交给统计服务器,再由统计服务器返回统计结果。以异步的方式来统计,化解dz sessions表的性能瓶颈。而统计信息的异步提交,可以提交到本地数据库,可以提交到第三方统计系统,当然也可以根据需要独立开发一套小型统计系统。

方案3是本人原创方案,方案的修改代码在以下附件中: 异步session统计信息同步,欢迎大家使用。

由于dz的开发考虑的是大众市场,功能冗余代码逻辑复杂。但优化dz并不是那么的困难,而优化的思路,也是跟其他系统优化相似:mysql瓶颈。一个即将崩溃的系统,或者频繁崩溃的系统,是进行优化的最好示例:减少sql查询,提高sql语句查询效率。dz考虑大众市场,为了提高产品兼容性,并没有引入太多的第三方软件:比如memcached,bdb,ttserver等,虽然内部已经为主从预留了接口,但未见很明显的文档支持。
第三个方案优化的思路也很明显,减少sessions表的慢查询而改为memcached高速的数据存储,把统计功能做接口留出,此功能给第三方来做。这样sessions表的瓶颈即可消除。

]]>
http://www.sunboyu.cn/2010/01/17/discuz%e8%ae%ba%e5%9d%9bsessions%e8%a1%a8%e6%9c%80%e7%bb%88%e4%bc%98%e5%8c%96%e6%96%b9%e6%a1%88.shtml/feed
撞在墙上的一个思路 http://www.sunboyu.cn/2010/01/16/%e6%92%9e%e5%9c%a8%e5%a2%99%e4%b8%8a%e7%9a%84%e4%b8%80%e4%b8%aa%e6%80%9d%e8%b7%af.shtml http://www.sunboyu.cn/2010/01/16/%e6%92%9e%e5%9c%a8%e5%a2%99%e4%b8%8a%e7%9a%84%e4%b8%80%e4%b8%aa%e6%80%9d%e8%b7%af.shtml#comments Fri, 15 Jan 2010 16:59:49 +0000 admin http://www.sunboyu.cn/?p=1159 今天一天没干别的,没写程序,没玩游戏,除了中午参加公司的一个吹气球比赛得了第一,获得“**公司第一吹”的称号。

一天都在考虑使用完全开源的方案来解决dz sessions表的性能问题。中午大脑极度紧张,以至于撞在关兄的工位,工位几近散架。

在轻度震荡中想到一个优化方案,就是分离sessions表的一些功能,把sessions会话和统计功能分离,并且统计使用异步提交。

这样,如果sessions会话生存期10分钟的量计算,20万人同时在线,sessions会话存memcached,而统计只用少量字段在独立的表中。因为php的sessions操作速度高,而统计信息调用并不是非常频繁,并且查找也是简单的int型查询,速度快,并且也进行memcached缓存。

下午吴同学详细讲述了我们的统计系统的负载和数据量,在大量实际应用的基础上,我的方案应该能很好的实施。

这样算来,连接瓶颈跟存储瓶颈似乎都能解决。明天集中时间实现这个方案。

]]>
http://www.sunboyu.cn/2010/01/16/%e6%92%9e%e5%9c%a8%e5%a2%99%e4%b8%8a%e7%9a%84%e4%b8%80%e4%b8%aa%e6%80%9d%e8%b7%af.shtml/feed
关于discuz的优化纠结 http://www.sunboyu.cn/2010/01/15/%e5%85%b3%e4%ba%8ediscuz%e7%9a%84%e4%bc%98%e5%8c%96%e7%ba%a0%e7%bb%93.shtml http://www.sunboyu.cn/2010/01/15/%e5%85%b3%e4%ba%8ediscuz%e7%9a%84%e4%bc%98%e5%8c%96%e7%ba%a0%e7%bb%93.shtml#comments Fri, 15 Jan 2010 07:23:42 +0000 admin http://www.sunboyu.cn/?p=1155 最近一直在寻找一个开源的方案来解决discuz的性能瓶颈。在做完几个关键表的分表后,sessions表又成了最大的瓶颈。因为页面每次刷新,至少两个sql语句在session表上,究其原因,session表的最大作用在于对用户行为的统计。

曾经尝试过使用php的session,不过支持phpsession的几个sever都不支持条件查询,除非是遍历匹配。这样也不能起到提高性能的作用。

在以上条件下,我寻找了两套方案:ttserver mongodb。

在session表100w数据的测试下,得出以下数据:

连接测试-只测试连接释放
tt:40.0904033184
mysqldb:0.0669066905975

mongodb:226.840053558
mysqldb:0.154407262802

经过一万次的连接测试,同一个脚本中,
ttserver连接耗时 40.09 秒,而mysql连接耗时0.07秒 linux下测试
mongodb 连接耗时 226.8 秒,而mysql连接耗时0.15秒 linux下测试

但是在500次的查询测试中,同一个脚本中,主键查询和索引优化后的复杂查询
mongodb 查询耗时 0.021 秒
mysql 查询耗时 0.123 秒

可以看出,tt和mongo两个功能上完全支持此表优化的数据库,在连接性能上远不如mysql,而web为频繁连接中断的服务,显然并不适合做这项功能。

继续寻找支持此功能的开源方案,欢迎大家提供线索。

]]>
http://www.sunboyu.cn/2010/01/15/%e5%85%b3%e4%ba%8ediscuz%e7%9a%84%e4%bc%98%e5%8c%96%e7%ba%a0%e7%bb%93.shtml/feed
单点登录sso粗解+示例 http://www.sunboyu.cn/2009/12/31/%e5%8d%95%e7%82%b9%e7%99%bb%e5%bd%95sso%e7%b2%97%e8%a7%a3%e7%a4%ba%e4%be%8b.shtml http://www.sunboyu.cn/2009/12/31/%e5%8d%95%e7%82%b9%e7%99%bb%e5%bd%95sso%e7%b2%97%e8%a7%a3%e7%a4%ba%e4%be%8b.shtml#comments Thu, 31 Dec 2009 02:56:46 +0000 admin http://www.sunboyu.cn/?p=1131

用户中心代码 sso
跨域测试脚本 cookie

单点登录,英语为 Single Sign-On,粗俗点讲,就是登录一次,全站适用。

单点登录在应用中的实际意义,就是减少开发量,增强用户体验。

减少开发量,指的是:只要开发一套用户系统, 各个系统统一调用。用户系统尽量优化接口,通用性,安全性,达到一次开发, 全站适用。

增强用户体验,指的是:用户一次登录,全站登录。而不是切换一个模块,就登录一次。

web方面单点登录主要是用cookie传递令牌进行身份认证。简单说下令牌。

我这里用散列值来作为令牌,当然散列值之中有我的的密钥,防止别人伪造我的令牌。

环境:sso.sunboyu.cn 用户中心 vps.sunboyu.cn/cookie.php 跨子域不同脚本访问测试。 令牌密钥: $key

具体规则: sso.sunboyu.cn 用户登录,登录信息写到cookie,cookie做用域为 sunboyu.cn。并且生成令牌sso_key=md5(uid+username+key)。

登陆后,其他子域站点调用此cookie信息,并且验证此令牌是否是合法的令牌,if( md5( cookie[uid]+cookie[username] )==cookie[key] )

这样既可判断,此令牌合法性而确认此用户为登录。

具体demo:http://sso.sunboyu.cn

延伸:一个简单的md5似乎很容易让别人猜解加密的算法,来暴力一翻也不是没有可能,因此,除了加密外,算法的安全性和密钥的安全性也是需要考虑的。

如果安全级别要求高之又高,可以考虑rsa算法,不过速度就是问题了。其中又参考了一些朋友的意见,用对称加密,比如php中的Mcrypt 函数。

扩展开发:对于大多数网站,跨子域的单点登录就能满足应用。但对于一些域名复杂的网站,比如sohu,显然多个域名不能用此方法实现。这时就得搞出跨跨的单点登录系统。等年后继续得瑟。

]]>
http://www.sunboyu.cn/2009/12/31/%e5%8d%95%e7%82%b9%e7%99%bb%e5%bd%95sso%e7%b2%97%e8%a7%a3%e7%a4%ba%e4%be%8b.shtml/feed
使用无模式数据库来改造dz的session http://www.sunboyu.cn/2009/12/29/%e4%bd%bf%e7%94%a8%e6%97%a0%e6%a8%a1%e5%bc%8f%e6%95%b0%e6%8d%ae%e5%ba%93%e6%9d%a5%e6%94%b9%e9%80%a0dz%e7%9a%84session.shtml http://www.sunboyu.cn/2009/12/29/%e4%bd%bf%e7%94%a8%e6%97%a0%e6%a8%a1%e5%bc%8f%e6%95%b0%e6%8d%ae%e5%ba%93%e6%9d%a5%e6%94%b9%e9%80%a0dz%e7%9a%84session.shtml#comments Tue, 29 Dec 2009 01:26:58 +0000 admin http://www.sunboyu.cn/?p=1124 前两天还不知道啥是无模式数据库,不过最近迫切需要修改discuz bbs的session表,所以研究了一下相关的资料,发现了无模式这个名字。

具体无模式是啥,这里找了两篇文章:

关系数据库的末日是否已经来临
关系数据库的根本问题分析及数据库革命之走向

关于无模式的应用案例,很典型的一个,就是康盛uchome的feed表。

这里简单介绍几个无模式数据库,供大家参考:

mongodb : http://www.mongodb.org/display/DOCS/Home

mongodb的php扩展 http://www.mongodb.org/display/DOCS/Installing+the+PHP+Driver#InstallingthePHPDriver-PECL

这个数据库已经在淘宝上配合10gen做了云计算的session(名字很操蛋),具体资料在这里 http://rdc.taobao.com/blog/dw/archives/410。具有了实际应用的东西应该很不错,不过我没尝试过。

Tokyo Tyrant:http://1978th.net/

tt的php扩展 http://www.php.net/manual/en/book.tokyo-tyrant.php

这个大家就比较熟悉了,SB日本鬼子写的东西,应用很广,sina,qq等公司里都在大量应用,sina的研发团队在此基础上还做了个分布式的东东,很是不错。据说这玩意还得到了很多公司的赞助,shit。

TCSQL:张宴基于tt开发的一套东西,内部做了很多算法优化,具体可参考此文章 http://blog.s135.com/tcsql/

总结:康盛使用mysql来存储session,不能说是一种错,但对于dz的负载绝对是第一个瓶颈。用这种方式,在线人数5w对数据库绝对是个坎。很多负载比较大的论坛,都做了此方面的优化,比如,给session表单独一个数据库,或者干脆阉割此功能。不错,独立的session表,或者分库,访问量大的时候,瓶颈依然在mysql上;阉割此功能,有些心疼,而且很多运营数据会丢失。所以,保持原功能而平滑提升性能,是一个不错的解决方向。

]]>
http://www.sunboyu.cn/2009/12/29/%e4%bd%bf%e7%94%a8%e6%97%a0%e6%a8%a1%e5%bc%8f%e6%95%b0%e6%8d%ae%e5%ba%93%e6%9d%a5%e6%94%b9%e9%80%a0dz%e7%9a%84session.shtml/feed
改变exec的阻塞模式 http://www.sunboyu.cn/2009/12/25/%e6%94%b9%e5%8f%98exec%e7%9a%84%e9%98%bb%e5%a1%9e%e6%a8%a1%e5%bc%8f.shtml http://www.sunboyu.cn/2009/12/25/%e6%94%b9%e5%8f%98exec%e7%9a%84%e9%98%bb%e5%a1%9e%e6%a8%a1%e5%bc%8f.shtml#comments Fri, 25 Dec 2009 02:19:41 +0000 admin http://www.sunboyu.cn/?p=1118 > /dev/null &” ) ]]> 很多操作时间会很长,不能让用户在页面上执行PHP脚本,否则页面会被拖死。

一个不错的方案,就是提交到后台去执行。

linux有个命令 nohup command & 这样就会提交到后台,而终端的用户体会不到程序执行的过程。

原来我使用这种方式 shell_exec( “nohuo php file.php &” ) 进行后台提交,后来发现速度依然不快, 还是被挂起了。查看手册,exec函数有如下提示:

Note: 如果用本函数启动一个程序并希望保持在后台运行,必须确保该程序的输出被重定向到一个文件或者其它输出流去,否则 PHP 会在程序执行结束前挂起。

因此,这样修改就达到了目的:

exec( “nohuo php file.php >> /dev/null &” )

]]>
http://www.sunboyu.cn/2009/12/25/%e6%94%b9%e5%8f%98exec%e7%9a%84%e9%98%bb%e5%a1%9e%e6%a8%a1%e5%bc%8f.shtml/feed
完全缓存discuz论坛数据 http://www.sunboyu.cn/2009/12/06/%e5%ae%8c%e5%85%a8%e7%bc%93%e5%ad%98discuz%e8%ae%ba%e5%9d%9b%e6%95%b0%e6%8d%ae.shtml http://www.sunboyu.cn/2009/12/06/%e5%ae%8c%e5%85%a8%e7%bc%93%e5%ad%98discuz%e8%ae%ba%e5%9d%9b%e6%95%b0%e6%8d%ae.shtml#comments Sun, 06 Dec 2009 14:15:07 +0000 admin http://www.sunboyu.cn/?p=1072 >>> 发帖数/更新时间 ,则有必要做此缓存,此处缓存更新最为频繁,适合做内存缓存,但 更新时间不宜太久,此时间根据首页更新频度确定。 forumdisplay.php 更新频繁,优化策略同上,只是更新频度略低于首页。 viewthread.php 回复更新频繁,内容更新频度低,适合做硬盘缓存。但分页部分不可做缓存,否则…… space.php 更新不频繁,适合做硬盘缓存。 faq.php 做个静态即可。 以上分析只是根据平时维护总结,临时脑子一蹦,未作具体分析,欢迎广大站长讨论试用。版权所有,欢迎盗版。 ]]> 最近一直在琢磨discuz的优化,想出一些数据缓存的策略:

index.php 部分数据已经进行了缓存,但需要全部缓存,只有当 页面刷新数/更新时间 >>>> 发帖数/更新时间 ,则有必要做此缓存,此处缓存更新最为频繁,适合做内存缓存,但 更新时间不宜太久,此时间根据首页更新频度确定。

forumdisplay.php 更新频繁,优化策略同上,只是更新频度略低于首页。

viewthread.php 回复更新频繁,内容更新频度低,适合做硬盘缓存。但分页部分不可做缓存,否则……

space.php 更新不频繁,适合做硬盘缓存。

faq.php 做个静态即可。

以上分析只是根据平时维护总结,临时脑子一蹦,未作具体分析,欢迎广大站长讨论试用。版权所有,欢迎盗版。

]]>
http://www.sunboyu.cn/2009/12/06/%e5%ae%8c%e5%85%a8%e7%bc%93%e5%ad%98discuz%e8%ae%ba%e5%9d%9b%e6%95%b0%e6%8d%ae.shtml/feed
大话discuz性能优化 http://www.sunboyu.cn/2009/11/27/%e5%a4%a7%e8%af%9ddiscuz%e6%80%a7%e8%83%bd%e4%bc%98%e5%8c%96.shtml http://www.sunboyu.cn/2009/11/27/%e5%a4%a7%e8%af%9ddiscuz%e6%80%a7%e8%83%bd%e4%bc%98%e5%8c%96.shtml#comments Fri, 27 Nov 2009 15:46:31 +0000 admin http://www.sunboyu.cn/?p=1065 接此篇 http://www.sunboyu.cn/2009/11/05/discuz%E8%AE%BA%E5%9D%9B%E4%BC%98%E5%8C%96.shtml

最近一直在修改discuz,看到了很多问题,在跟系统工程部门合作的时候,也看到了很多比较优秀的解决方案,可以引入到系统中。

底下粗略讲述下已经做过的优化和可以着手进行的优化。

对于一个数据量比较大的论坛,首先是分表。posts表,threads表是必须要分的。可以按照forum表的fid进行分,也可以使用tid进行hash散列分布。分表带来的问题,显然是分页。我们进行排序的时候不可能去进行union查询,否则就失去了分表的意义。在这里,我们使用了一个支持排序的key-value型存储的小型数据库-Tokyo Tyrant(http://1978th.net/tokyotyrant/),用此数据库去同步threads表和posts表的数据,达到高速分页。(附:典型应用可以参见此文章 http://blog.s135.com/tcsql/ )

随着数据表的膨胀,很多join联查必须进行拆分。分表可能强制我们去拆分联查,另外一些很变动不大的表,比如用户信息表的数据,使用率明显很高,变动不会太大,而使用key-value存储再合适不过。这时候,bdb和memcached是首选,我推荐使用bdb,可以持久存储于硬盘上,由用户更新资料触发更新,不必考虑过期和服务器重启的问题。这样可以减少太多的join联查,而节约数据库服务器的缓存。

随着静态文件的增长和访问量的增长,带宽浪费是一个值得考虑的问题。我们打开discuz的首页,静态文件要比php文件多好几倍,而每个文件都夹带了长长的cookie信息,因此,把这些cookie去掉显然会节约大量的带宽。discuz的文件结构还是很不错的,通常通过一个参数的配置或者全文替换就能完成这项工作。此应用,可以在新浪所有的图片上有所体现。

全文检索是mysql所不擅长的,因此附加一个好的全文检索方案很必须,我熟悉的方案:Lucene,sphinx,whoosh是我喜欢的几个全文检索的工具,对于discuz的负载,我感觉任何一个都能满足应用。在此方案上,设计一个完美的同步触发机制很重要。

还有很多问题,都在待发现中,部分问题已经解决,部分问题可以优化。discuz优化好,其实是个不错的产品。

]]>
http://www.sunboyu.cn/2009/11/27/%e5%a4%a7%e8%af%9ddiscuz%e6%80%a7%e8%83%bd%e4%bc%98%e5%8c%96.shtml/feed
给WordPress加了个每日谚语插件 http://www.sunboyu.cn/2009/11/23/%e7%bb%99wordpress%e5%8a%a0%e4%ba%86%e4%b8%aa%e6%af%8f%e6%97%a5%e8%b0%9a%e8%af%ad%e6%8f%92%e4%bb%b6.shtml http://www.sunboyu.cn/2009/11/23/%e7%bb%99wordpress%e5%8a%a0%e4%ba%86%e4%b8%aa%e6%af%8f%e6%97%a5%e8%b0%9a%e8%af%ad%e6%8f%92%e4%bb%b6.shtml#comments Mon, 23 Nov 2009 15:04:53 +0000 admin http://www.sunboyu.cn/?p=1060 很久没写点自己的小代码了,感觉手生。

  1. < ?=$voice[rand(0,count($voice)-1)]?>  #加在title的地方,$voice这个数组随便找个地方塞一下就行
]]>
http://www.sunboyu.cn/2009/11/23/%e7%bb%99wordpress%e5%8a%a0%e4%ba%86%e4%b8%aa%e6%af%8f%e6%97%a5%e8%b0%9a%e8%af%ad%e6%8f%92%e4%bb%b6.shtml/feed
discuz论坛优化 http://www.sunboyu.cn/2009/11/05/discuz%e8%ae%ba%e5%9d%9b%e4%bc%98%e5%8c%96.shtml http://www.sunboyu.cn/2009/11/05/discuz%e8%ae%ba%e5%9d%9b%e4%bc%98%e5%8c%96.shtml#comments Thu, 05 Nov 2009 10:19:59 +0000 admin http://www.sunboyu.cn/?p=1031 discuz论坛在国内非常流行,用户众多。优秀的用户体验和超强的负载,也赢得了众多的好评。

但discuz毕竟是为中小型网站设计,很容易达到性能的瓶颈。在最近对discuz的改造和表结构的分析,做了以下的探讨,来提升论坛的性能。

第一步,当然就是分表。
技术实力不太强的用户(严重依赖mysql的用户),分表是最直接的做法(当然,有些功能会损失)。

分析一个运营两年的discuz数据库,库表大概是十几个G左右,posts数据表已经几个千万。

首先可以拆分的,就是post表了。根据情况,post表可以分10张,百张,规则可以哈希,也可以阶段自增(分表主键使用tid(帖子id))。分完表,可以看到一排post_**的表,每个表的数据量降到百万以下,速度就无太大影响。

第二个可以拆分的,是threads表,此表分表,可以水平分割方式水平的分割,可以根据论坛版块id进行分表,这样可以使每个表的数据量减小,但这样也损失了一个功能:全站标题检索。

通过以上两个表的改造论坛的承载能力能迅速见长。

底下会讨论高级优化改造得方法,且听下次分解。

]]>
http://www.sunboyu.cn/2009/11/05/discuz%e8%ae%ba%e5%9d%9b%e4%bc%98%e5%8c%96.shtml/feed
php使用header来控制cookie http://www.sunboyu.cn/2009/09/28/php%e4%bd%bf%e7%94%a8header%e6%9d%a5%e6%8e%a7%e5%88%b6cookie.shtml http://www.sunboyu.cn/2009/09/28/php%e4%bd%bf%e7%94%a8header%e6%9d%a5%e6%8e%a7%e5%88%b6cookie.shtml#comments Mon, 28 Sep 2009 07:33:33 +0000 admin http://www.sunboyu.cn/?p=1011 php中的setcookie函数是有bug的,bug原理不太明白,不过底下这个方法可以避免这个bug

  1. function setcookies( $name , $value , $expire , $path = "/" , $domain = "" )
  2. {
  3.     header("Set-Cookie: $name=$value; path=$path; domain=$domain; expires=".gmstrftime("%A, %d-%b-%Y %H:%M:%S GMT",$expire));
  4. }
]]>
http://www.sunboyu.cn/2009/09/28/php%e4%bd%bf%e7%94%a8header%e6%9d%a5%e6%8e%a7%e5%88%b6cookie.shtml/feed
mysql数据抽象层-PDO http://www.sunboyu.cn/2009/08/20/mysql%e6%95%b0%e6%8d%ae%e6%8a%bd%e8%b1%a1%e5%b1%82-pdo.shtml http://www.sunboyu.cn/2009/08/20/mysql%e6%95%b0%e6%8d%ae%e6%8a%bd%e8%b1%a1%e5%b1%82-pdo.shtml#comments Thu, 20 Aug 2009 08:02:02 +0000 admin http://www.sunboyu.cn/?p=953 好久不用PDO了,公司这边有的项目使用PDO,再熟悉一下,继续沿用之前的方法:

没用数据绑定和一些高级的功能,只是实现基础功能。

  1. < ?php
  2. interface DateBaseConnect
  3. {
  4. #数据库连接
  5. public function Connect( $host , $user , $pass , $datebase );
  6. #使用数据库
  7. public function selectDateBase( $datebase );
  8. #执行一个查询
  9. public function query( $sql );
  10. #取得一行
  11. public function fetch( $sql );
  12. #取得所有
  13. public function fetchAll( $sql );
  14. #取得影响行数
  15. public function affectedRow();
  16. #取得结果行数
  17. public function recordCount();
  18. #取得上次插入ID
  19. public function insertID();
  20. #释放资源
  21. public function close();
  22. }
  23. class sPDO implements DateBaseConnect
  24. {
  25. #连接标识
  26. public $handle = false;
  27. #结果标识
  28. public $query;
  29. #查询次数
  30. public $exetime;
  31. #影响行数
  32. public $affectedRows;
  33. #statement
  34. public $statement;
  35. #数据库连接
  36. public function Connect( $host , $user , $pass , $datebase )
  37. {
  38. try
  39. {
  40. $this->handle = new PDO("mysql:dbname=".$datebase.";host=".$host, $user, $pass);
  41. }
  42. catch (PDOException $e)
  43. {
  44.             echo 'Connection failed: ' . $e->getMessage();
  45. }
  46. $this->exetime = 0;
  47. }
  48. #选择数据库
  49. public function selectDateBase( $database )
  50. {
  51.     return true;
  52. }
  53. #执行一个查询
  54. public function query( $sql )
  55. {
  56.     $this->affectedRows = $this->handle->exec( $sql );
  57. $this->exetime++;
  58. return true;
  59. }
  60. #取得一行
  61. public function fetch( $sql )
  62. {
  63. $this->statement = $this->handle->query( $sql );
  64. return $this->statement->fetch(PDO::FETCH_ASSOC);
  65. }
  66. #取得所有
  67. public function fetchAll( $sql )
  68. {
  69. $this->statement = $this->handle->query( $sql );
  70. return $this->statement->fetchAll(PDO::FETCH_ASSOC);
  71. }
  72. #取得影响行数
  73. public function affectedRow()
  74. {
  75. return $this->affectedRows;
  76. }
  77. #取得结果行数
  78. public function recordCount()
  79. {
  80. return $this->statement->rowCount();
  81. }
  82. #取得上次插入ID
  83. public function insertID()
  84. {
  85. $sql = sprintf("SELECT LAST_INSERT_ID() AS id");
  86. $pdostatement = $this->handle->query( $sql );
  87. $rs = $pdostatement->fetch();
  88. return $rs['id'];
  89. }
  90. #释放资源
  91. public function close()
  92. {
  93. unset($this->handle);
  94. }
  95. #析构函数
  96. function __destruct()
  97. {
  98. $this->close();
  99. }
  100. }
  101. #Demo
  102. $db = new sPDO;
  103. $db->Connect( 'localhost' , 'root' , '123456' , 'ucenterhome' );
  104. $rs = $db->fetchAll( "SELECT * FROM uchome_blogfield" );
  105. print_r( $rs );
  106. ?>
]]>
http://www.sunboyu.cn/2009/08/20/mysql%e6%95%b0%e6%8d%ae%e6%8a%bd%e8%b1%a1%e5%b1%82-pdo.shtml/feed
对UCenter Home的一点看法 http://www.sunboyu.cn/2009/08/17/%e5%af%b9ucenter-home%e7%9a%84%e4%b8%80%e7%82%b9%e7%9c%8b%e6%b3%95.shtml http://www.sunboyu.cn/2009/08/17/%e5%af%b9ucenter-home%e7%9a%84%e4%b8%80%e7%82%b9%e7%9c%8b%e6%b3%95.shtml#comments Mon, 17 Aug 2009 14:27:19 +0000 admin http://www.sunboyu.cn/?p=950 最近改了改UCenter Home,发现,这的确是个不错的产品,但不能算一个成熟的程序。

产品看法:

这个产品主要是服务一些个人站长和小型站点,功能模仿一些成熟的sns系统,模仿比较到位,而且功能上尽可能大的去完善,让管理员可以方便进行比较系统全面的管理。而从产品的设计体验上,也能适应中国大多数的用户。

所以,这个产品在国内算一套非常不错的sns建站系统。

编码方面:

要说代码,我相信阅读过代码的人一定很头疼,从discuz的bbs就这样。

代码只是面向过程,这个,在discuz方面,我估计是累积开发造成的,一个个版本升级,变化不能太大,如果变化真的太大,会失去一些开发者。另外,他自己升级也是个问题。

不过uch这个产品也开发成了这样。代码结构我倒挺喜欢,之前我写那个架子也是这样。优点:结构规范,适合多人协作。缺点,面向对象性,代码复用差。这个结构,我估计是公司某元老折腾的,然后有几个小弟进行模块开发。

为什么这么说,是有原因的,因为遍历整个代码,起码有两种以上的代码风格,而且人员之间沟通配合也造成了一些错误,虽然不是bug,但看得出来项目进行的仓促。不过这也是公司的一个战略措施,小戴同学总是及时放出产品来打压竞争对手。

再说负载,其实这个问题就不用说,从大量的垃圾sql语句就能看出,这个产品不能支持较大的负载。

再说最后一点,如果你想去优化改善,彻底改善,放弃吧。重写。

我看的只是uch2.0的预览版,估计正式版放出的时候,这些问题会有所改善。

]]>
http://www.sunboyu.cn/2009/08/17/%e5%af%b9ucenter-home%e7%9a%84%e4%b8%80%e7%82%b9%e7%9c%8b%e6%b3%95.shtml/feed
Discuz一些乱码错误的总结 http://www.sunboyu.cn/2009/08/03/discuz%e4%b8%80%e4%ba%9b%e4%b9%b1%e7%a0%81%e9%94%99%e8%af%af%e7%9a%84%e6%80%bb%e7%bb%93.shtml http://www.sunboyu.cn/2009/08/03/discuz%e4%b8%80%e4%ba%9b%e4%b9%b1%e7%a0%81%e9%94%99%e8%af%af%e7%9a%84%e6%80%bb%e7%bb%93.shtml#comments Mon, 03 Aug 2009 14:19:12 +0000 admin http://www.sunboyu.cn/2009/08/03/discuz%e4%b8%80%e4%ba%9b%e4%b9%b1%e7%a0%81%e9%94%99%e8%af%af%e7%9a%84%e6%80%bb%e7%bb%93.shtml 最近用Discuz6.0,在用到分类信息功能的时候,自建模板总是出现错误,仔细跟踪,发现是个别模板编码错误。我用的UTF-8版本,有不少文件里用了中文字符,而且是gbk编码,造成了这种错误。

我google此类信息,有不少问题都出现在了编码上,建议网友在使用的时候,发现编码错误,仔细跟踪一下,找出模板。大部分的问题基本能以此方式解决。

]]>
http://www.sunboyu.cn/2009/08/03/discuz%e4%b8%80%e4%ba%9b%e4%b9%b1%e7%a0%81%e9%94%99%e8%af%af%e7%9a%84%e6%80%bb%e7%bb%93.shtml/feed
smarty分页程序,模板小改进 http://www.sunboyu.cn/2009/07/27/smarty%e5%88%86%e9%a1%b5%e7%a8%8b%e5%ba%8f%ef%bc%8c%e6%a8%a1%e6%9d%bf%e5%b0%8f%e6%94%b9%e8%bf%9b.shtml http://www.sunboyu.cn/2009/07/27/smarty%e5%88%86%e9%a1%b5%e7%a8%8b%e5%ba%8f%ef%bc%8c%e6%a8%a1%e6%9d%bf%e5%b0%8f%e6%94%b9%e8%bf%9b.shtml#comments Mon, 27 Jul 2009 07:11:04 +0000 admin http://www.sunboyu.cn/?p=899 增加了:跳转到第几页的功能

模板部分

  1. <div id="page">
  2. <table>
  3.     <tr>
  4.     <td>
  5. 共{{$page.count}}条数据 每页{{$page.pagesize}}条  共{{$page.pagecount}}页 当前第{{$page.page}}页
  6.                 <!-- 新加的跳转功能  start -->
  7.                 跳转到第
  8.                 <select onchange="window.location.href='{{$page.baseurl}}&page='+this.options[this.selectedIndex].value">
  9.                 {{section name=pagejump loop=4 start=0 step=1 max=4}}
  10.                 <option value="{{$smarty.section.pagejump.index+1}}">{{$smarty.section.pagejump.index+1}}</option>
  11.                 {{/section}}
  12.                 </select> 页
  13.                 <!-- 新加的跳转功能  start -->
  14. </td>
  15. <td>
  16. {{if $page.pagecount>1}}
  17. {{if $page.first eq 1}}
  18. <a href="{{$page.baseurl}}">首页</a>
  19. {{else}}
  20. 首页
  21. {{/if}}
  22. {{if $page.pre eq 1}}
  23. <a href="{{$page.baseurl}}&page={{$page.page-1}}">上一页</a>
  24. {{else}}
  25. 上一页
  26. {{/if}}
  27. {{foreach from=$page.pagelist item=vols}}
  28.     {{if ($vols.page > 0 ) && ($vols.page < = $page.pagecount) }}
  29. {{if $vols.link eq 1}}
  30. <a href="{{$page.baseurl}}&page={{$vols.page}}">[{{$vols.page}}]
  31. {{else}}
  32. [{{$vols.page}}]
  33. {{/if}}
  34. {{/if}}
  35. {{/foreach}}
  36. {{if $page.next eq 1}}
  37. <a href="{{$page.baseurl|default:"?"}}&page={{$page.page+1}}">下一页</a>
  38. {{else}}
  39. 下一页
  40. {{/if}}
  41. {{if $page.last eq 1}}
  42. <a href="{{$page.baseurl|default:"?"}}&page={{$page.pagecount}}">尾页</a>
  43. {{else}}
  44. 尾页
  45. {{/if}}
  46. {{/if}}
  47. </td>
  48. </tr>
  49. </table>
  50. </div>

其实我在做的时候又出现个问题,如果是url重写了,如何来做这个baseurl变量。问题解决方法是,把url当做模板,比如/blog/index/%d

]]>
http://www.sunboyu.cn/2009/07/27/smarty%e5%88%86%e9%a1%b5%e7%a8%8b%e5%ba%8f%ef%bc%8c%e6%a8%a1%e6%9d%bf%e5%b0%8f%e6%94%b9%e8%bf%9b.shtml/feed
使用成语的文字验证码 http://www.sunboyu.cn/2009/07/24/%e4%bd%bf%e7%94%a8%e6%88%90%e8%af%ad%e7%9a%84%e6%96%87%e5%ad%97%e9%aa%8c%e8%af%81%e7%a0%81.shtml http://www.sunboyu.cn/2009/07/24/%e4%bd%bf%e7%94%a8%e6%88%90%e8%af%ad%e7%9a%84%e6%96%87%e5%ad%97%e9%aa%8c%e8%af%81%e7%a0%81.shtml#comments Fri, 24 Jul 2009 13:48:44 +0000 admin http://www.sunboyu.cn/?p=897 上次写的nb验证码程序,遭到了大部分人的唾弃,因为我使用了中国汉字全集,而大部分中国人对汉字了解还只能占其一半,也就是四个汉字中经常出现生僻字,造成无法使用。

这次使用成语作为汉字验证码(其实已经发现其他网站再用),则中文用户识别的几率就大得多。

demo:

程序下载:点击下载

]]>
http://www.sunboyu.cn/2009/07/24/%e4%bd%bf%e7%94%a8%e6%88%90%e8%af%ad%e7%9a%84%e6%96%87%e5%ad%97%e9%aa%8c%e8%af%81%e7%a0%81.shtml/feed
图片动态缩放PHP与JS算法 http://www.sunboyu.cn/2009/07/20/%e5%9b%be%e7%89%87%e5%8a%a8%e6%80%81%e7%bc%a9%e6%94%bephp%e4%b8%8ejs%e7%ae%97%e6%b3%95.shtml http://www.sunboyu.cn/2009/07/20/%e5%9b%be%e7%89%87%e5%8a%a8%e6%80%81%e7%bc%a9%e6%94%bephp%e4%b8%8ejs%e7%ae%97%e6%b3%95.shtml#comments Mon, 20 Jul 2009 00:19:05 +0000 admin http://www.sunboyu.cn/?p=875 这个算法写好多次了,虽然简单,但每次都得想一次,这里做个备份。

因为GD函数进行缩放,必须有宽和高,而在浏览器中,会自动按照比率调整宽高,所以两个函数稍有区别。

  1. #PHP版
  2. # $s_width  原图宽
  3. # $s_height 原图高
  4. # $t_width  目标文件最大宽
  5. # $t_height 目标文件最大高
  6. function ReSizePic( $s_width , $s_height , $t_width , $t_height)
  7. {
  8. if( $s_width / $s_height > $t_width / $t_height && $s_width > $t_width)
  9. {
  10. $t_height = $s_height * $t_width / $s_width;
  11. $t_width = $t_width;
  12. }
  13. else if( $s_width / $s_height > $t_width / $t_height && $s_width < = $t_width)
  14. {
  15. $t_height = $s_height;
  16. $t_width  = $s_width;
  17. }
  18. else if( $s_width / $s_height < $t_width / $t_height && $s_height > $t_height)
  19. {
  20. $t_width = $s_width*$t_height/$s_height;
  21. $t_height = $t_height;
  22. }
  23. else if( $s_width / $s_height < $t_width / $t_height && $s_height <= $t_height)
  24. {
  25. $t_height = $s_height;
  26. $t_width  = $s_width;
  27. }
  28. return array( "width" => $t_width , "height" => $t_height );
  29. }
  30. #JS版
  31. # obj 图片对象
  32. # maxWidth 显示最大宽
  33. # maxHeight 显示最大高
  34. function ReSizePic( obj , maxWidth , maxHeight )
  35. {
  36. if( ( obj.width/obj.height >= maxWidth/maxHeight ) && obj.width > maxWidth )
  37. {
  38. obj.width = maxWidth;
  39. }
  40. else if( ( obj.width/obj.height < maxWidth/maxHeight ) && obj.height > maxHeight )
  41. {
  42. obj.height = maxHeight;
  43. }
  44. }
]]>
http://www.sunboyu.cn/2009/07/20/%e5%9b%be%e7%89%87%e5%8a%a8%e6%80%81%e7%bc%a9%e6%94%bephp%e4%b8%8ejs%e7%ae%97%e6%b3%95.shtml/feed
为FCKEditor增加图片附件管理功能 http://www.sunboyu.cn/2009/07/15/%e4%b8%bafckeditor%e5%a2%9e%e5%8a%a0%e5%9b%be%e7%89%87%e9%99%84%e4%bb%b6%e7%ae%a1%e7%90%86%e5%8a%9f%e8%83%bd.shtml http://www.sunboyu.cn/2009/07/15/%e4%b8%bafckeditor%e5%a2%9e%e5%8a%a0%e5%9b%be%e7%89%87%e9%99%84%e4%bb%b6%e7%ae%a1%e7%90%86%e5%8a%9f%e8%83%bd.shtml#comments Wed, 15 Jul 2009 05:38:10 +0000 admin http://www.sunboyu.cn/?p=858 其实好久没用过FCKEeditor了,因为将近两年没写过CMS,今天突然人品大爆发,想起了这个问题。

fckeditor是一个非常棒的所见即所得在线编辑器,包括一些门户网站都在使用。fckeditor有个问题,就是上传图片默认为一个文件夹,当然这个问题早已经解决,我们可以用cookie或者session的方式给参数 $Config['UserFilesPath'] 就可以定制上传路径。而后在文章保存的过程中即可保存图片地址。

然后在使用过程中又出现一个问题,虽然我们知道图片在哪个文件夹,但我们却不能动态的去知道具体文件夹内有哪几个图片,预览是什么。而且,我们在写CMS的时候经常需要调用其中一张图片做封面,原来的机制显然无法去满足这些需求(当然你也可以查看编辑器内的源代码来查看图片地址,不过对于外行似乎有点困难)。

突然看到了discuz的附件机制,相出这么个损招:每张图片上传都给他存储在数据库中,打上guid(或者唯一的地址)进行标识,当我们保存的时候,图片会跟文章关联,在使用之前还可以用ajax动态调用预览,可谓一举两得。

文章保存后,图片进入数据库,另外还可以方便找出编辑遗留的垃圾,因为很多时候一个已经传了文章的草稿没有保存,而遗留很多的临时文件。

最近的fck版本好像升级了,配置文件放从根目录迁移了,不过fck代码非常规整,做这么个改造不是很难,就没写demo。

———————————————-

文章很冗余,骗稿费?

]]>
http://www.sunboyu.cn/2009/07/15/%e4%b8%bafckeditor%e5%a2%9e%e5%8a%a0%e5%9b%be%e7%89%87%e9%99%84%e4%bb%b6%e7%ae%a1%e7%90%86%e5%8a%9f%e8%83%bd.shtml/feed
PHP开发的一个pureftpd管理工具 http://www.sunboyu.cn/2009/07/10/php%e5%bc%80%e5%8f%91%e7%9a%84%e4%b8%80%e4%b8%aapureftpd%e7%ae%a1%e7%90%86%e5%b7%a5%e5%85%b7.shtml http://www.sunboyu.cn/2009/07/10/php%e5%bc%80%e5%8f%91%e7%9a%84%e4%b8%80%e4%b8%aapureftpd%e7%ae%a1%e7%90%86%e5%b7%a5%e5%85%b7.shtml#comments Fri, 10 Jul 2009 08:49:14 +0000 admin http://www.sunboyu.cn/?p=850 用过pureftpd manager,虽然功能足够,但很多bug,无法使用,而pureftpd功能简单,写个管理工具也没多复杂,于是乎,花两个晚上写了个简单的管理脚本,分享给大家。不过没来得及写注释,回头会把注释补上。

分流下载 http://down.chinaz.com/soft/26439.htm

点击下载

  1. < ?php
  2. error_reporting(2047);
  3. header("Content-Type: text/html; charset=utf-8");
  4. header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
  5. header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // 过去的时间
  6. define("FILENAME",$_SERVER['PHP_SELF']);
  7. $adminuser = "admin";
  8. $adminpass = "admin";
  9.  
  10. $servtype = 'mysql';
  11. $hostname = 'localhost';
  12. $username = 'root';
  13. $password = '123456';
  14. $datebase = 'pure-ftpd';
  15. $table    = "users";
  16. $charset  = 'utf8';
  17. $crypt    = "MD5";
  18.  
  19. session_start();
  20. #session_destroy();
  21. $action = isset($_GET['action']) ? $_GET['action'] : "index";
  22.  
  23.  
  24. switch( $action )
  25. {
  26.     case "index":
  27.     checklogin();
  28. func_html( 0 );
  29. switch($_SESSION['user'])
  30. {
  31.     case $adminuser:
  32.     func_admin_index();
  33. break;
  34. default:
  35.     func_user_index();
  36. break;
  37. }
  38. func_html( 1 );
  39. break;
  40.     case "userlogin":
  41. case "adminlogin":
  42.     func_html( 0 );
  43.     func_userlogin();
  44. func_html( 1 );
  45. break;
  46. case "userloginaction":
  47.     func_userloginaction( $_POST['username'] , $_POST['password'] , $_POST['logintype'] );
  48. break;
  49. case "userpasswordchang":
  50.     checklogin();
  51. user_password_chang( $_POST['password'] );
  52. break;
  53. case "adminchangeuserpassword":
  54. case "useradd":
  55.     checklogin(true);
  56. func_admin_user_edit( isset($_GET['user']) ? $_GET['user'] : false );
  57. break;
  58. case "userinfoac":
  59.     checklogin(true);
  60. switch($_POST['action'])
  61. {
  62.     case "edit":
  63.     func_admin_useredit();
  64. break;
  65. case "add":
  66.     func_admin_useradd();
  67. break;
  68. }
  69. break;
  70. case "adminuserdel":
  71.     func_user_del( $_GET['user'] );
  72. break;
  73. case "logout":
  74.     func_logout();
  75. break;
  76. }
  77.  
  78.  
  79. function func_html( $position = 0 )
  80. {
  81.     switch( $position )
  82. {
  83.     case 0:
  84.     echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
  85. <html xmlns=\"http://www.w3.org/1999/xhtml\">
  86. <head>
  87. <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
  88. <title>PURE-FTPD简易管理系统</title>
  89. <style type=\"text/css\">
  90. td
  91. {
  92. padding:4px;
  93. }
  94. .bar
  95. {
  96.     width:80%;
  97. border-bottom:dotted 1px #aaa;
  98. margin-bottom:20px;
  99. padding:10px;
  100. }
  101. </style>
  102. </head>
  103. <body>
  104. <div class=\"bar\">PURE-FTPD简易管理工具 &nbsp; 孙博宇 &nbsp; http://www.sunboyu.cn &nbsp; QQ:176300676 &nbsp; MSN:sunboyu@gmail.com  &nbsp; ";
  105. if(isset($_SESSION['user']))
  106. {
  107.     echo "<input type=\"button\" name=\"logout\" id=\"logout\" value=\"退出\"  onclick=\"window.location.href='?action=logout'\" />";
  108. }
  109. echo "</div>";
  110. break;
  111. case 1:
  112.     echo "</body>
  113. </html>
  114. ";
  115. break;
  116. }
  117.     
  118. }
  119. function checklogin( $type = false )
  120. {
  121.     global $adminuser;
  122.     if(!isset($_SESSION['user']))
  123. {
  124. header("Location:".FILENAME."?action=userlogin");
  125. }
  126. if($type&&$_SESSION['user']!=$adminuser)
  127. {
  128.     header("Location:".FILENAME."?action=adminlogin");
  129. }
  130. }
  131.  
  132. function func_userlogin( )
  133. {
  134.     echo "<form name=\"loginform\" id=\"loginform\" action=\"?action=userloginaction\" method=\"post\">
  135. <table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"margin:0px;\">
  136. <tr>
  137. <td colspan=\"2\" align=\"center\">用户登录</td>
  138. </tr>
  139. <tr>
  140. <td width=\"60\" align=\"right\">用户名</td><td width=\"200\"><input type=\"text\" name=\"username\" id=\"username\" /></td>
  141. </tr>
  142. <tr>
  143. <td align=\"right\">密码</td><td><input type=\"password\" name=\"password\" id=\"password\" /></td>
  144. </tr>
  145. <tr>
  146. <td align=\"center\" colspan=\"2\"><input type=\"submit\" name=\"submit\" id=\"submit\" value=\"登录\" /><input type=\"hidden\" name=\"logintype\" id=\"logintype\" value=\"{$_GET['action']}\" /> &nbsp; ";
  147. if($_GET['action']=="userlogin")
  148. {
  149.     echo "<a href=\"?action=adminlogin\">管理员登录</a>";
  150. }
  151. else
  152. {
  153.     echo "<a href=\"?action=userlogin\">用户登录</a>";
  154. }
  155. echo "</td>
  156. </tr>
  157. <tr>
  158. <td align=\"center\" colspan=\"2\">".(isset($_GET['error']) ? $_GET['error'] : "")."</td>
  159. </tr>
  160. </table>
  161. </form>
  162. ";
  163. }
  164.  
  165. function func_getdb()
  166. {
  167.     global $hostname,$username,$password,$datebase,$charset;
  168. $handle = @mysql_connect( $hostname , $username , $password , false ) or die("Can't connetc to the DateBse.".mysql_error());
  169. @mysql_select_db( $datebase , $handle ) or die("Can't select the DateBase".mysql_error());
  170. mysql_query( "SET NAMES '{$charset}'" , $handle );
  171. return $handle;
  172. }
  173.  
  174. function func_userloginaction( $usernames , $passwords , $logintype )
  175. {
  176.     switch( $logintype )
  177. {
  178.     case "userlogin":
  179.     global $table,$username,$password,$crypt;
  180. $handle = func_getdb();
  181. #echo "SELECT COUNT(*) AS count FROM {$table} WHERE User = '{$usernames}' AND Password = ".$crypt."('".$passwords."')";
  182. $query = mysql_query("SELECT COUNT(*) AS count FROM {$table} WHERE User = '{$usernames}' AND Password = ".$crypt."('".$passwords."')" , $handle);
  183. $row = mysql_fetch_array( $query, MYSQL_ASSOC );
  184. if($row['count']==1)
  185. {
  186. $_SESSION['user'] = $usernames;
  187. echo "登录成功,跳转中……";
  188. echo "<meta http-equiv=\"Refresh\" content=\"1; url=".FILENAME."?action=index\">";
  189. }
  190. else
  191. {
  192. header("Location:".FILENAME."?action=userlogin&error=".urlencode("用户名或者密码错误!"));
  193. }
  194. break;
  195. case "adminlogin":
  196.     global $adminuser,$adminpass;
  197.     if($adminuser==$usernames&&$adminpass==$passwords)
  198. {
  199.     $_SESSION['user'] = $usernames;
  200. echo "登录成功,跳转中……";
  201. echo "</meta><meta http-equiv=\"Refresh\" content=\"1; url=".FILENAME."?action=index\">";
  202. }
  203. else
  204. {
  205.     header("Location:".FILENAME."?action=adminlogin&error=".urlencode("用户名或者密码错误!"));
  206. }
  207. break;
  208. }
  209. }
  210.  
  211. function func_user_index()
  212. {
  213.     global $table,$username,$password,$crypt;
  214. $handle = func_getdb();
  215. $query = mysql_query("SELECT * FROM {$table} WHERE User = '{$_SESSION['user']}'" , $handle);
  216. $row = mysql_fetch_array( $query, MYSQL_ASSOC );
  217.     echo "<form name=\"userpassword\" id=\"userpassword\" method=\"post\" action=\"?action=userpasswordchang\">
  218. <table cellpadding=\"0\" cellspacing=\"0\" border=\"1\">
  219.     <tr>
  220.     <td colspan=\"2\" align=\"center\">服务器信息</td>
  221. </tr>
  222.     <tr>
  223.     <td width=\"100\" align=\"right\">ip</td><td width=\"500\">".gethostbyname($_SERVER['SERVER_NAME'])."</td>
  224. </tr>
  225. <tr>
  226.     <td colspan=\"2\" align=\"center\">账户信息</td>
  227. </tr>
  228. <tr>
  229.     <td width=\"100\" align=\"right\">用户名</td><td width=\"500\">".$row['User']."</td>
  230. </tr>
  231. <tr>
  232.     <td width=\"100\" align=\"right\">修改密码</td><td width=\"500\"><input type=\"password\" name=\"password\" id=\"password\" /> &nbsp; <input type=\"submit\" name=\"submit\" id=\"submit\" value=\"修改\" /></td>
  233. </tr>
  234. <tr>
  235.     <td width=\"100\" align=\"right\">Uid</td><td width=\"500\">".$row['Uid']."</td>
  236. </tr>
  237. <tr>
  238.     <td width=\"100\" align=\"right\">Gid</td><td width=\"500\">".$row['Gid']."</td>
  239. </tr>
  240. <tr>
  241.     <td width=\"100\" align=\"right\">Status</td><td width=\"500\">".$row['status']."</td>
  242. </tr>
  243. <tr>
  244.     <td width=\"100\" align=\"right\">Dir</td><td width=\"500\">".$row['Dir']."</td>
  245. </tr>
  246. <tr>
  247.     <td width=\"100\" align=\"right\">ULBandwidth</td><td width=\"500\">".$row['ULBandwidth']."</td>
  248. </tr>
  249. <tr>
  250.     <td width=\"100\" align=\"right\">DLBandwidth</td><td width=\"500\">".$row['DLBandwidth']."</td>
  251. </tr>
  252. <tr>
  253.     <td width=\"100\" align=\"right\">ipaccess</td><td width=\"500\">".$row['ipaccess']."</td>
  254. </tr>
  255. <tr>
  256.     <td width=\"100\" align=\"right\">QuotaSize</td><td width=\"500\">".$row['QuotaSize']."</td>
  257. </tr>
  258. <tr>
  259.     <td width=\"100\" align=\"right\">QuotaFiles</td><td width=\"500\">".$row['QuotaFiles']."</td>
  260. </tr>
  261. </table>
  262. </form>
  263. ";
  264. }
  265.  
  266. function user_password_chang( $password )
  267. {
  268.     global $crypt,$table;
  269.     if(empty($password))
  270. {
  271.     echo "密码不能为空,修改失败……";
  272. echo "</meta><meta http-equiv=\"Refresh\" content=\"1; url=".FILENAME."?action=index\">";
  273. }
  274. else
  275. {
  276. $handle = func_getdb();
  277. $query = mysql_query("UPDATE {$table} SET Password = ".$crypt."('".$password."') WHERE User = '{$_SESSION['user']}'" , $handle);
  278. session_destroy();
  279. echo "修改成功,请重新登录。如果新的密码不能登录,请尝试使用旧密码进行登录……";
  280. echo "</meta><meta http-equiv=\"Refresh\" content=\"1; url=".FILENAME."?action=userlogin\">";
  281. }
  282. }
  283.  
  284. function func_admin_index()
  285. {
  286.     global $table,$username,$password,$crypt;
  287. $handle = func_getdb();
  288. $query = mysql_query("SELECT * FROM {$table} ORDER BY User ASC" , $handle);
  289. echo "<script language=\"javascript\">
  290. function del( username )
  291. {
  292.     if(confirm('确认删除 '+username+'?'))
  293. {
  294.     window.location.href=\"?action=adminuserdel&user=\"+username;
  295. }
  296. else
  297. {
  298.     return false;
  299. }
  300. }
  301. </script><table cellpadding=\"0\" cellspacing=\"0\" border=\"1\">
  302. <tr>
  303. <td colspan=\"4\" align=\"center\">用户列表</td>
  304. <td align=\"right\"><input type=\"button\" name=\"add\" id=\"add\" value=\"添加账户\" onclick=\"window.location.href='?action=useradd'\" /></td>
  305. </tr>
  306. <tr>
  307. <td align=\"center\">账号</td>
  308. <td align=\"center\">Uid</td>
  309. <td align=\"center\">Gid</td>
  310. <td align=\"center\">Dir</td>
  311. <td align=\"center\">操作</td>   
  312. </tr>";
  313. while( $row = mysql_fetch_array( $query, MYSQL_ASSOC ) )
  314. {
  315.     echo "<tr>
  316. <td>".$row['User']."</td>
  317. <td align=\"center\">".$row['Uid']."</td>
  318. <td align=\"center\">".$row['Gid']."</td>
  319. <td>".$row['Dir']."</td>
  320. <td align=\"center\"><input type=\"button\" name=\"button\" id=\"button\" value=\"修改\" onclick=\"window.location.href='?action=adminchangeuserpassword&user=".$row['User']."'\" />
  321. <input type=\"button\" name=\"del\" id=\"del\" value=\"删除\" onclick=\"del('".$row['User']."')\" /></td>   
  322. </tr>";
  323. }
  324. echo "</table>";
  325. }
  326.  
  327. function func_admin_user_edit( $user = false )
  328. {
  329.     
  330.     if($user)
  331. {
  332.     global $table,$crypt;
  333. $handle = func_getdb();
  334. $query = mysql_query("SELECT * FROM {$table} WHERE User = '".$user."'" , $handle);
  335. $row = mysql_fetch_array( $query, MYSQL_ASSOC );
  336. if($row==false)
  337. {
  338.     echo "不存在这个用户……";
  339.     echo "</meta><meta http-equiv=\"Refresh\" content=\"1; url=".FILENAME."?action=index\">";
  340. exit();
  341. }
  342. $action = "edit";
  343. }
  344. else
  345. {
  346.     $row["User"] = "";
  347. $row['Uid'] = "";
  348. $row['Gid'] = "";
  349. $row['status'] = 0;
  350. $row['Dir'] = "";
  351. $row['ULBandwidth'] = 0;
  352. $row['DLBandwidth'] = 0;
  353. $row['ipaccess'] = "*";
  354. $row['QuotaSize'] = 0;
  355. $row['QuotaFiles'] = 0;
  356. $action = "add";
  357. }
  358. echo "<form name=\"userpassword\" id=\"userpassword\" method=\"post\" action=\"?action=userinfoac\">
  359. <table cellpadding=\"0\" cellspacing=\"0\" border=\"1\">
  360. <tr>
  361.     <td colspan=\"2\" align=\"center\">账户信息</td>
  362. </tr>
  363. <tr>
  364.     <td width=\"100\" align=\"right\">用户名</td><td width=\"500\">";
  365. if($action=="add")
  366. {
  367.     echo  "<input type=\"text\" name=\"User\" id=\"User\" value=\"".$row['User']."\" />";
  368. }
  369. else
  370. {
  371.     echo  $row['User']."<input type=\"hidden\" name=\"User\" id=\"User\" value=\"".$row['User']."\" />";
  372. }
  373. echo "</td>
  374. </tr>
  375. <tr>
  376.     <td width=\"100\" align=\"right\">密码</td><td width=\"500\"><input type=\"password\" name=\"password\" id=\"password\" /> </td>
  377. </tr>
  378. <tr>
  379.     <td width=\"100\" align=\"right\">Uid</td><td width=\"500\"> <input type=\"text\" name=\"Uid\" id=\"Uid\" value=\"".$row['Uid']."\" /></td>
  380. </tr>
  381. <tr>
  382.     <td width=\"100\" align=\"right\">Gid</td><td width=\"500\"> <input type=\"text\" name=\"Gid\" id=\"Gid\" value=\"".$row['Gid']."\" /></td>
  383. </tr>
  384. <tr>
  385.     <td width=\"100\" align=\"right\">Status</td><td width=\"500\"> <input type=\"text\" name=\"status\" id=\"status\" value=\"".$row['status']."\" /></td>
  386. </tr>
  387. <tr>
  388.     <td width=\"100\" align=\"right\">Dir</td><td width=\"500\"> <input type=\"text\" name=\"Dir\" id=\"Dir\" value=\"".$row['Dir']."\" /></td>
  389. </tr>
  390. <tr>
  391.     <td width=\"100\" align=\"right\">ULBandwidth</td><td width=\"500\"> <input type=\"text\" name=\"ULBandwidth\" id=\"ULBandwidth\" value=\"".$row['ULBandwidth']."\" /></td>
  392. </tr>
  393. <tr>
  394.     <td width=\"100\" align=\"right\">DLBandwidth</td><td width=\"500\"> <input type=\"text\" name=\"DLBandwidth\" id=\"DLBandwidth\" value=\"".$row['DLBandwidth']."\" /></td>
  395. </tr>
  396. <tr>
  397.     <td width=\"100\" align=\"right\">ipaccess</td><td width=\"500\"> <input type=\"text\" name=\"ipaccess\" id=\"ipaccess\" value=\"".$row['ipaccess']."\" /></td>
  398. </tr>
  399. <tr>
  400.     <td width=\"100\" align=\"right\">QuotaSize</td><td width=\"500\"> <input type=\"text\" name=\"QuotaSize\" id=\"QuotaSize\" value=\"".$row['QuotaSize']."\" /></td>
  401. </tr>
  402. <tr>
  403.     <td width=\"100\" align=\"right\">QuotaFiles</td><td width=\"500\"> <input type=\"text\" name=\"QuotaFiles\" id=\"QuotaFiles\" value=\"".$row['QuotaFiles']."\" /></td>
  404. </tr>
  405. <tr>
  406.     <td align=\"center\" colspan=\"2\"><input type=\"submit\" name=\"submit\" id=\"submit\" value=\"提交\" /> <input type=\"button\" name=\"back\" id=\"back\" onclick=\"window.history.go(-1)\" value=\"返回\" /> <input type=\"hidden\" name=\"action\" id=\"action\" value=\"".$action."\" /></td>
  407. </tr>
  408. </table>
  409. </form>";
  410. }
  411.  
  412. function func_admin_useredit()
  413. {
  414.     global $table,$crypt;
  415. $handle = func_getdb();
  416. $query = mysql_query("SELECT * FROM {$table} WHERE User = '".$_POST['User']."'" , $handle);
  417. $row = mysql_fetch_array( $query, MYSQL_ASSOC );
  418. if($row==false)
  419. {
  420. echo "不存在这个用户……";
  421. echo "</meta><meta http-equiv=\"Refresh\" content=\"1; url=".FILENAME."?action=index\">";
  422. exit();
  423. }
  424. $query = mysql_query("UPDATE {$table} SET password = ".$crypt."('".$_POST['password']."') , Uid = {$_POST['Uid']} , Gid = {$_POST['Gid']} , status = '{$_POST['status']}' , Dir = '{$_POST['Dir']}' , ULBandwidth = {$_POST['ULBandwidth']} , DLBandwidth = {$_POST['DLBandwidth']} , ipaccess = '{$_POST['ipaccess']}' , QuotaSize = {$_POST['QuotaSize']} , QuotaFiles = {$_POST['QuotaFiles']} WHERE User = '{$_POST['User']}'");
  425. if($query)
  426. {
  427.     echo "修改成功,稍后返回……";
  428. }
  429. else
  430. {
  431.     echo "修改失败,请仔细检查每个参数……";
  432. }
  433. echo "</meta><meta http-equiv=\"Refresh\" content=\"1; url=".FILENAME."?action=index\">";
  434. exit();
  435. }
  436.  
  437. function func_admin_useradd()
  438. {
  439.     global $table,$crypt;
  440. $handle = func_getdb();
  441. $query = mysql_query("SELECT * FROM {$table} WHERE User = '".$_POST['User']."'" , $handle);
  442. $row = mysql_fetch_array( $query, MYSQL_ASSOC );
  443. if($row)
  444. {
  445. echo "用户已经存在……";
  446. echo "</meta><meta http-equiv=\"Refresh\" content=\"1; url=".FILENAME."?action=index\">";
  447. exit();
  448. }
  449. $query = mysql_query("INSERT INTO {$table} SET password = ".$crypt."('".$_POST['password']."') , Uid = {$_POST['Uid']} , Gid = {$_POST['Gid']} , status = '{$_POST['status']}' , Dir = '{$_POST['Dir']}' , ULBandwidth = {$_POST['ULBandwidth']} , DLBandwidth = {$_POST['DLBandwidth']} , ipaccess = '{$_POST['ipaccess']}' , QuotaSize = {$_POST['QuotaSize']} , QuotaFiles = {$_POST['QuotaFiles']} , User = '{$_POST['User']}' , comment = ''");
  450. if($query)
  451. {
  452.     echo "添加成功,稍后返回……";
  453. }
  454. else
  455. {
  456.     echo "添加失败,请仔细检查每个参数……";
  457. }
  458. echo "</meta><meta http-equiv=\"Refresh\" content=\"1; url=".FILENAME."?action=index\">";
  459. exit();
  460. }
  461.  
  462. function func_user_del( $user )
  463. {
  464.     global $table;
  465. $handle = func_getdb();
  466. $query = mysql_query("DELETE FROM {$table} WHERE User = '{$user}'" , $handle);
  467. if($query)
  468. {
  469.     echo "删除成功,稍后返回……";
  470. }
  471. else
  472. {
  473.     echo "删除失败,稍后返回……";
  474. }
  475. echo "</meta><meta http-equiv=\"Refresh\" content=\"1; url=".FILENAME."?action=index\">";
  476. }
  477.  
  478. function func_logout()
  479. {
  480.     session_destroy();
  481. echo "退出成功……";
  482. echo "</meta><meta http-equiv=\"Refresh\" content=\"1; url=".FILENAME."?action=userlogin\">";
  483. }
  484. ?>
  485. </meta>
]]>
http://www.sunboyu.cn/2009/07/10/php%e5%bc%80%e5%8f%91%e7%9a%84%e4%b8%80%e4%b8%aapureftpd%e7%ae%a1%e7%90%86%e5%b7%a5%e5%85%b7.shtml/feed
RSS解析类-SimplePie http://www.sunboyu.cn/2009/07/08/rss%e8%a7%a3%e6%9e%90%e7%b1%bb-simplepie.shtml http://www.sunboyu.cn/2009/07/08/rss%e8%a7%a3%e6%9e%90%e7%b1%bb-simplepie.shtml#comments Wed, 08 Jul 2009 01:31:05 +0000 admin http://www.sunboyu.cn/?p=844 最近做一个RSS解析调用的东东,研究了rss2.0的协议,发现自己去写解析程序会要命的,于是找了个开源的php rss解析类,发现完全可以满足需求,故推荐给大家。虽然有一些bug,但是可以绕过,不影响主要字段显示,先这么用着。底下写了个demo:

  1. $this->load("SimplePie","http://www.sunboyu.cn/feed");   #自己写的框架,load是加载类的方法,可根据自己的情况进行修改 new Simplepie()
  2. $this->SimplePie->strip_comments(true);
  3. $this->SimplePie->enable_xml_dump( false );
  4. $this->SimplePie->init();
  5. $this->SimplePie->handle_content_type();
  6.  
  7. foreach( $r as $item ):
  8.     echo "<font color=\"red\">标题</font>  ".$item->get_title();
  9.     echo "<br />";
  10.     echo "<font color=\"red\">链接</font>  ".$item->get_link();
  11.     echo "<br />";
  12.     echo "<font color=\"red\">链接</font>  ".$item->get_id();
  13.     echo "<br />";
  14.     echo "<font color=\"red\">更新时间</font>  ".strtotime($item->get_date());
  15.     echo "<br />";
  16.     $authors = $item->get_authors();
  17.     echo "<font color=\"red\">作者</font>  ".$authors[0]->name;
  18.     echo "<br />";
  19.     echo "<font color=\"red\">描述</font>  ".$item->get_description();
  20.     echo "<br />";
  21.     echo $item->get_local_date();
  22.     echo "<br />";
  23.     echo "<font color=\"red\">正文</font>  ".$item->get_content();
  24.     echo "<br /><br />";
  25. foreachend;
]]>
http://www.sunboyu.cn/2009/07/08/rss%e8%a7%a3%e6%9e%90%e7%b1%bb-simplepie.shtml/feed
在windows下玩apache php不能不知的几个小设置 http://www.sunboyu.cn/2009/06/10/%e5%9c%a8windows%e4%b8%8b%e7%8e%a9apache-php%e4%b8%8d%e8%83%bd%e4%b8%8d%e7%9f%a5%e7%9a%84%e5%87%a0%e4%b8%aa%e5%b0%8f%e8%ae%be%e7%bd%ae.shtml http://www.sunboyu.cn/2009/06/10/%e5%9c%a8windows%e4%b8%8b%e7%8e%a9apache-php%e4%b8%8d%e8%83%bd%e4%b8%8d%e7%9f%a5%e7%9a%84%e5%87%a0%e4%b8%aa%e5%b0%8f%e8%ae%be%e7%bd%ae.shtml#comments Wed, 10 Jun 2009 09:09:26 +0000 admin http://www.sunboyu.cn/?p=779 1、PHPIniDir “D:\PHP5″

这样不用每次都把php.ini拷贝到C:\Windows下

2、set Path=D:\PHP5;D:\PHP5\ext;%Path%

这样不用每次把那些dll拷贝到C:\Windows\system32下

]]>
http://www.sunboyu.cn/2009/06/10/%e5%9c%a8windows%e4%b8%8b%e7%8e%a9apache-php%e4%b8%8d%e8%83%bd%e4%b8%8d%e7%9f%a5%e7%9a%84%e5%87%a0%e4%b8%aa%e5%b0%8f%e8%ae%be%e7%bd%ae.shtml/feed
脱裤子放屁典范程序 http://www.sunboyu.cn/2009/06/05/%e8%84%b1%e8%a3%a4%e5%ad%90%e6%94%be%e5%b1%81%e5%85%b8%e8%8c%83%e7%a8%8b%e5%ba%8f.shtml http://www.sunboyu.cn/2009/06/05/%e8%84%b1%e8%a3%a4%e5%ad%90%e6%94%be%e5%b1%81%e5%85%b8%e8%8c%83%e7%a8%8b%e5%ba%8f.shtml#comments Fri, 05 Jun 2009 02:25:48 +0000 admin http://www.sunboyu.cn/?p=766 最近搞一个单点登录的东东,研究了下康盛的ucenterhome产品,在研究cookie的时候发现这么一段处理程序:

  1. $prelength = strlen($_SC['cookiepre']);
  2. foreach($_COOKIE as $key => $val) {
  3. if(substr($key, 0, $prelength) == $_SC['cookiepre']) {
  4. $_SCOOKIE[(substr($key, $prelength))] = empty($magic_quote) ? saddslashes($val) : $val;
  5. }
  6. }

其目的是把合法的cookie拿出来防到一个全局变量里去用。

cookie本身就是一个挺好的全局变量,而康盛又把这个变量拿出来去用,为什么?

或者,为了方便管理变量,但判断函数判断自定义全局变量跟判断cookie全局变量成本相同;

或者,为了让开发者必须彻底明白业务逻辑才能修改,提高竞争对手抄袭门槛或者提高二次开发门槛而给项目部带来更高的收入?

这样的代码里边很多,也许只有他们自己才能了解最终目的。

]]>
http://www.sunboyu.cn/2009/06/05/%e8%84%b1%e8%a3%a4%e5%ad%90%e6%94%be%e5%b1%81%e5%85%b8%e8%8c%83%e7%a8%8b%e5%ba%8f.shtml/feed
xml与array互转函数 http://www.sunboyu.cn/2009/05/31/xml%e4%b8%8earray%e4%ba%92%e8%bd%ac%e5%87%bd%e6%95%b0.shtml http://www.sunboyu.cn/2009/05/31/xml%e4%b8%8earray%e4%ba%92%e8%bd%ac%e5%87%bd%e6%95%b0.shtml#comments Sun, 31 May 2009 10:42:11 +0000 admin http://www.sunboyu.cn/?p=741 突然发现写程序不像原来思路那么清晰了,一个递归居然想了半天,不过还是凑合着写了一个简单的xml与array互转的函数,来实现跟其他系统的对接。

原来一直用的是拼凑的方式生成xml,这次使用了DOMDocument对象。不知道这个类是否有非法字符的问题,待测试一下便知。

  1. class AXML
  2. {
  3. var $dom = '';
  4. #    array to xml       ###########################################
  5.     #array to xml
  6. function array2xml( $array )
  7. {
  8. $this->dom = new DOMDocument('1.0', 'utf-8');
  9. $this->dom->formatOutput = true;
  10. $this->_array( array( 'root' => $array ) , $this->dom );
  11. echo $this->dom->saveXML();
  12. }
  13.  
  14. #array to dom
  15. function _array( $array = array() , $dom )
  16. {
  17. $i = 0;
  18. foreach( $array as $key => $value )
  19. {
  20. if( is_array( $value ) )
  21. {
  22. //遍历
  23. $node[$i] = $this->dom->createElement( $key );
  24. $dom->appendChild( $node[$i] );
  25. $this->_array( $value , $node[$i] );
  26. }
  27. else
  28. {
  29. $node[$i] = $this->dom->createElement( $key , $value );
  30. $dom->appendChild( $node[$i] );
  31. }
  32. $i++;
  33. }
  34. }
  35. #   xml  to array       ###########################################
  36. #xml to array
  37. function xml2array( $xmls )
  38. {
  39. $array = array();
  40. $this->dom = new SimpleXMLElement( $xmls );
  41. print_r( $this->_object( $this->dom ) );
  42. }
  43. #object to array
  44. function _object( $object )
  45. {
  46. $array = array();
  47. $t = get_object_vars( $object );
  48. $i = 0;
  49. foreach( $t as $key => $value )
  50. {
  51. if(is_object($value))
  52. {
  53. $array[$key] = $this->_object( $value );
  54. }
  55. else
  56. {
  57. $array[$key] = $value;
  58. }
  59. $i++;
  60. }
  61. return $array;
  62. }
  63. }
  64. $xml = new AXML();
  65. $xml->array2xml( $array );
  66. $xml->xml2array( $xml_string );
]]>
http://www.sunboyu.cn/2009/05/31/xml%e4%b8%8earray%e4%ba%92%e8%bd%ac%e5%87%bd%e6%95%b0.shtml/feed
Linux下APACHE MYSQL PHP FCgid Suexec 配置文档V1.0 http://www.sunboyu.cn/2009/05/22/linux%e4%b8%8bapache-mysql-php-fcgid-suexec-%e9%85%8d%e7%bd%ae%e6%96%87%e6%a1%a3v10.shtml http://www.sunboyu.cn/2009/05/22/linux%e4%b8%8bapache-mysql-php-fcgid-suexec-%e9%85%8d%e7%bd%ae%e6%96%87%e6%a1%a3v10.shtml#comments Fri, 22 May 2009 03:14:12 +0000 admin http://www.sunboyu.cn/?p=716 文档版本:V1.0

启动撰写时间: 2009年05月20日

目的:全面详细介绍LAMP fastcgi方式配置细节,基于之前的自动配置脚本,目的是把更多的细节转达给大家。

需要软件源码:

CentOS4.7

http://centos.ustc.edu.cn/centos/4.7/isos/i386/CentOS-4.7.ServerCD-i386.iso

http://centos.ustc.edu.cn/centos/4.7/isos/x86_64/CentOS-4.7.ServerCD-x86_64.iso

Apache-2.2.9

http://archive.apache.org/dist/httpd/httpd-2.2.9.tar.gz

MYSQL-5.2.6

http://downloads.mysql.com/archives/mysql-5.0/mysql-5.0.22.tar.gz

PHP-5.2.6

http://museum.php.net/php5/php-5.2.6.tar.gz

FCGID

http://ncu.dl.sourceforge.net/sourceforge/mod-fcgid/mod_fcgid.2.2.tgz

安装:

第一步:Linux系统安装,同时可以参照我原来的文档

http://www.sunboyu.cn/2008/06/13/centos5%E5%AE%89%E8%A3%85%E6%8C%87%E5%8D%97%EF%BC%88%E7%AE%80%E5%8D%95%E7%AF%87%EF%BC%89.shtml

视频。我按照最小化进行安装。最后ping百度不通,是因为没有重启,重启后是正常的。从过程可疑看出,我用的vmware进行安装,所以,要根据你实际的网络情况进行调整配置。

Linux Centos 4.7 安装视频(下载)(关闭)

第二步:系统更新,组件安装。

首先更新一下yum源,具体查看这篇日志 http://www.sunboyu.cn/2009/01/07/centos4%E5%88%9D%E5%A7%8B%E5%8C%96%E7%9A%84%E4%B8%80%E4%BA%9B%E8%84%9A%E6%9C%AC.shtml

升级一下系统:

yum upgrade

安装一些必要的组件:

yum install gcc gcc-c++ gcc4-c++ autoconf gd gd-devel libxml2 libxml2-devel zlib-devel glibc glibc-devel glib2 glib2-devel bzip2 bzip2-devel ncurses ncurses-devel curl curl-devel e2fsprogs e2fsprogs-devel krb5 krb5-devel libidn libidn-devel openssl openssl-devel expat expat-devel sqlite sqlite-devel png-devel jpeg-devel libtool libjpeg* libpng* freetype-devel

安装MYSQL-5.0.22

解压mysql

#tar -zxvf mysql-5.0.22.tar.gz

#cd cd mysql-5.0.22

#groupadd mysql

#useradd -g mysql mysql

#./configure –prefix=/opt/mysql-5.0.22 \
–without-debug \
–enable-thread-safe-client \
–with-client-ldflags=-all-static \
–with-mysqld-ldflags=-all-static \
–enable-local-infile \
–enable-largefile \
–with-charset=utf8 \
–with-collation=utf8_unicode_ci \
–with-extra-charsets=complex \
–with-pic \
–with-mysqld-libs \
–with-comment \
–with-query-cache \
–with-bench \
–with-big-tables \
–with-innodb \
–with-mysqld-use=mysql

#make

#make install

#cp ./support-files/my-medium.cnf /etc/my.cnf

#cp ./support-files/mysql.server /etc/init.d/mysqld

#chmod 755 /etc/init.d/mysqld

#/opt/mysql-5.0.22/bin/mysql_install_db –user=mysql &

#echo “/opt/mysql-5.0.22/bin/mysqld_safe –user=mysql &”>>/etc/rc.local

#service mysqld start

#/opt/mysql-5.0.22/bin/mysqladmin -u root password ‘123456′

#cd ..

安装APACHE

#groupadd apache

#useradd -g apache apache

#tar -zxvf httpd-2.2.9.tar.gz

#cd httpd-2.2.9

#./configure –prefix=/opt/httpd-2.2.9 \
–enable-dav \
–enable-dav-fs \
–enable-modules=all \
–enable-mods-shared=all \
–disable-auth-basic \
–enable-include \
–enable-substitute \
–enable-authz-dbm \
–enable-log-config \
–enable-headers \
–enable-setenvif \
–with-ssl \
–enable-static-ab \
–enable-http \
–enable-mime \
–enable-status \
–enable-isapi \
–enable-imagemap \
–enable-actions \
–enable-speling \
–enable-userdir \
–enable-alias \
–enable-vhost-alias \
–enable-dir \
–enable-rewrite \
–enable-dumpio \
–enable-echo \
–enable-so \
–enable-example \
–enable-case-filter \
–enable-substitute \
–enable-log-config \
–enable-logio \
–enable-env \
–with-mpm=worker \
–with-included-apr \
–with-apr \
–with-apr-util \
–with-z \
–enable-proxy \
–enable-proxy-connect \
–enable-proxy-ftp \
–enable-proxy-http \
–enable-proxy-ajp \
–enable-proxy-balancer \
–enable-suexec \
–with-suexec-caller=apache \
–with-suexec-userdir=www \
–with-suexec-docroot=/home \
–with-suexec-uidmin=100 \
–with-suexec-gidmin=100 \
–with-suexec-logfile=/var/log/suexec_log

#make

#make install

#ln -s /opt/httpd-2.2.9/bin/apachectl /etc/init.d/httpd

#cd ..

修改apache配置文件 /opt/httpd-2.2.9/conf/httpd.conf

找到

User daemon
Group daemon

修改为

User apache
Group apache

安装 fcgid

#tar -zxvf mod_fcgid.2.2.tgz

#cd mod_fcgid.2.2

修改Makefile

top_dir = /usr/local/apache2 为 top_dir = /opt/httpd-2.2.9

#make

#make install

#cd ..

修改apache配置文件 httpd.conf

增加 LoadModule fcgid_module modules/mod_fcgid.so

安装PHP,记得增加cgi支持

#tar -zxvf php-5.2.6.tar.gz

#cd php-5.2.6

#./configure –prefix=/opt/php-5.2.6 –with-libxml-dir –enable-cli –enable-cgi –enable-fastcgi –enable-bcmath –enable-force-cgi-redirect –enable-discard-path –enable-path-info-check –with-openssl –with-pcre-regex –enable-calendar –enable-dom –enable-ftp –with-openssl-dir=/usr/local/ssl –enable-gd-jis-conv –enable-hash –with-iconv –enable-json –enable-mbstring –enable-mbregex –enable-pdo –enable-posix –enable-libxml –enable-simplexml –with-sqlite –enable-tokenizer –enable-xmlreader –enable-xmlwriter –enable-sockets –with-zlib –with-freetype-dir –with-gd –with-jpeg-dir=/usr/lib –with-png-dir=/usr/lib –with-mime-magic –with-mysql=/opt/mysql-5.0.22 –with-zlib-dir=/usr/lib/libz.so –with-pdo-mysql=/opt/mysql-5.0.22 –with-pdo-sqlite –enable-posix –enable-soap

#make

#make install

修改apache配置文件httpd.conf

找到

# Virtual hosts
#Include conf/extra/httpd-vhosts.conf

修改为

# Virtual hosts
Include conf/extra/httpd-vhosts.conf

修改apache配置文件 conf/extra/httpd-vhosts.conf

删除所有的虚拟主机

现在配置虚拟主机:

所有虚拟主机的组为 vhost

增加一个用户名为sunboyu的虚拟主机

#groupadd vhost

#useradd -g vhost sunboyu

用户主目录默认为 /home/sunboyu

增加两个目录

#mkdir /home/sunboyu/www

#mkdir /home/sunboyu/logs

增加虚拟主机配置文件

SuexecUserGroup sunboyu vhost
ServerAdmin sunboyu@gmail.com
DocumentRoot “/home/sunboyu/www”
ServerName 192.168.0.4
ServerAlias sunboyu.cn
ErrorLog “/home/sunboyu/logs/error_log”
CustomLog “|/opt/httpd-2.2.9/bin/rotatelogs /home/sunboyu/logs/%Y_%m_%d_log 86400 +480″ common

AddHandler fcgid-script .php
#AddHandler cgi-script .pl .cgi
FCGIWrapper /home/sunboyu/php-cgi .php
Options ExecCGI FollowSymLinks
AllowOverride all
Order deny,allow
Allow from all

创建文件 /home/sunboyu/php-cgi 文件内容为

#!/bin/sh
export PHPRC=/home/sunboyu
export PHP_FCGI_CHILDREN=4
export PHP_FCGI_MAX_REQUESTS=5000
exec /opt/php-5.2.6/bin/php-cgi “$@”

#chmod 755 -R /home/sunboyu

#chown sunboyu:vhost -R /home/sunboyu

配置到现在,重启apache

#service httpd restart

在虚拟目录根下 /home/sunboyu/www 下写文件 info.php 内容为 phpinfo() 修改权限为755 用户组为 sunboyu:vhost

现在访问应该是phpinfo的信息。

在写这篇文档的时候,基本是按照数续依次安装。

如果有问题,希望帮忙,请提前修改你服务器root密码,我们可以一起调试。

]]>
http://www.sunboyu.cn/2009/05/22/linux%e4%b8%8bapache-mysql-php-fcgid-suexec-%e9%85%8d%e7%bd%ae%e6%96%87%e6%a1%a3v10.shtml/feed
Smarty分页类修正版 http://www.sunboyu.cn/2009/05/08/smarty%e5%88%86%e9%a1%b5%e7%b1%bb%e4%bf%ae%e6%ad%a3%e7%89%88.shtml http://www.sunboyu.cn/2009/05/08/smarty%e5%88%86%e9%a1%b5%e7%b1%bb%e4%bf%ae%e6%ad%a3%e7%89%88.shtml#comments Thu, 07 May 2009 19:59:49 +0000 admin http://www.sunboyu.cn/?p=691 原来写的分页类有问题,经过排查,发现一个变量用错了,修改之

效果,很简单,黑白配,有心的人可以自己修改一下风格,欢迎共享

e69caae591bde5908d-1

PHP部分

  1. < ?php
  2. /*  Page.Class.php
  3.  *  Page
  4.  *  @link        http://www.sunboyu.cn
  5.  *  @package     OA
  6.  *  @version     V1.0
  7.  *
  8.  *  2009 05 07  sunboyu@gmail.com
  9.  *  Demo
  10. $page = new Page( 1 , 'v_user' , '*' , '' );
  11. $rs = $page->__getlist();
  12. $smarty->assign("page",$page->__getpagelist());
  13.  */
  14.  class Page
  15.  {
  16. public $count;      #结果总数
  17. public $page;       #当前页
  18. public $pagesize;   #每页结果数
  19. public $pagecount;  #翻页数
  20. public $baseurl;    #url
  21. public $result;     #结果数组集
  22. public $pagelist;   #每翻页数
  23. public $db;         #数据库连接
  24. public $table;      #要查询的表
  25. public $fileds;     #要返回的字段
  26. public $where;      #where条件
  27.  
  28. #构造函数,初始化变量
  29. function __construct( $page , $table , $fields = '*' , $where = false , $baseurl = false )
  30. {
  31.      global $_CFG,$db;
  32. $this->db        = $db;
  33. $this->table     = $table;
  34. $this->page      = isset($page) ? intval($page) : 1;
  35. $this->fileds    = $fields;
  36. $this->pagesize  = $_CFG['pagesize'];
  37. $this->baseurl   = ($baseurl!=false) ? $baseurl : $this->__geturl();
  38. $this->pagelist  = $_CFG['pagelist'];
  39. $this->where     = $where;
  40. }
  41.  
  42. #获得当前url
  43. function __geturl()
  44. {
  45. parse_str($_SERVER['QUERY_STRING'],$str);
  46. if(isset($str['page']))
  47. {
  48. unset($str['page']);
  49. }
  50. return count($str) > 0 ? "?".http_build_query($str) : "?";
  51. }
  52.  
  53. #获得记录集
  54. function __getlist()
  55. {
  56.      #获得count记录
  57. $sql = sprintf("SELECT COUNT(*) AS table_count FROM %s %s",$this->table,(($this->where!=false) ? " WHERE ".$this->where : ''));
  58. $rs = $this->db->fetch( $sql );
  59. $this->count = $rs['table_count'];
  60.      $offset = ($this->page-1)*$this->pagesize-1;
  61.      $sql = sprintf("SELECT %s FROM %s %s LIMIT %d,%d",$this->fileds,$this->table,(($this->where!=false) ? " WHERE ".$this->where : ''),$this->pagesize*($this->page-1),$this->pagesize);
  62. #echo $sql;
  63.          $list = $this->db->fetchAll( $sql );
  64. return $list;
  65. }
  66.  
  67. #获得分页列表
  68. function __getpagelist()
  69. {
  70. $this->result['count'] = $this->count;
  71. $this->result['page'] = $this->page;
  72. $this->result['pagesize'] = $this->pagesize;
  73. $this->result['pagecount'] = ceil($this->count/$this->pagesize);
  74. if($this->result['pagecount']< =1) //只有一页以下
  75. {
  76. $this->result['pagelist'] = 0;
  77. }
  78. else //一页以上
  79. {
  80. #前一页,第一页的算法
  81. $this->result['first'] = ($this->page == 1) ? 0 : 1;
  82. $this->result['pre'] = ($this->page == 1) ? 0 : 1;
  83. #后一页,最后一页的算法
  84. $this->result['next'] = ($this->page == $this->result['pagecount'] ) ? 0 : 1;
  85. $this->result['last'] = ($this->page == $this->result['pagecount'] ) ? 0 : 1;
  86.  
  87. #起始
  88. $pagearray = array();
  89. $start = floor(($this->page-1)/10)*10+1;
  90. for($i=0;$i&lt;10;$i++)
  91. {
  92.      if( ($start+$i) < = $this->result['pagecount'])
  93. {
  94.      $pagearray[$i]['page'] = $start+$i;
  95. }
  96. if( ($start+$i) != $this->page )
  97. {
  98.      $pagearray[$i]['link'] = 1;
  99. }
  100. }
  101. #分页导航列表
  102. $this->result['pagelist'] = $pagearray;
  103. $this->result['baseurl'] = $this->baseurl;
  104. }
  105. return $this->result;
  106. }
  107. }
  108. ?>

模板部分

  1. <div id="page">
  2. <table>
  3.     <tr>
  4.     <td>
  5. 共{{$page.count}}条数据 每页{{$page.pagesize}}条  共{{$page.pagecount}}页 当前第{{$page.page}}页
  6. </td>
  7. <td>
  8. {{if $page.pagecount>1}}
  9. {{if $page.first eq 1}}
  10. <a href="{{$page.baseurl}}">首页</a>
  11. {{else}}
  12. 首页
  13. {{/if}}
  14. {{if $page.pre eq 1}}
  15. <a href="{{$page.baseurl}}&page={{$page.page-1}}">上一页</a>
  16. {{else}}
  17. 上一页
  18. {{/if}}
  19. {{foreach from=$page.pagelist item=vols}}
  20.     {{if ($vols.page > 0 ) && ($vols.page < = $page.pagecount) }}
  21. {{if $vols.link eq 1}}
  22. <a href="{{$page.baseurl}}&page={{$vols.page}}">[{{$vols.page}}]
  23. {{else}}
  24. [{{$vols.page}}]
  25. {{/if}}
  26. {{/if}}
  27. {{/foreach}}
  28. {{if $page.next eq 1}}
  29. <a href="{{$page.baseurl|default:"?"}}&page={{$page.page+1}}">下一页</a>
  30. {{else}}
  31. 下一页
  32. {{/if}}
  33. {{if $page.last eq 1}}
  34. <a href="{{$page.baseurl|default:"?"}}&page={{$page.pagecount}}">尾页</a>
  35. {{else}}
  36. 尾页
  37. {{/if}}
  38. {{/if}}
  39. </td>
  40. </tr>
  41. </table>
  42. </div>

补充一个demo

  1. #PHP部分
  2. $page = new Page( $page , $this->area_table , $fields = '*' , $where);
  3. $result['rs'] = $page->__getlist();
  4. $result['page'] = $page->__getpagelist();
  5. $smarty->assign("list",$result['rs']);
  6. $smarty->assign("page",$result['page']);
  7. $smarty->display('list.tpl');
  8. #模板里边只要引用这个分页模板即可
  9. {{include file=$smarty.const.Tpl|cat:"/Page.tpl"}}
]]>
http://www.sunboyu.cn/2009/05/08/smarty%e5%88%86%e9%a1%b5%e7%b1%bb%e4%bf%ae%e6%ad%a3%e7%89%88.shtml/feed
我的框架依然有人记得 http://www.sunboyu.cn/2009/05/05/%e6%88%91%e7%9a%84%e6%a1%86%e6%9e%b6%e4%be%9d%e7%84%b6%e6%9c%89%e4%ba%ba%e8%ae%b0%e5%be%97.shtml http://www.sunboyu.cn/2009/05/05/%e6%88%91%e7%9a%84%e6%a1%86%e6%9e%b6%e4%be%9d%e7%84%b6%e6%9c%89%e4%ba%ba%e8%ae%b0%e5%be%97.shtml#comments Tue, 05 May 2009 11:59:09 +0000 admin http://www.sunboyu.cn/?p=687 去年尝试开发了一个框架,开发了一半。或者说第一阶段开发完成。

为了开发这个框架,阅读了大量框架代码,框架思想,然后精心去调试了自己的框架。

在框架完成后,我并没有去使用。

框架的初衷是为了性能跟开发规范,而我在这个框架下兼职无法写代码,无法发挥。自从学写PHP,我从来没受什么规矩约束过,向来是自由度很高。而规则则是多年编程留下的一些经验。后来发现我的风格实在无法用框架来约束,所以放弃使用这个框架,依然按照自己的风格进行开发。

但反思,为什么有很多的框架在项目中应用-那就是规范。不成规矩,不成方圆。尤其在团队合作开发过程中,团队利益就高于个体利益。如果每个人能损失一点个人利益,那团队就可能拥有至高的利益。

因此,我又尝试开发了一套闭源自用的框架。其既集成了框架的一些模块化,规范化的理念,又适合程序员在小范围内自由发挥。后来我又加上了一些管理功能,通用模块系统,现在我可以在这个上边快速开发,又可以很轻松得把模块拆离重组。

内心我并没有把他当作框架,叫做程序“模子”会更好,感谢lamp群友给这么个名字。

]]>
http://www.sunboyu.cn/2009/05/05/%e6%88%91%e7%9a%84%e6%a1%86%e6%9e%b6%e4%be%9d%e7%84%b6%e6%9c%89%e4%ba%ba%e8%ae%b0%e5%be%97.shtml/feed
PHP DeZend真的很爽 http://www.sunboyu.cn/2009/05/02/php-dezend%e7%9c%9f%e7%9a%84%e5%be%88%e7%88%bd.shtml http://www.sunboyu.cn/2009/05/02/php-dezend%e7%9c%9f%e7%9a%84%e5%be%88%e7%88%bd.shtml#comments Fri, 01 May 2009 16:19:03 +0000 admin http://www.sunboyu.cn/?p=681 突然在网上发现一套我渴望已久的IDC管理软件,下载下来,除用vb之类的加密外,其源代码是用zend加密过的PHP代码。大喜,网上找到这个工具,然后迅速反接后,看到所有源代码。开始研究。

PHP DeZend

]]>
http://www.sunboyu.cn/2009/05/02/php-dezend%e7%9c%9f%e7%9a%84%e5%be%88%e7%88%bd.shtml/feed
几个画蛇添足的函数,出自我手 http://www.sunboyu.cn/2009/03/18/%e5%87%a0%e4%b8%aa%e7%94%bb%e8%9b%87%e6%b7%bb%e8%b6%b3%e7%9a%84%e5%87%bd%e6%95%b0%ef%bc%8c%e5%87%ba%e8%87%aa%e6%88%91%e6%89%8b.shtml http://www.sunboyu.cn/2009/03/18/%e5%87%a0%e4%b8%aa%e7%94%bb%e8%9b%87%e6%b7%bb%e8%b6%b3%e7%9a%84%e5%87%bd%e6%95%b0%ef%bc%8c%e5%87%ba%e8%87%aa%e6%88%91%e6%89%8b.shtml#comments Tue, 17 Mar 2009 17:20:14 +0000 admin http://www.sunboyu.cn/?p=608 翻看自己以前的代码,发现自己的一些搞笑的函数,列一个

  1. function func_arrtoQuerystring($array)             #其实就是http_build_query
  2. {
  3.     $string = '?';
  4.     foreach($array as $key=>$value)
  5. {
  6.     $string .= $key.",".$value.";";
  7. }
  8. $string = substr($string,0,substr($string)-1);
  9. $string .= ".html";
  10. return $string;
  11. }

回头多找几个这样的,自勉

]]>
http://www.sunboyu.cn/2009/03/18/%e5%87%a0%e4%b8%aa%e7%94%bb%e8%9b%87%e6%b7%bb%e8%b6%b3%e7%9a%84%e5%87%bd%e6%95%b0%ef%bc%8c%e5%87%ba%e8%87%aa%e6%88%91%e6%89%8b.shtml/feed
file_get_contents函数使用post方法 http://www.sunboyu.cn/2009/03/16/file_get_contents%e5%87%bd%e6%95%b0%e4%bd%bf%e7%94%a8post%e6%96%b9%e6%b3%95.shtml http://www.sunboyu.cn/2009/03/16/file_get_contents%e5%87%bd%e6%95%b0%e4%bd%bf%e7%94%a8post%e6%96%b9%e6%b3%95.shtml#comments Mon, 16 Mar 2009 04:27:44 +0000 admin http://www.sunboyu.cn/?p=602 以前总用socket的方式发送接收http的包,结果收到的包也有一堆http的协议头信息。
处理这些信息还挺费劲的。

然后想到了file_get_contents($url)方法,可以得到纯净的http包的正文。但这种方式默认是get的方式,后查手册和搜索,得到了post的方法。

这种方式基本跟socket的方式相同,包头构建好即可。

  1. $array = array ('a' => 'b','c'=>'d');
  2. $url= http_build_query($array );
  3. $postdate = array (
  4.     'http' => array (
  5.         'method' => 'POST',
  6.         'header'=> "Content-type: application/x-www-form-urlencoded\r\n" .
  7.                    "Content-Length: " . strlen($url) . "\r\n",
  8.         'content' => $url
  9.     ),
  10. );
  11. $postcontent = stream_context_create($postdate );
  12. $return= file_get_contents('http://www.sunboyu.cn', false, $postcontent ); 
  13. echo $return;
]]>
http://www.sunboyu.cn/2009/03/16/file_get_contents%e5%87%bd%e6%95%b0%e4%bd%bf%e7%94%a8post%e6%96%b9%e6%b3%95.shtml/feed
解决了该死的权限问题,是否真的有效 http://www.sunboyu.cn/2009/03/12/%e8%a7%a3%e5%86%b3%e4%ba%86%e8%af%a5%e6%ad%bb%e7%9a%84%e6%9d%83%e9%99%90%e9%97%ae%e9%a2%98%ef%bc%8c%e6%98%af%e5%90%a6%e7%9c%9f%e7%9a%84%e6%9c%89%e6%95%88.shtml http://www.sunboyu.cn/2009/03/12/%e8%a7%a3%e5%86%b3%e4%ba%86%e8%af%a5%e6%ad%bb%e7%9a%84%e6%9d%83%e9%99%90%e9%97%ae%e9%a2%98%ef%bc%8c%e6%98%af%e5%90%a6%e7%9c%9f%e7%9a%84%e6%9c%89%e6%95%88.shtml#comments Thu, 12 Mar 2009 15:43:34 +0000 admin http://www.sunboyu.cn/?p=600 我的apache+php权限是配置的最为严格的,当然,在用的时候难免伴随着混乱的账户情况,linux的权限机制也是很让人头疼的,终于,还是在风平浪静种碰到了麻烦。

我不认为PHP很强,因为它只是一个面向Web的脚本语言,而PHP的开发者却赋予了它太多,让人去用,有人也滥用。

当然,一门语言能解决N多问题是好的,比如汇编,C,但终究PHP有它跨不过的坎。毕竟它只是web脚本语言。

权限出现很大的问题,至今没有搞透,说白了对linux还是一知半解,使用python写了个第三方的东西,很完美得跳跃了权限的问题。至于效率,python肯定要比php强的,起码PHP作为服务器端程序运行,PHP还没有线程和进程的控制(一直没有发现),python有完善的线程进程的库。在权限管理上,python没细看,PHP在linux下有posix函数库,我一直也没有用过。

在没有更好的解决方案前,我依然用PHP做服务器端程序,python作为一些补充。也许,全部切换过去。

]]>
http://www.sunboyu.cn/2009/03/12/%e8%a7%a3%e5%86%b3%e4%ba%86%e8%af%a5%e6%ad%bb%e7%9a%84%e6%9d%83%e9%99%90%e9%97%ae%e9%a2%98%ef%bc%8c%e6%98%af%e5%90%a6%e7%9c%9f%e7%9a%84%e6%9c%89%e6%95%88.shtml/feed
SQLite牛刀小试 http://www.sunboyu.cn/2009/03/07/sqlite%e7%89%9b%e5%88%80%e5%b0%8f%e8%af%95.shtml http://www.sunboyu.cn/2009/03/07/sqlite%e7%89%9b%e5%88%80%e5%b0%8f%e8%af%95.shtml#comments Fri, 06 Mar 2009 18:07:28 +0000 admin http://www.sunboyu.cn/?p=594 这玩意据说跟bdb一样,嵌入式数据库,正好嵌到了PHP上边,因为写框架,框架里新添加了一个功能,就是管理模块的一个模块,本想用mysql来做,又一想,用mysql,那迁移起来可麻烦了,不运行一个install就没法部署了,不如把功能直接镶嵌,直接使用。
SQLite跟mysql一样,是关系型数据库,而且功能都类似,我直接使用原来的接口,写了一个数据抽象层,直接挂接到原框架里,很好用。
SQLite管理,我还找了两个工具,一个桌面版的,类似mysql front ,一个web版的,看来就像phpmyadmin了。

413 Request Entity Too Large

——————————————————————————–

nginx/0.5.34

FUCK Nginx HOST

那个sqlitemanager http://www.sqlitemanager.org/

代码如下,因为使用不多,临时用一下,所以细节没怎么处理,待出问题的时候再来修改。

  1. < ?php
  2. /*  DB.SQLite.Class.php
  3.  *  SQLite
  4.  *  @link        http://www.sunboyu.cn
  5.  *  @package     OA
  6.  *  @version     V1.0
  7.  *
  8.  *  2009 03 07  sunboyu@gmail.com
  9.  *  Demo
  10.  */
  11. require_once(ROOT."/Include/Class/DB.InterFace.php");
  12. class SQLite implements DateBaseConnect
  13. {
  14. #连接标识
  15. public $handle = false;
  16. #结果标识
  17. public $query;
  18. #查询次数
  19. public $exetime;
  20. #数据库连接
  21.     public function Connect( $argvs )
  22. {
  23. $this->handle = @sqlite_open( $argvs['hostname'].'/'.$argvs['datebase'] , $argvs['mode'] , $sqliteerror );
  24. if(!$this->handle)
  25. {
  26. die("Can't connect to the datebase ".$argvs['datebase']);
  27. }
  28. $this->exetime = 0;
  29. }
  30. #使用数据库
  31. public function selectDateBase( $datebase )
  32. {
  33. #此方法无用
  34. return true;
  35. }
  36. #执行一个查询
  37. public function query( $sql )
  38. {
  39.         #echo $sql;
  40. $this->query = sqlite_query( $sql , $this->handle ) or die("query error".sqlite_last_error( $this->handle ));
  41. $this->exetime++;
  42. return true;
  43. }
  44. #取得一行
  45. public function fetch( $sql )
  46. {
  47. $this->query( $sql );
  48. while( $row = mysql_fetch_array( $this->query, MYSQL_ASSOC ) )
  49. {
  50. return $row;
  51.     }
  52. return false;
  53. }
  54. #取得所有
  55. public function fetchAll( $sql )
  56. {
  57. $this->query( $sql );
  58. return sqlite_fetch_all( $this->query );
  59. }
  60. #取得影响行数
  61. public function affectedRow()
  62. {
  63. return true;
  64. }
  65. #取得结果行数
  66. public function recordCount()
  67. {
  68. return sqlite_num_rows( $this->query );
  69. }
  70. #取得上次插入ID
  71. public function insertID()
  72. {
  73. return false;
  74. }
  75. #释放资源
  76. public function close()
  77. {
  78. unset( $this->handle );
  79. }
  80. #析构函数
  81. /*
  82. function __destruct()
  83. {
  84. $this->close();
  85. }
  86. */
  87. }
  88. ?>
]]>
http://www.sunboyu.cn/2009/03/07/sqlite%e7%89%9b%e5%88%80%e5%b0%8f%e8%af%95.shtml/feed
给代码打上版本号 http://www.sunboyu.cn/2009/03/03/%e7%bb%99%e4%bb%a3%e7%a0%81%e6%89%93%e4%b8%8a%e7%89%88%e6%9c%ac%e5%8f%b7.shtml http://www.sunboyu.cn/2009/03/03/%e7%bb%99%e4%bb%a3%e7%a0%81%e6%89%93%e4%b8%8a%e7%89%88%e6%9c%ac%e5%8f%b7.shtml#comments Tue, 03 Mar 2009 15:55:20 +0000 admin http://www.sunboyu.cn/?p=591 这个版本号,当然不是svn的版本号。

写程序再多,很多情况还是考虑不清楚。有时候代码耦合度并不能合理权衡,一旦升级某项功能,大改一下也是难免。但大换血式的更改代码是很忌讳的,尤其是运行很稳定的程序。

迫不得已,流程要修改,而且可能是截断了某个流程,创建分支,这时候,如果有一个版本的控制,那只需要更新特定的版本文件,即可实现无缝升级。当然,如果不稳定,可以迅速实现代码版本的回滚。

不过这种情况要求程序模块松散耦合,当你有紧耦合代码需要调整的时候,可以享受版本切换带来的享受。

]]>
http://www.sunboyu.cn/2009/03/03/%e7%bb%99%e4%bb%a3%e7%a0%81%e6%89%93%e4%b8%8a%e7%89%88%e6%9c%ac%e5%8f%b7.shtml/feed
重写框架 http://www.sunboyu.cn/2009/03/01/%e9%87%8d%e5%86%99%e6%a1%86%e6%9e%b6.shtml http://www.sunboyu.cn/2009/03/01/%e9%87%8d%e5%86%99%e6%a1%86%e6%9e%b6.shtml#comments Sun, 01 Mar 2009 04:06:52 +0000 admin http://www.sunboyu.cn/?p=585 其实我有两个框架,一个是比较简单的框架,适用于多人生产,只是拿出了框架的一些基本特性,便于由程序员自由发挥,又不缺乏一个基本的规则。

另一个是cakephp的“高仿版”,虽然是一个完整的框架,但学习成本高,另外扼杀了程序员的天性,所以,不再更新。

这次更新的是第一个框架,因为投入了生产,暴露了很多问题,这次的目标,首先是一个完善的框架系统,另外继承很多的应用实例。

另外一些LAMP应用脚本也会适当集成,当然得是拥有root的人才能使用这些功能。

主框架依然是PHP类库,路由,JS库(考虑是否集成JQUERY)

]]>
http://www.sunboyu.cn/2009/03/01/%e9%87%8d%e5%86%99%e6%a1%86%e6%9e%b6.shtml/feed
发现问题,PHP中时间的一些细节 http://www.sunboyu.cn/2009/02/01/%e5%8f%91%e7%8e%b0%e9%97%ae%e9%a2%98%ef%bc%8cphp%e4%b8%ad%e6%97%b6%e9%97%b4%e7%9a%84%e4%b8%80%e4%ba%9b%e7%bb%86%e8%8a%82.shtml http://www.sunboyu.cn/2009/02/01/%e5%8f%91%e7%8e%b0%e9%97%ae%e9%a2%98%ef%bc%8cphp%e4%b8%ad%e6%97%b6%e9%97%b4%e7%9a%84%e4%b8%80%e4%ba%9b%e7%bb%86%e8%8a%82.shtml#comments Sun, 01 Feb 2009 13:53:18 +0000 admin http://www.sunboyu.cn/?p=548 php中,时间戳和date取得的时间是不同的。

时间戳是时间段,不受时区影响,无论哪个时区,取得都是格林威治的时间段。

date,是取得的系统时间,也就是加了时区的。

为了保持一致,php的头文件应该首先声明时区。

犯个错误,还得导数据库……

]]>
http://www.sunboyu.cn/2009/02/01/%e5%8f%91%e7%8e%b0%e9%97%ae%e9%a2%98%ef%bc%8cphp%e4%b8%ad%e6%97%b6%e9%97%b4%e7%9a%84%e4%b8%80%e4%ba%9b%e7%bb%86%e8%8a%82.shtml/feed
服务器性能负载记录工具 http://www.sunboyu.cn/2009/01/14/%e6%9c%8d%e5%8a%a1%e5%99%a8%e6%80%a7%e8%83%bd%e8%b4%9f%e8%bd%bd%e8%ae%b0%e5%bd%95%e5%b7%a5%e5%85%b7.shtml http://www.sunboyu.cn/2009/01/14/%e6%9c%8d%e5%8a%a1%e5%99%a8%e6%80%a7%e8%83%bd%e8%b4%9f%e8%bd%bd%e8%ae%b0%e5%bd%95%e5%b7%a5%e5%85%b7.shtml#comments Wed, 14 Jan 2009 09:15:38 +0000 admin http://www.sunboyu.cn/?p=486 服务器突然发生了崩溃,老板开始找我了。

找了半天居然没找到问题在哪里,一咬牙,写了个性能和负载的记录工具,再出事我可有记录了-,-||

备注:只能在linux下用。

  1. < ?php
  2. date_default_timezone_set('Asia/Shanghai');
  3. define('SLEEPTIME',10);       //10秒记录一次
  4. $memfile  = "/proc/meminfo";
  5. $loadfile = "/proc/loadavg";
  6. $logfile  = sprintf("/var/www/html/log/%s.log",date('Y-m-d'));
  7. while(1)
  8. {
  9. $log = getload();
  10. $log .= getmem();
  11. $log .= mymem();
  12. $log .= "\n\r".date("Y-m-d H:i:s");
  13. $log .= "\n\r\n\r";
  14. $handle = fopen($logfile,'a');
  15. fwrite($handle,$log);
  16. fclose($handle);
  17. sleep(SLEEPTIME);
  18. }
  19.  
  20. function getload()      //获得负载
  21. {
  22. global $loadfile;
  23. return file_get_contents($loadfile);
  24. }
  25. function getmem()      //获得内存占用
  26. {
  27. global $memfile;
  28. $mem = file($memfile);
  29. return $mem[0];
  30. }
  31. function mymem()       //程序本身内存占用
  32. {
  33. $pid = getmypid();
  34. exec("ps -eo%mem,rss,pid | grep $pid", $output);
  35.         $output = explode(" ", $output[0]);
  36.         return $output[1] * 1024;
  37. }
  38. ?>
]]>
http://www.sunboyu.cn/2009/01/14/%e6%9c%8d%e5%8a%a1%e5%99%a8%e6%80%a7%e8%83%bd%e8%b4%9f%e8%bd%bd%e8%ae%b0%e5%bd%95%e5%b7%a5%e5%85%b7.shtml/feed
PHP开发中,框架(frame)、脚手架(scaffolding)、应用资源包(application package)详解 http://www.sunboyu.cn/2009/01/11/php%e5%bc%80%e5%8f%91%e4%b8%ad%ef%bc%8c%e6%a1%86%e6%9e%b6frame%e3%80%81%e8%84%9a%e6%89%8b%e6%9e%b6scaffolding%e3%80%81%e5%ba%94%e7%94%a8%e8%b5%84%e6%ba%90%e5%8c%85application-package%e8%af%a6.shtml http://www.sunboyu.cn/2009/01/11/php%e5%bc%80%e5%8f%91%e4%b8%ad%ef%bc%8c%e6%a1%86%e6%9e%b6frame%e3%80%81%e8%84%9a%e6%89%8b%e6%9e%b6scaffolding%e3%80%81%e5%ba%94%e7%94%a8%e8%b5%84%e6%ba%90%e5%8c%85application-package%e8%af%a6.shtml#comments Sun, 11 Jan 2009 10:34:08 +0000 admin http://www.sunboyu.cn/?p=473 什么是框架:字典中框架指架构,骨架结构,框子,底座等,从字面意思,不难理解,框架指一个基础,而在程序开发中,框架指基于底层语言而逐步向上层应用进行的一些功能实现。其并没有实现具体的功能,而是简化了开发过程,任何模块中常用的功能都被框架进行封装或者扩充,给开发人员以最简的操作实现。

常用的PHP框架:Cakephp Flexphp Thinkphp

什么是脚手架:脚手架通常使用在框架的数据抽象层,数据脚手架可以很直观得给开发者或者使用者数据结构的表现。脚手架同样可以表现在一些具体应用上。但脚手架的功能只是把数据或者应用的最终结果能用简单的方式表现,但并没有达到最终的应用效果,常用在建模或结构设计的初期。脚手架的优势就是给最终用户一个直观的产品但中间并没有经过大量的开发,以减少需求变更所带来的反复开发。

常用脚手架:CI框架中数据脚手架

什么是应用资源包:应用资源包就是具体的应用了,比如bbs,blog,用户管理,资源管理等一些具体的应用。应用资源包侧重完成了一个完整的功能,而面向开发的应用资源包又提高了可迁移性,使一些项目的功能模块直接修改应用资源包的接口而达到快速开发。

常用案例:xoops中功能模块包。

]]>
http://www.sunboyu.cn/2009/01/11/php%e5%bc%80%e5%8f%91%e4%b8%ad%ef%bc%8c%e6%a1%86%e6%9e%b6frame%e3%80%81%e8%84%9a%e6%89%8b%e6%9e%b6scaffolding%e3%80%81%e5%ba%94%e7%94%a8%e8%b5%84%e6%ba%90%e5%8c%85application-package%e8%af%a6.shtml/feed
揭发一个写程序以来自己常犯的错误 http://www.sunboyu.cn/2009/01/06/%e6%8f%ad%e5%8f%91%e4%b8%80%e4%b8%aa%e5%86%99%e7%a8%8b%e5%ba%8f%e4%bb%a5%e6%9d%a5%e8%87%aa%e5%b7%b1%e5%b8%b8%e7%8a%af%e7%9a%84%e9%94%99%e8%af%af.shtml http://www.sunboyu.cn/2009/01/06/%e6%8f%ad%e5%8f%91%e4%b8%80%e4%b8%aa%e5%86%99%e7%a8%8b%e5%ba%8f%e4%bb%a5%e6%9d%a5%e8%87%aa%e5%b7%b1%e5%b8%b8%e7%8a%af%e7%9a%84%e9%94%99%e8%af%af.shtml#comments Tue, 06 Jan 2009 15:05:24 +0000 admin http://www.sunboyu.cn/?p=460 从来没发现这个错误,今天突然想到。

数据库中时间,我习惯使用时间戳来保存,取某天或者某小时的数据时,采用 sql 的 between and 方法。

  1. < ?php
  2. #某天的数据
  3. $time[0] = strtotime(date('Y-m-d'));
  4. $time[1] = $time[0]+86400;
  5. $sql = "SELECT * FROM TABLE WHERE TIME BETWEEN $time[0] AND $time[1]"  //伪代码
  6. ?>

乍看这样是没有什么问题的,取某天的时间段。实践证明,在数据时间的分布比较疏松的时候,的确没什么问题,但如果数据分布十分密集,每秒都有若干数据的时候,问题就出来了。根据between的规则,实际的时间就是 $time[1]-$time[0]+1 = 86401

每条语句多算了一秒……汗

解决方案,时间段的计算一律 $time[0] + 60*60*24*x -1

]]>
http://www.sunboyu.cn/2009/01/06/%e6%8f%ad%e5%8f%91%e4%b8%80%e4%b8%aa%e5%86%99%e7%a8%8b%e5%ba%8f%e4%bb%a5%e6%9d%a5%e8%87%aa%e5%b7%b1%e5%b8%b8%e7%8a%af%e7%9a%84%e9%94%99%e8%af%af.shtml/feed
使用linux进程来分布PHP的压力,构造高负载多并发的系统 http://www.sunboyu.cn/2008/12/25/%e4%bd%bf%e7%94%a8linux%e8%bf%9b%e7%a8%8b%e6%9d%a5%e5%88%86%e5%b8%83php%e7%9a%84%e5%8e%8b%e5%8a%9b%ef%bc%8c%e6%9e%84%e9%80%a0%e9%ab%98%e8%b4%9f%e8%bd%bd%e5%a4%9a%e5%b9%b6%e5%8f%91%e7%9a%84%e7%b3%bb.shtml http://www.sunboyu.cn/2008/12/25/%e4%bd%bf%e7%94%a8linux%e8%bf%9b%e7%a8%8b%e6%9d%a5%e5%88%86%e5%b8%83php%e7%9a%84%e5%8e%8b%e5%8a%9b%ef%bc%8c%e6%9e%84%e9%80%a0%e9%ab%98%e8%b4%9f%e8%bd%bd%e5%a4%9a%e5%b9%b6%e5%8f%91%e7%9a%84%e7%b3%bb.shtml#comments Thu, 25 Dec 2008 07:42:53 +0000 admin http://www.sunboyu.cn/?p=437 最近又跟P友讨论PHP的多进程问题,解决的方案,一般都是建立新的系统进程去处理,而linux的nohup命令可以创建新的进程,如果主程序需要处理很多数据,比如一个队列,把这些记录分布开,可以提高主程序的响应,能更快的使主程序结束。

这个方案最早出现在这哥们的博客里,大家可以参考 http://blog.s135.com/read.php/311.htm

而我处理,基本基于PHP的cli模式,使用$argv传递参数而非url,在一些涉及轮询的程序中,可以尽快得把负载分散,使单一的轮询程序来处理下一次的轮询。

]]>
http://www.sunboyu.cn/2008/12/25/%e4%bd%bf%e7%94%a8linux%e8%bf%9b%e7%a8%8b%e6%9d%a5%e5%88%86%e5%b8%83php%e7%9a%84%e5%8e%8b%e5%8a%9b%ef%bc%8c%e6%9e%84%e9%80%a0%e9%ab%98%e8%b4%9f%e8%bd%bd%e5%a4%9a%e5%b9%b6%e5%8f%91%e7%9a%84%e7%b3%bb.shtml/feed
PHP引用机制和垃圾回收机制详解 http://www.sunboyu.cn/2008/12/12/php%e5%bc%95%e7%94%a8%e6%9c%ba%e5%88%b6%e5%92%8c%e5%9e%83%e5%9c%be%e5%9b%9e%e6%94%b6%e6%9c%ba%e5%88%b6%e8%af%a6%e8%a7%a3.shtml http://www.sunboyu.cn/2008/12/12/php%e5%bc%95%e7%94%a8%e6%9c%ba%e5%88%b6%e5%92%8c%e5%9e%83%e5%9c%be%e5%9b%9e%e6%94%b6%e6%9c%ba%e5%88%b6%e8%af%a6%e8%a7%a3.shtml#comments Fri, 12 Dec 2008 14:16:09 +0000 admin http://www.sunboyu.cn/?p=426 PHP对变量的跟踪,其实是采用引用,比如 $a = “test” 那么就是在内存中开辟一个存储区,保存 test,$a 做为test的引用。

同时我们可以 $b = &$a,$b作为 $a的引用,他们同时指向test存储空间。

在文章 http://www.sunboyu.cn/2008/11/19/php%E4%B8%AD%E5%8F%98%E9%87%8F%E5%BC%95%E7%94%A8%E8%AF%A6%E8%A7%A3.shtml 中,我们做了一个应用的测试,当删除一个引用后,变量并不消失,是因为PHP使用一个引用计数的东东。当$a=”test”建立后,test的引用计数就是1,建立 $b=&$a后,test的引用计数就是2,删除任何一个引用后,引用计数为1.

只要是引用计数不为0的数据,则为当前有效的数据。然而,当数据的引用计数为0的时候,系统就会识别此数据为垃圾数据,需要回收,这也就形成了PHP的垃圾回收机制。

]]>
http://www.sunboyu.cn/2008/12/12/php%e5%bc%95%e7%94%a8%e6%9c%ba%e5%88%b6%e5%92%8c%e5%9e%83%e5%9c%be%e5%9b%9e%e6%94%b6%e6%9c%ba%e5%88%b6%e8%af%a6%e8%a7%a3.shtml/feed
山穷水复疑无路,柳暗花明又一村 http://www.sunboyu.cn/2008/12/07/%e5%b1%b1%e7%a9%b7%e6%b0%b4%e5%a4%8d%e7%96%91%e6%97%a0%e8%b7%af%ef%bc%8c%e6%9f%b3%e6%9a%97%e8%8a%b1%e6%98%8e%e5%8f%88%e4%b8%80%e6%9d%91.shtml http://www.sunboyu.cn/2008/12/07/%e5%b1%b1%e7%a9%b7%e6%b0%b4%e5%a4%8d%e7%96%91%e6%97%a0%e8%b7%af%ef%bc%8c%e6%9f%b3%e6%9a%97%e8%8a%b1%e6%98%8e%e5%8f%88%e4%b8%80%e6%9d%91.shtml#comments Sat, 06 Dec 2008 16:13:48 +0000 admin http://www.sunboyu.cn/?p=413 学习就是这样,突然发现了PHP居然有ssh2的模块,这样远程连接linux服务器就很容易,我正头疼用socket写个ssh2的连接类,突然就发现了这个玩意。手册看得还是少,罚吃巧克力一块。
官方文档:http://www.php.net/manual/en/book.ssh2.php

]]>
http://www.sunboyu.cn/2008/12/07/%e5%b1%b1%e7%a9%b7%e6%b0%b4%e5%a4%8d%e7%96%91%e6%97%a0%e8%b7%af%ef%bc%8c%e6%9f%b3%e6%9a%97%e8%8a%b1%e6%98%8e%e5%8f%88%e4%b8%80%e6%9d%91.shtml/feed
CentPHP V1.0 release http://www.sunboyu.cn/2008/12/05/centphp-v10-release.shtml http://www.sunboyu.cn/2008/12/05/centphp-v10-release.shtml#comments Fri, 05 Dec 2008 14:06:54 +0000 admin http://www.sunboyu.cn/?p=412 1.0不发布,1.1就不会出来,折腾了半月,终于写了个简单的框架,虽然只有简单的几个类,但基本实现了全OOP的操作。这个归功于网上众多的开源软件,没有这些资源的帮助,就不会有我的进步。

取名CentPHP,是因为我希望它像CentPHP一样强大稳定,而且免费开源。

最终把session的数据库保存方式给去了,因为太麻烦,模板引擎基本没什么功能,只有传值和显示,虽然进行了一些优化,但没有彻底跟踪排查资源调用情况,这个在以后版本要逐渐修正。
下边是相关文件列表,源码~~~~~~~~~等实现完一个项目后放出……

F:.
│ Index.php

├─lib
│ └─kernel
│ CentPHP.php
│ Class.Controller.php
│ Class.CP.php
│ Class.Mysql.php
│ Class.Router.php
│ Class.URI.php
│ Class.View.php
│ Common.php

├─usr
│ ├─config
│ │ Config.Mysql.php
│ │ Config.View.php
│ │
│ ├─controllers
│ │ welcome.php
│ │
│ ├─lib
│ │ Class.Session.php
│ │
│ └─views
│ welcome.php

└─var

]]>
http://www.sunboyu.cn/2008/12/05/centphp-v10-release.shtml/feed
Session处理,比较怪异的应用 http://www.sunboyu.cn/2008/12/04/session%e5%a4%84%e7%90%86%ef%bc%8c%e6%af%94%e8%be%83%e6%80%aa%e5%bc%82%e7%9a%84%e5%ba%94%e7%94%a8.shtml http://www.sunboyu.cn/2008/12/04/session%e5%a4%84%e7%90%86%ef%bc%8c%e6%af%94%e8%be%83%e6%80%aa%e5%bc%82%e7%9a%84%e5%ba%94%e7%94%a8.shtml#comments Thu, 04 Dec 2008 15:47:35 +0000 admin http://www.sunboyu.cn/?p=411 其实我很不喜欢把session放在数据库中处理,不过公司一直这么用,就先这么写,更倒霉的是,花了老大力气集成在一个不适合大项目的小框架里。
session本来是用URI类统一处理,过滤全局变量中的不安全因素,这样依赖,因为要重写session的几个方法,把原来的流程整得乱七八糟。
我正在想,是不是要把他做成一个钩子,钩挂在原来系统中,通过命令的方式开关,这样貌似是个不错的办法,不过,得把钩子的类写好……

补充:session放到数据库中的好处:可以即时得查看在新的用户(当然不是非常准确),可以踢人,如果是有登录认证的话。缺点:速度贼拉得慢,不如放到内存中。操作一次内存,得反复读写数据库,且不说硬盘,网络传输就是不消的消耗。

]]>
http://www.sunboyu.cn/2008/12/04/session%e5%a4%84%e7%90%86%ef%bc%8c%e6%af%94%e8%be%83%e6%80%aa%e5%bc%82%e7%9a%84%e5%ba%94%e7%94%a8.shtml/feed
PHP5.2.7RC版本发布 http://www.sunboyu.cn/2008/12/04/php527rc%e7%89%88%e6%9c%ac%e5%8f%91%e5%b8%83.shtml http://www.sunboyu.cn/2008/12/04/php527rc%e7%89%88%e6%9c%ac%e5%8f%91%e5%b8%83.shtml#comments Thu, 04 Dec 2008 04:01:03 +0000 admin http://www.sunboyu.cn/?p=410 官方地址 http://qa.php.net/

下载地址 http://downloads.php.net/ilia/php-5.2.7RC5.tar.gz

]]>
http://www.sunboyu.cn/2008/12/04/php527rc%e7%89%88%e6%9c%ac%e5%8f%91%e5%b8%83.shtml/feed
Windows下安装Apache,Mysql,PHP过程详解 http://www.sunboyu.cn/2008/12/04/windows%e4%b8%8b%e5%ae%89%e8%a3%85apache%ef%bc%8cmysql%ef%bc%8cphp%e8%bf%87%e7%a8%8b%e8%af%a6%e8%a7%a3.shtml http://www.sunboyu.cn/2008/12/04/windows%e4%b8%8b%e5%ae%89%e8%a3%85apache%ef%bc%8cmysql%ef%bc%8cphp%e8%bf%87%e7%a8%8b%e8%af%a6%e8%a7%a3.shtml#comments Thu, 04 Dec 2008 01:40:14 +0000 admin http://www.sunboyu.cn/?p=409 原则:使用官方程序,完全自己配置,不使用其他辅助工具套件等。

准备:

apache2.2.*   http://httpd.apache.org/download.cgi   如果有stable版本,最好用stable版,其实最新版作为调试也不错

PHP5.2.*  http://www.php.net/downloads.php  目前是5.2.6

mysql5.1  http://dev.mysql.com/downloads/mysql/5.1.html  下载windows安装版本

1、安装Apache,安装路径随意,默认即可,手工管理更好,建议放到 d:\Apache 放D盘是为了以后重装的话,所有的配置文件都还在(备份不仅要备份数据,还要备份不起眼的配置文件)

2、安装Mysql,同上,安装到 D:\Mysql  理由同上

3、解压PHP5.2.×至目录 D:\PHP5 理由还是同上

4、配置环境变量:在桌面上找到“我的电脑”,右键点击“我的电脑”,选择“属性”里的“高级”标签,点击“环境变量”,在“系统变量”里找到“Path”,点击“编辑”按钮,在“变量值”后面加上“;D:\PHP5\;D:\PHP5\ext”,然后点“确定”退出。环境变量配置完成。(windows下Path环境变量是做什么用,google一下先,这样设置后,系统会自动搜索PHP目录里的可执行文件和加载类库)

5、进入PHP5目录下,找到php.ini-dist文件,将其复制到C盘的WINDOWS目录下,并将其文件名修改为“php.ini”。(php会默认从这个路径找php.ini这个文件,当然也可以手工指定这个目录,修改apache的配置文件即可)

6、再次进入PHP5目录下,将以下文件复制到C盘的WINDOWS目录下的System32里:(原因,我也不太清楚,但貌似可以设置一个环境变量指向这个路径就ok,那个方法一直没找到,也没理解)
fdftk.dll
gds32.dll
libeay32.dll
libmcrypt.dll
libmhash.dll
libmysql.dll
msql.dll
news.txt
ntwdblib.dll

7、打开Apache的主目录,进入conf文件夹,找到“httpd.conf”文件,为操作方便起见,建议使用Dreamweaver打开它。打开后在第126行左右找到 LoadModule vhost_alias_module modules/mod_vhost_alias.so,在后面添加以下语句:
LoadModule php5_module “D:/PHP5/php5apache2_2_filter.dll
“AddType application/x-httpd-php .php
添加完成后保存文件。

8、在apache主目录下htdocs下创建index.php文件,内容为<?php phpinfo(); ?>保存。

9、在浏览器的地址栏里输入http://127.0.0.1/index.php。即可打开显示PHP信息的页面。配置成功。

]]>
http://www.sunboyu.cn/2008/12/04/windows%e4%b8%8b%e5%ae%89%e8%a3%85apache%ef%bc%8cmysql%ef%bc%8cphp%e8%bf%87%e7%a8%8b%e8%af%a6%e8%a7%a3.shtml/feed
框架资源消耗分析 http://www.sunboyu.cn/2008/12/03/%e6%a1%86%e6%9e%b6%e8%b5%84%e6%ba%90%e6%b6%88%e8%80%97%e5%88%86%e6%9e%90.shtml http://www.sunboyu.cn/2008/12/03/%e6%a1%86%e6%9e%b6%e8%b5%84%e6%ba%90%e6%b6%88%e8%80%97%e5%88%86%e6%9e%90.shtml#comments Wed, 03 Dec 2008 14:42:09 +0000 admin http://www.sunboyu.cn/?p=408 简单使用了下CI框架,发现了不少技巧:在 Controller类中实例化了好多的类

  1. function _ci_initialize()
  2. {
  3. // Assign all the class objects that were instantiated by the
  4. // front controller to local class variables so that CI can be
  5. // run as one big super object.
  6. $classes = array(
  7. 'config' => 'Config',
  8. 'input' => 'Input',
  9. 'benchmark' => 'Benchmark',
  10. 'uri' => 'URI',
  11. 'output' => 'Output',
  12. 'lang' => 'Language',
  13. 'router' => 'Router'
  14. );
  15. foreach ($classes as $var => $class)
  16. {
  17. $this->$var =& load_class($class);
  18. }
  19.  
  20. // In PHP 5 the Loader class is run as a discreet
  21. // class.  In PHP 4 it extends the Controller
  22. if (floor(phpversion()) >= 5)
  23. {
  24. $this->load =& load_class('Loader');
  25. $this->load->_ci_autoloader();
  26. }
  27. else
  28. {
  29. $this->_ci_autoloader();
  30. // sync up the objects since PHP4 was working from a copy
  31. foreach (array_keys(get_object_vars($this)) as $attribute)
  32. {
  33. if (is_object($this->$attribute))
  34. {
  35. $this->load->$attribute =& $this->$attribute;
  36. }
  37. }
  38. }

然后在默认welcome的模型里print_r($this),那是一个密密麻麻阿,无数的实例化数据摆在这里,估计内存CPU消耗也是惊人。
当然,作者并不是没有解决这些问题,所有的类在实例化之后使用static的方式常驻内存中,在第一次加载后,响应时间明显缩短,我本地测试是否默认实例化如此多的对象速度没有明显的差别。
对于原来我写程序,其实是有洁癖的,或者是心理障碍,就是像写C一样仔细考虑每个变量和每个方法,计算操作复杂度,其实对于整个系统开发和PHP这们语言来说,这么开发其实是杞人忧天,因为PHP本身就可以处理这些问题,比如static方法,一些缓存。
在进行各种测试之后,我的类库居然也默认加载了一些方法,只是应用在小网站中。
对于大型网站,还是要充分考虑效率性能的问题。

]]>
http://www.sunboyu.cn/2008/12/03/%e6%a1%86%e6%9e%b6%e8%b5%84%e6%ba%90%e6%b6%88%e8%80%97%e5%88%86%e6%9e%90.shtml/feed
框架开发的两个主方向 http://www.sunboyu.cn/2008/12/02/%e6%a1%86%e6%9e%b6%e5%bc%80%e5%8f%91%e7%9a%84%e4%b8%a4%e4%b8%aa%e4%b8%bb%e6%96%b9%e5%90%91.shtml http://www.sunboyu.cn/2008/12/02/%e6%a1%86%e6%9e%b6%e5%bc%80%e5%8f%91%e7%9a%84%e4%b8%a4%e4%b8%aa%e4%b8%bb%e6%96%b9%e5%90%91.shtml#comments Tue, 02 Dec 2008 05:50:28 +0000 admin http://www.sunboyu.cn/?p=406 最近一直在研究框架,翻阅了各大框架结构,最后总结出两点:性能和接口规范。
1、接口规范
框架的一大意义在于整合类库和资源,使用统一的接口和统一的方式进行调用,统一的接口又更加方便其他资源的整合,模块化的管理更容易对代码进行管理。这样,可以使得不同的开发人员形成一致的风格进行分工协作。
2、效率
框架在整合类库,判断路由的时候,毕竟消耗很多冗余操作。太多的类库加载也将耗费很多的内存和CPU,因此,框架开发的另一个要点就是要降低操作复杂性,降低内存消耗,在这个基础上有可优化性。

总结到这里,晚上继续玩命……

]]>
http://www.sunboyu.cn/2008/12/02/%e6%a1%86%e6%9e%b6%e5%bc%80%e5%8f%91%e7%9a%84%e4%b8%a4%e4%b8%aa%e4%b8%bb%e6%96%b9%e5%90%91.shtml/feed
框架学习之起步阶段:罗马的出发 http://www.sunboyu.cn/2008/11/27/%e6%a1%86%e6%9e%b6%e5%ad%a6%e4%b9%a0%e4%b9%8b%e8%b5%b7%e6%ad%a5%e9%98%b6%e6%ae%b5%ef%bc%9a%e7%bd%97%e9%a9%ac%e7%9a%84%e5%87%ba%e5%8f%91.shtml http://www.sunboyu.cn/2008/11/27/%e6%a1%86%e6%9e%b6%e5%ad%a6%e4%b9%a0%e4%b9%8b%e8%b5%b7%e6%ad%a5%e9%98%b6%e6%ae%b5%ef%bc%9a%e7%bd%97%e9%a9%ac%e7%9a%84%e5%87%ba%e5%8f%91.shtml#comments Thu, 27 Nov 2008 14:11:23 +0000 admin http://www.sunboyu.cn/?p=403 罗马真的不是一天建成的,不能不承认,那些框架作者在此花费的精力。我的框架只写了一个说明,两个函数,就已经尽兴不下去了,当然跟这几天的感冒有关,不过,更多的是我没有理清框架应该有的结构。

一个优秀的框架除了规范化大部分操作外,其在效率和性能损耗上做了进步一的改进,从而能够高效处理复杂的操作。

第一个自动加载类的函数,参考了下PHP手册关于引用部分,才发现自己原来写类的方法,是如何的消耗内存和CPU,任何一个方法的诞生都是有其目的的,不能认为PHP是神,但PHP毕竟比我强,因此我还是要相信这些我不熟悉的操作是有用武之地的。

第二个方法,是要定义URI路由,URI路由我会尽量使用逐一匹配的方式进行解析,但有些操作不确定变量数量的时候,简单使用正则。我正则不很强,但也对着手册也可以写,但我总感觉这玩意太费劲,大脑想着费劲,电脑做着肯定费劲。有简单的方式,为何用难的,难道只是为了省点代码空间么,没必要的。

不过说到底,正则这东西还是很有用,不能因为效率差而失去,计划写个分支,把简单的用模板匹配,复杂的用正则,皆大欢喜。

不过写之前,还是要大量翻看别人的东西。

]]>
http://www.sunboyu.cn/2008/11/27/%e6%a1%86%e6%9e%b6%e5%ad%a6%e4%b9%a0%e4%b9%8b%e8%b5%b7%e6%ad%a5%e9%98%b6%e6%ae%b5%ef%bc%9a%e7%bd%97%e9%a9%ac%e7%9a%84%e5%87%ba%e5%8f%91.shtml/feed
PHP中引用返回的用法 http://www.sunboyu.cn/2008/11/21/php%e4%b8%ad%e5%bc%95%e7%94%a8%e8%bf%94%e5%9b%9e%e7%9a%84%e7%94%a8%e6%b3%95.shtml http://www.sunboyu.cn/2008/11/21/php%e4%b8%ad%e5%bc%95%e7%94%a8%e8%bf%94%e5%9b%9e%e7%9a%84%e7%94%a8%e6%b3%95.shtml#comments Fri, 21 Nov 2008 02:49:47 +0000 admin http://www.sunboyu.cn/?p=390 先看个例子

  1. function &new_class( $classname )
  2. {
  3.         static $object = array();
  4.         if(isset( $object[$classname] ))
  5.         {
  6.                 return $object[$classname];
  7.         }
  8.         $object[$classname] = & new $classname();
  9.         return $object[$classname];
  10. }
  11. class abc
  12. {
  13. public $a;
  14. public $b;
  15. function abc()
  16. {
  17. $this->a = 1;
  18. $this->b = 2;
  19. }
  20. }
  21. class test
  22. {
  23. }
  24.  
  25. $a = new test();
  26. $a->abc = & new_class( 'abc' );
  27. print_r($a);

很显然,这样做的好处是减少了实例化对象的复制,直接绑定了对象。这样减少了内存的消耗和操作的复杂。但实际上官方又说了这么一句,很是纳闷:
Do not use return-by-reference to increase performance, the engine is smart enough to optimize this on its own.
不要尝试用引用返回提高性能,因为PHP引擎足够聪明,自己会解决。
闷中

]]>
http://www.sunboyu.cn/2008/11/21/php%e4%b8%ad%e5%bc%95%e7%94%a8%e8%bf%94%e5%9b%9e%e7%9a%84%e7%94%a8%e6%b3%95.shtml/feed
PHP中变量引用详解 http://www.sunboyu.cn/2008/11/19/php%e4%b8%ad%e5%8f%98%e9%87%8f%e5%bc%95%e7%94%a8%e8%af%a6%e8%a7%a3.shtml http://www.sunboyu.cn/2008/11/19/php%e4%b8%ad%e5%8f%98%e9%87%8f%e5%bc%95%e7%94%a8%e8%af%a6%e8%a7%a3.shtml#comments Wed, 19 Nov 2008 13:37:24 +0000 admin http://www.sunboyu.cn/?p=388 PHP中,引用就是用另一个变量是访问一个变量的值。但是跟C中指针不通。这里做几个测试,以说明:

  1. $a = "date";
  2. $b = &amp;$a;
  3. echo $a; // date
  4. echo $b; // date
  5. $b = "date1";
  6. echo $a; // date1
  7. echo $b; // date1
  8. unset($a);
  9. echo $b; // date1


可以看出,引用其实就是给一个变量增加了一个别名,而对于有别名的变量,删除这个变量只是删除了这个变量的名字,而变量的内容不变,同时,使用任何一个函数名操作一个变量,都是操作了值,值的结果可以使用任何一个别名访问。

]]>
http://www.sunboyu.cn/2008/11/19/php%e4%b8%ad%e5%8f%98%e9%87%8f%e5%bc%95%e7%94%a8%e8%af%a6%e8%a7%a3.shtml/feed
框架之争 http://www.sunboyu.cn/2008/11/13/%e6%a1%86%e6%9e%b6%e4%b9%8b%e4%ba%89.shtml http://www.sunboyu.cn/2008/11/13/%e6%a1%86%e6%9e%b6%e4%b9%8b%e4%ba%89.shtml#comments Thu, 13 Nov 2008 13:36:52 +0000 admin http://www.sunboyu.cn/?p=383 最近在看一些框架,从zendframework,cakephp,IC,都大概了解了一下,因为以前习惯全部手工代码,但后来发现这种方式过于松散,松散到不能管理,因为类,函数,虽然有自己的方式整理,但每次开展项目的时候都得重新整理,重新配置接口,过于麻烦,于是想到了框架。

框架,其实是用程序管理类库的一种方式,采用统一的接口,统一的调用风格进行操作,对于团队合作中代码可读性提供了便利。但框架也有很严重的问题,就是效率。

框架大都采用了单点的入口,然后提供url的路由功能进行解析,另外,类的调用也大都采取__autoload进行寻找,大大降低了程序的效率。

后又看了奶瓶老仙的BSMlite,深有感触。

其实,使用框架完全可以应付中小型项目,至于效率,也可以在完工后进行优化再发布,这样就会达到两全其美的效果。

]]>
http://www.sunboyu.cn/2008/11/13/%e6%a1%86%e6%9e%b6%e4%b9%8b%e4%ba%89.shtml/feed
PHP版DES加密解密 http://www.sunboyu.cn/2008/11/12/php%e7%89%88des%e5%8a%a0%e5%af%86%e8%a7%a3%e5%af%86.shtml http://www.sunboyu.cn/2008/11/12/php%e7%89%88des%e5%8a%a0%e5%af%86%e8%a7%a3%e5%af%86.shtml#comments Wed, 12 Nov 2008 05:31:27 +0000 admin http://www.sunboyu.cn/?p=382
  1. < ?php
  2. class DES
  3. {
  4. public $key = '';
  5. public $iv = '';
  6. public $td = '';
  7. public $ks = '';
  8. //构造函数
  9. public function __construct( $key )
  10. {
  11. $this->td = mcrypt_module_open('rijndael-256', '', 'ofb', '');
  12. $this->iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($this->td), (substr(PHP_OS,0,3)=='WIN' ? MCRYPT_RAND : MCRYPT_DEV_RANDOM));
  13. $this->ks = mcrypt_enc_get_key_size($this->td);
  14. $this->key = substr(md5($key), 0, $this->ks);
  15. }
  16. //加密函数
  17. function encrypt( $value )
  18.     {
  19. mcrypt_generic_init($this->td, $this->key, $this->iv);
  20. $r = mcrypt_generic( $this->td , $value );
  21. mcrypt_generic_deinit($this->td);
  22. return $r;
  23.     }
  24. //解密函数
  25. function decrypt( $value )
  26.     {
  27. mcrypt_generic_init($this->td, $this->key, $this->iv);
  28. $r = mdecrypt_generic($this->td, $value);
  29. mcrypt_generic_deinit($this->td);
  30. return $r;
  31.     }
  32. //西沟函数
  33. function __destruct()
  34. {
  35. mcrypt_module_close($this->td);
  36. }
  37. }
  38.  
  39.  
  40. $des = new DES('FDASFDAS');
  41. $content = file_get_contents('example.php');
  42. echo $content;
  43. echo "<br /><br /><br /><br /><br />";
  44. $encode = $des->encrypt( $content );
  45. echo $encode;
  46. echo "<br /><br /><br /><br /><br />";
  47. $decode = $des->decrypt($encode);
  48. echo $decode;
  49. ?>
]]>
http://www.sunboyu.cn/2008/11/12/php%e7%89%88des%e5%8a%a0%e5%af%86%e8%a7%a3%e5%af%86.shtml/feed
无级分类算法的实现与其可用性 http://www.sunboyu.cn/2008/10/14/%e6%97%a0%e7%ba%a7%e5%88%86%e7%b1%bb%e7%ae%97%e6%b3%95%e7%9a%84%e5%ae%9e%e7%8e%b0%e4%b8%8e%e5%85%b6%e5%8f%af%e7%94%a8%e6%80%a7.shtml http://www.sunboyu.cn/2008/10/14/%e6%97%a0%e7%ba%a7%e5%88%86%e7%b1%bb%e7%ae%97%e6%b3%95%e7%9a%84%e5%ae%9e%e7%8e%b0%e4%b8%8e%e5%85%b6%e5%8f%af%e7%94%a8%e6%80%a7.shtml#comments Tue, 14 Oct 2008 14:27:27 +0000 admin http://www.sunboyu.cn/?p=343 根据动易ASP CMS的算法,简单实现了无级分类的算法,不过根据系统易用性原则,这种无级的分类很难在实际的CMS系统中应用,因此,这种算法在中小型信息管理系统中是不需要的,而大型的信息管理系统也要尽量避免分类深度过高而造成的系统效率问题。总结下来,这只能算自己连手的一个作品。

]]>
http://www.sunboyu.cn/2008/10/14/%e6%97%a0%e7%ba%a7%e5%88%86%e7%b1%bb%e7%ae%97%e6%b3%95%e7%9a%84%e5%ae%9e%e7%8e%b0%e4%b8%8e%e5%85%b6%e5%8f%af%e7%94%a8%e6%80%a7.shtml/feed
PHP缓存组件APC简介 http://www.sunboyu.cn/2008/10/03/php%e7%bc%93%e5%ad%98%e7%bb%84%e4%bb%b6apc%e7%ae%80%e4%bb%8b.shtml http://www.sunboyu.cn/2008/10/03/php%e7%bc%93%e5%ad%98%e7%bb%84%e4%bb%b6apc%e7%ae%80%e4%bb%8b.shtml#comments Fri, 03 Oct 2008 02:55:15 +0000 admin http://www.sunboyu.cn/?p=332 php是解释型语言,比起编译型语言,速度自然会慢.每种语言基本都是 1、源代码->编译成二进制机器码 2、编译成二进制机器码->执行 编译型语言(如c,java)在执行一次步骤1后,多次执行步骤2,而asp,php之类的解释型语言每次访问,都重复步骤1,2,故效率低下。

PHP官方提供了一个编译php为二进制码的工具,Zend,价格昂贵,今天讨论免费的APC。

APC组件下载地址:http://pecl4win.php.net/ext.php/php_apc.dll http://pecl.php.net/package/apc 根据自己的操作系统版本来下载安装。我这里使用的是windows系统,直接把php_apc.dll放在扩展文件路径里,在php.ini里增加extension=php_apc.dll,再查看phpinfo(),可看到apc安装成功的信息。具体配置信息在这里 http://cn2.php.net/manual/en/apc.configuration.php

其中的参数可以设定是否缓存php的编译文件,还有一些常用的限制。

除此之外,还有很多opcode缓存组件,如accelerator,xcache之类,详情可参见这里 http://en.wikipedia.org/wiki/Alternative_PHP_Cache#Alternative_PHP_Cache

]]>
http://www.sunboyu.cn/2008/10/03/php%e7%bc%93%e5%ad%98%e7%bb%84%e4%bb%b6apc%e7%ae%80%e4%bb%8b.shtml/feed
Mysql数据库抽象层操作类 http://www.sunboyu.cn/2008/09/08/mysql%e6%95%b0%e6%8d%ae%e5%ba%93%e6%8a%bd%e8%b1%a1%e5%b1%82%e6%93%8d%e4%bd%9c%e7%b1%bb.shtml http://www.sunboyu.cn/2008/09/08/mysql%e6%95%b0%e6%8d%ae%e5%ba%93%e6%8a%bd%e8%b1%a1%e5%b1%82%e6%93%8d%e4%bd%9c%e7%b1%bb.shtml#comments Mon, 08 Sep 2008 06:26:23 +0000 admin http://www.sunboyu.cn/?p=308 DB.InterFace.php

  1. <?php
  2. /*  DB.InterFace.php
  3.  *  DB
  4.  *  @link        http://www.sunboyu.cn
  5.  *  @package     OA
  6.  *  @version     V1.0
  7.  *
  8.  *  2008 08 28  sunboyu@gmail.com
  9.  *  Demo
  10.  */
  11. interface DateBaseConnect
  12. {
  13.     #数据库连接
  14.     public function Connect( $host , $user , $pass , $datebase );
  15. #使用数据库
  16. public function selectDateBase( $datebase );
  17. #执行一个查询
  18. public function Query( $sql );
  19. #取得一行
  20. public function fetchRow( $sql );
  21. #取得所有
  22. public function fetchAll( $sql );
  23. #取得影响行数
  24. public function affectedRow();
  25. #取得结果行数
  26. public function recordCount();
  27. #取得上次插入ID
  28. public function insertID();
  29. #释放资源
  30. public function close();
  31. }
  32. ?>


DB.Mysql.Class.php

  1. <?php
  2. /*  DB.Mysql.Class.php
  3.  *  Mysql
  4.  *  @link        http://www.sunboyu.cn
  5.  *  @package     OA
  6.  *  @version     V1.0
  7.  *
  8.  *  2008 08 28  sunboyu@gmail.com
  9.  *  Demo
  10.  */
  11. require_once(ROOT."/Include/Class/DB.InterFace.php");
  12. class Mysql implements DateBaseConnect
  13. {
  14. #连接标识
  15. public $handle = false;
  16. #结果标识
  17. public $query;
  18. #查询次数
  19. public $exetime;
  20. #数据库连接
  21.     public function Connect( $host , $user , $pass , $datebase )
  22. {
  23. $this->handle = @mysql_connect( $host , $user , $pass , false ) or die("Can't connetc to the DateBse.".mysql_error());
  24. $this->selectDateBase( $datebase );
  25. $this->exetime = 0;
  26. }
  27. #使用数据库
  28. public function selectDateBase( $datebase )
  29. {
  30. @mysql_select_db( $datebase , $this->handle ) or die("Can't select the DateBase".mysql_error());
  31. }
  32. #执行一个查询
  33. public function Query( $sql )
  34. {
  35. $this->query = mysql_query( $sql , $this->handle ) or die("query error".mysql_error());
  36. $this->exetime++;
  37. return true;
  38. }
  39. #取得一行
  40. public function fetchRow( $sql )
  41. {
  42. $this->Query( $sql );
  43. while( $row = mysql_fetch_array( $this->query, MYSQL_ASSOC ) )
  44. {
  45. return $row;
  46.     }
  47. return false;
  48. }
  49. #取得所有
  50. public function fetchAll( $sql )
  51. {
  52. $this->Query( $sql );
  53. $rows = false;
  54. while( $rs = mysql_fetch_array( $this->query, MYSQL_ASSOC ) )
  55. {
  56. $rows[] = $rs;
  57. }
  58. return $rows;
  59. }
  60. #取得影响行数
  61. public function affectedRow()
  62. {
  63. return mysql_affected_rows( $this->query );
  64. }
  65. #取得结果行数
  66. public function recordCount()
  67. {
  68. return mysql_num_rows( $this->query );
  69. }
  70. #取得上次插入ID
  71. public function insertID()
  72. {
  73. return (mysql_insert_id()>0) ? mysql_insert_id() : false;
  74. }
  75. #释放资源
  76. public function close()
  77. {
  78. @mysql_close( $this->handle );
  79. }
  80. #析构函数
  81. /*
  82. function __destruct()
  83. {
  84. $this->close();
  85. }
  86. */
  87. }
  88. ?>

DB.Mysql.Fact.Class.php

  1. <?php
  2. /*  DB.Mysql.Fact.Class.php
  3.  *  Mysql
  4.  *  @link        http://www.sunboyu.cn
  5.  *  @package     OA
  6.  *  @version     V1.0
  7.  *
  8.  *  2008 08 28  sunboyu@gmail.com
  9.  *  Demo
  10.  */
  11. require_once(ROOT."/Include/Class/DB.Mysql.Class.php");
  12. class DB extends Mysql
  13. {
  14.     #插入操作
  15. /*
  16. $array = array(
  17.     'name' = "sunboyu",
  18. 'pass' = "123456"
  19. );
  20. */
  21. function __insert( $array , $table )
  22. {
  23.     $sql = "INSERT INTO {$table} (";
  24.     if(!is_array($array))
  25. {
  26.     die('the array is not a array!');
  27. }
  28. $keys = array_keys( $array );
  29. $sql .= implode( ',' , $keys );
  30. $sql .= ") VALUES (";
  31. foreach( $array as $key=>$value )
  32. {
  33.     if(is_int( $array[$key] ))
  34. {
  35.     $sql .= $array[$key];
  36. }
  37. else if(is_string( $array[$key] ))
  38. {
  39.     $sql .= "'{$array[$key]}'";
  40. }
  41. $sql .= ",";
  42. }
  43. $sql = substr_replace( $sql , "" , -1 );
  44. $sql .= ")";
  45. return $this->Query( $sql );
  46. }
  47. }
  48. ?>
]]>
http://www.sunboyu.cn/2008/09/08/mysql%e6%95%b0%e6%8d%ae%e5%ba%93%e6%8a%bd%e8%b1%a1%e5%b1%82%e6%93%8d%e4%bd%9c%e7%b1%bb.shtml/feed
倒霉的ADODB,折腾死了 http://www.sunboyu.cn/2008/09/05/%e5%80%92%e9%9c%89%e7%9a%84adodb%ef%bc%8c%e6%8a%98%e8%85%be%e6%ad%bb%e4%ba%86.shtml http://www.sunboyu.cn/2008/09/05/%e5%80%92%e9%9c%89%e7%9a%84adodb%ef%bc%8c%e6%8a%98%e8%85%be%e6%ad%bb%e4%ba%86.shtml#comments Fri, 05 Sep 2008 08:56:31 +0000 admin http://www.sunboyu.cn/?p=305 突然发现ADODB_lite很多方法跟以前不一样了,变了好多,所以,一气之下决定放弃adodb,自己写个数据抽象层的类。

用别人的东西总是有很多的局限,如果去修改,工作量又很大。其实我们使用的也就是那么点功能,这样我们去完成自己的类工作量并不大,而且能根据自己的需求不断改进。

]]>
http://www.sunboyu.cn/2008/09/05/%e5%80%92%e9%9c%89%e7%9a%84adodb%ef%bc%8c%e6%8a%98%e8%85%be%e6%ad%bb%e4%ba%86.shtml/feed
简单分页程序,adodb+smarty http://www.sunboyu.cn/2008/08/31/%e7%ae%80%e5%8d%95%e5%88%86%e9%a1%b5%e7%a8%8b%e5%ba%8fadodbsmarty.shtml http://www.sunboyu.cn/2008/08/31/%e7%ae%80%e5%8d%95%e5%88%86%e9%a1%b5%e7%a8%8b%e5%ba%8fadodbsmarty.shtml#comments Sun, 31 Aug 2008 09:56:16 +0000 admin http://www.sunboyu.cn/?p=292 分页类

  1. <?php
  2. /*  Page.Class.php
  3.  *  Page
  4.  *  @link        http://www.sunboyu.cn
  5.  *  @package     OA
  6.  *  @version     V1.0
  7.  *
  8.  *  2008 08 28  sunboyu@gmail.com
  9.  *  Demo
  10. $page = new Page( 1 , 'v_user' , '*' , '' );
  11. $rs = $page->__getlist();
  12. $smarty->assign("page",$page->__getpagelist());
  13.  */
  14.  class Page
  15.  {
  16. public $count;      #结果总数
  17. public $page;       #当前页
  18. public $pagesize;   #每页结果数
  19. public $pagecount;  #翻页数
  20. public $baseurl;    #url
  21. public $result;     #结果数组集
  22. public $pagelist;   #每翻页数
  23. public $db;         #数据库连接
  24. public $table;      #要查询的表
  25. public $fileds;     #要返回的字段
  26. public $where;      #where条件
  27.  
  28. #构造函数,初始化变量
  29. function __construct( $page , $table , $fields = '*' , $where = false , $baseurl = false )
  30. {
  31.      global $_CFG;
  32. $this->db        = GetDB();
  33. $this->count     = $count;
  34. $this->table     = $table;
  35. $this->page      = isset($page) ? intval($_GET['page']) : 1;
  36. $this->fileds    = $fields;
  37. $this->pagesize  = $_CFG['pagesize'];
  38. $this->baseurl   = ($baseurl!=false) ? $baseurl : $this->__geturl();
  39. $this->pagelist  = $_CFG['pagelist'];
  40. $this->where     = $where;
  41. }
  42.  
  43. #获得当前url
  44. function __geturl()
  45. {
  46. $str = ereg_replace(sprintf("(^|&)page=%d",$this->page),"",$_SERVER['QUERY_STRING']);
  47. return $str=="" ? '?' : $str;
  48. }
  49. #获得记录集
  50. function __getlist()
  51. {
  52.      #获得count记录
  53. $sql = sprintf("SELECT COUNT(0) AS table_count FROM %s",$this->table);
  54. $rs = $this->db->Execute( $sql );
  55. $this->count = $rs->fields['table_count'];
  56.      $offset = ($this->page-1)*$this->pagesize-1;
  57.      $sql = sprintf("SELECT %s FROM %s %s",$this->fileds,$this->table,(($this->where!=false) ? " WHERE ".$this->where : ''));
  58. $rs = $this->db->SelectLimit( $sql , $this->pagesize , $offset );
  59. $list = false;
  60. while(!$rs->EOF)
  61. {
  62.      $list[] = $rs->fields;
  63. $rs->MoveNext();
  64. }
  65. return $list;
  66. }
  67.  
  68. #获得分页列表
  69. function __getpagelist()
  70. {
  71. $this->result['count'] = $this->count;
  72. $this->result['page'] = $this->page;
  73. $this->result['pagesize'] = $this->pagesize;
  74. $this->result['pagecount'] = ceil($this->count/$this->pagesize);
  75. if($this->result['pagecount']<=1) //只有一页以下
  76. {
  77. $this->result['pagelist'] = 0;
  78. }
  79. else //一页以上
  80. {
  81. #前一页,第一页的算法
  82. $this->result['first'] = ($this->page == 1) ? 0 : 1;
  83. $this->result['pre'] = ($this->page == 1) ? 0 : 1;
  84. #后一页,最后一页的算法
  85. $this->result['next'] = ($this->page == $this->pagecount ) ? 0 : 1;
  86. $this->result['last'] = ($this->page == $this->pagecount ) ? 0 : 1;
  87.  
  88.  
  89. #起始
  90. $pagearray = array();
  91. $start = floor(($this->page-1)/10)*10+1;
  92. for($i=0;$i<10;$i++)
  93. {
  94.      if( ($start+$i) <= $this->result['pagecount'])
  95. {
  96.      $pagearray[$i]['page'] = $start+$i;
  97. }
  98. if( ($start+$i) != $this->page )
  99. {
  100.      $pagearray[$i]['link'] = 1;
  101. }
  102. }
  103. #分页导航列表
  104. $this->result['pagelist'] = $pagearray;
  105. $this->result['baseurl'] = $this->baseurl;
  106. }
  107. return $this->result;
  108. }
  109. }
  110. ?>

smarty模版

  1. {{config_load file="Lang.Page.$lang.conf"}}<div id="page">
  2. <table>
  3.     <tr>
  4.     <td>
  5. {{#gongs#}}{{$page.count}}{{#pagecountend#}} {{#pagepagesizeper#}}{{$page.pagesize}}{{#pagepagelistper#}}{{#tiao#}}  {{#gongs#}}{{$page.pagecount}}{{#page#}} {{#pagepage#}}{{$page.page+1}}{{#page#}}
  6. </td>
  7. <td>
  8. {{if $page.pagecount>1}}
  9. {{if $page.first eq 1}}
  10. <a href="{{$page.baseurl}}">{{#pagefirst#}}</a>
  11. {{else}}
  12. {{#pagefirst#}}
  13. {{/if}}
  14. {{if $page.pre eq 1}}
  15. <a href="{{$page.baseurl}}&page={{$page.page-1}}">{{#pagepre#}}</a>
  16. {{else}}
  17. {{#pagepre#}}
  18. {{/if}}
  19. {{foreach from=$page.pagelist item=vols}}
  20.     {{if $vols.link eq 1}}
  21. <a href="{{$page.baseurl}}&page={{$vols.page}}">[{{$vols.page}}]</a>
  22. {{else}}
  23. [{{$vols.page}}]
  24. {{/if}}
  25. {{/foreach}}
  26. {{if $page.next eq 1}}
  27. <a href="{{$page.baseurl|default:"?"}}&page={{$page.page+1}}">{{#pagenext#}}</a>
  28. {{else}}
  29. {{#pagenext#}}
  30. {{/if}}
  31. {{if $page.last eq 1}}
  32. <a href="{{$page.baseurl|default:"?"}}&page={{$page.pagecount}}">{{#pageend#}}</a>
  33. {{else}}
  34. {{#pagelast#}}
  35. {{/if}}
  36. {{/if}}
  37. </td>
  38. </tr>
  39. </table>
  40. </div>

语言包内容

  1. pagecountend      = "条数据"
  2. pagepagesizeper   = "每页"
  3. pagepagesizeend   = "条"
  4. page              = "页"
  5. tiao              = "条"
  6. pagepage          = "当前第"
  7. pagefirst         = "首页"
  8. pagepre           = "上一页"
  9. pagenext          = "下一页"
  10. pagelast          = "尾页"
  11. gongs             = "共"
]]>
http://www.sunboyu.cn/2008/08/31/%e7%ae%80%e5%8d%95%e5%88%86%e9%a1%b5%e7%a8%8b%e5%ba%8fadodbsmarty.shtml/feed
简单的PHP+SMARTY分页类 http://www.sunboyu.cn/2008/08/29/%e7%ae%80%e5%8d%95%e7%9a%84phpsmarty%e5%88%86%e9%a1%b5%e7%b1%bb.shtml http://www.sunboyu.cn/2008/08/29/%e7%ae%80%e5%8d%95%e7%9a%84phpsmarty%e5%88%86%e9%a1%b5%e7%b1%bb.shtml#comments Fri, 29 Aug 2008 15:21:47 +0000 admin http://www.sunboyu.cn/?p=291 类的代码

  1. <?php
  2. /*  Page.Class.php
  3.  *  Page
  4.  *  @link        http://www.sunboyu.cn
  5.  *  @package     OA
  6.  *  @version     V1.0
  7.  *
  8.  *  2008 08 28  sunboyu@gmail.com
  9.  */
  10.  class Page
  11.  {
  12. public $count;      #结果总数
  13. public $page;       #当前页
  14. public $pagesize;   #每页结果数
  15. public $pagecount;  #翻页数
  16. public $baseurl;    #url
  17. public $result;     #结果数组集
  18. public $pagelist;   #每翻页数
  19.  
  20. #构造函数,初始化变量
  21. function __construct( $count , $page , $pagesize , $pagelist , $baseurl = false )
  22. {
  23. $this->count     = $count;
  24. $this->page      = $page;
  25. $this->pagesize  = $pagesize;
  26. $this->baseurl   = isset($baseurl) ? $baseurl : $this->__geturl();
  27. $this->pagelist = $pagelist;
  28. }
  29.  
  30. #获得当前url
  31. function __geturl()
  32. {
  33. return ereg_replace("(^|&)page={$page}","",$_SERVER['QUERY_STRING']);
  34. }
  35.  
  36. #获得分页列表
  37. function __getpagelist()
  38. {
  39. $this->result['count'] = $this->count;
  40. $this->result['page'] = $this->page;
  41. $this->result['pagesize'] = $this->pagesize;
  42. $this->result['pagecount'] = ceil($this->count/$this->pagesize);
  43. if($this->result['pagecount']<=1) //只有一页以下
  44. {
  45. $this->result['pagelist'] = 0;
  46. }
  47. else //一页以上
  48. {
  49. #前一页,第一页的算法
  50. $this->result['first'] = ($this->page == 1) ? 0 : 1;
  51. $this->result['pre'] = ($this->page == 1) ? 0 : 1;
  52. #后一页,最后一页的算法
  53. $this->result['next'] = ($this->page == $this->pagecount ) ? 0 : 1;
  54. $this->result['last'] = ($this->page == $this->pagecount ) ? 0 : 1;
  55.  
  56.  
  57. #起始
  58. $pagearray = array();
  59. $start = floor(($this->page-1)/10)*10+1;
  60. for($i=0;$i<10;$i++)
  61. {
  62.      if( ($start+$i) <= $this->result['pagecount'])
  63. {
  64.      $pagearray[$i]['page'] = $start+$i;
  65. }
  66. if( ($start+$i) != $this->page )
  67. {
  68.      $pagearray[$i]['link'] = 1;
  69. }
  70. }
  71. #分页导航列表
  72. $this->result['pagelist'] = $pagearray;
  73. $this->result['baseurl'] = $this->baseurl;
  74. }
  75. }
  76. }
  77. ?>

模版代码

  1. <table>
  2.     <tr>
  3.     <td>
  4. 共{{$page.count}}条数据 每页{{$page.pagesize}}条 共{{$page.pagecount}}页 当前第{{$page.page}}页
  5. </td>
  6. <td>
  7. {{if $page.first eq 1}}
  8. <a href="{{$page.baseurl}}">首页</a>
  9. {{else}}
  10. 首页
  11. {{/if}}
  12. {{if $page.pre eq 1}}
  13. <a href="{{$page.baseurl}}&page={{$page.page-1}}">上一页</a>
  14. {{else}}
  15. 上一页
  16. {{/if}}
  17. {{foreach from=$page.pagelist item=vols}}
  18.     {{if $vols.link eq 1}}
  19. <a href="{{$page.baseurl}}&page={{$vols.page}}">[{{$vols.page}}]</a>
  20. {{else}}
  21. [{{$vols.page}}]
  22. {{/if}}
  23. {{/foreach}}
  24. {{if $page.next eq 1}}
  25. <a href="{{$page.baseurl}}&page={{$page.page-1}}">下一页</a>
  26. {{else}}
  27. 下一页
  28. {{/if}}
  29. {{if $page.last eq 1}}
  30. <a href="{{$page.baseurl}}&page={{$page.pagecount}}">尾页</a>
  31. {{else}}
  32. 尾页
  33. {{/if}}
  34. </td>
  35. </tr>
  36. </table>

调用范例

  1. <?php
  2. require_once('Include/Init.inc.php');
  3. require_once('Include/Class/Page.Class.php');
  4. $page = new Page( 999 , 12 , 10 , 6 , '?' );
  5. $page->__getpagelist();
  6. $smarty->assign("page",$page->result);
  7. $smarty->display("page.html");
  8. ?>
]]>
http://www.sunboyu.cn/2008/08/29/%e7%ae%80%e5%8d%95%e7%9a%84phpsmarty%e5%88%86%e9%a1%b5%e7%b1%bb.shtml/feed
PHP中FTP模块的一些应用 http://www.sunboyu.cn/2008/08/27/php%e4%b8%adftp%e6%a8%a1%e5%9d%97%e7%9a%84%e4%b8%80%e4%ba%9b%e5%ba%94%e7%94%a8.shtml http://www.sunboyu.cn/2008/08/27/php%e4%b8%adftp%e6%a8%a1%e5%9d%97%e7%9a%84%e4%b8%80%e4%ba%9b%e5%ba%94%e7%94%a8.shtml#comments Wed, 27 Aug 2008 02:20:06 +0000 admin http://www.sunboyu.cn/?p=288
  1. <?php
  2. class ftp
  3. {
  4. //connect id
  5. var $ftp;
  6. //remote dir
  7. var $remotedir = '/';
  8. //local dir
  9. var $localdir = './';
  10. //write log
  11. var $writelog = false;
  12. //log file
  13. var $logfile = 'ftp_log.txt';
  14. //print log
  15. var $printlog = false;
  16. //session time
  17. var $timeout = 60;
  18. //construct connetc
  19. function __construct( $host , $user , $pass )
  20. {
  21. $this->ftp = @ftp_connect( $host );
  22. ftp_login( $this->ftp, $user , $pass );
  23. //ftp_set_option( $this->ftp , FTP_TIMEOUT_SEC , $this->timeout );
  24. }
  25. //list sub files
  26. function __list( $dir = false , $subtree = false )
  27. {
  28. $rlist = array();
  29. if(!$dir)
  30. {
  31. $dir = $this->remotedir;
  32. }
  33. $list = ftp_rawlist($this->ftp,$dir,TRUE);
  34. if(is_array($list))
  35. {
  36. foreach( $list as $key => $value )
  37. {
  38. $tmp = explode( ' ' , $value );
  39. $rlist[$key] = end($tmp);
  40. if(@ftp_chdir($this->ftp,$dir.$rlist[$key].'/'))
  41. {
  42. $rlist[$rlist[$key]] = $this->__list( $dir.$rlist[$key].'/' );
  43. unset($rlist[$key]);
  44. }
  45. unset($tmp);
  46. }
  47. }
  48. return $rlist;
  49. }
  50. //change dir  $isabs = false,use rela dir default
  51. function __chdir( $dir , $isabs = false )
  52. {
  53. if(!$isabs)
  54. {
  55. $nextdir = $this->remotedir.$dir.'/';
  56. }
  57. else
  58. {
  59. $nextdir = $dir;
  60. }
  61. if(ftp_chdir($this->ftp,$nextdir))
  62. {
  63. $this->remotedir = $nextdir;
  64. return true;
  65. }
  66. else
  67. {
  68. return false;
  69. }
  70. }
  71. //close connect
  72. function __close()
  73. {
  74. @ftp_close($this->ftp);
  75. }
  76. }
  77. $ftp = new ftp( 'www.sunboyu.cn' , '**', '***' );
  78. $ftp->__chdir('website',0);
  79. $list = $ftp->__list('/');
  80. echo $a = time();
  81. print_r($list);
  82. echo time() - $a;
  83. ?>
]]>
http://www.sunboyu.cn/2008/08/27/php%e4%b8%adftp%e6%a8%a1%e5%9d%97%e7%9a%84%e4%b8%80%e4%ba%9b%e5%ba%94%e7%94%a8.shtml/feed
放弃ADODB_lite数据字典功能 http://www.sunboyu.cn/2008/08/26/%e6%94%be%e5%bc%83adodb_lite%e6%95%b0%e6%8d%ae%e5%ad%97%e5%85%b8%e5%8a%9f%e8%83%bd.shtml http://www.sunboyu.cn/2008/08/26/%e6%94%be%e5%bc%83adodb_lite%e6%95%b0%e6%8d%ae%e5%ad%97%e5%85%b8%e5%8a%9f%e8%83%bd.shtml#comments Tue, 26 Aug 2008 15:33:31 +0000 admin http://www.sunboyu.cn/?p=287 对adodb_lite的数据字典功能进行测试使用后,发现这玩意是一块鸡肋。其优秀之处在于多种数据库的无缝切换,当使用范围扩大的时候,弊端随之暴露:

1:对字段类型的支持不够完全,比如enum类型

2:不支持存储过程触发器之类

而一个项目中,存储过程触发器之类使用很多,没有这些,但出写表的数据字典感觉意义不大,不过简单的表还是会用这种方式,其他的就爹生成sql语句了

]]>
http://www.sunboyu.cn/2008/08/26/%e6%94%be%e5%bc%83adodb_lite%e6%95%b0%e6%8d%ae%e5%ad%97%e5%85%b8%e5%8a%9f%e8%83%bd.shtml/feed
小一探针 http://www.sunboyu.cn/2008/08/21/%e5%b0%8f%e4%b8%80%e6%8e%a2%e9%92%88.shtml http://www.sunboyu.cn/2008/08/21/%e5%b0%8f%e4%b8%80%e6%8e%a2%e9%92%88.shtml#comments Thu, 21 Aug 2008 03:26:28 +0000 admin http://www.sunboyu.cn/?p=283 闲来没事,突然想写个探针
http://www.sunboyu.cn/info.php
难点很多,逐一突破。写这么个东西对PHP和系统的认识提高很快。

]]>
http://www.sunboyu.cn/2008/08/21/%e5%b0%8f%e4%b8%80%e6%8e%a2%e9%92%88.shtml/feed
史上最牛的中文验证码,2过腾讯! http://www.sunboyu.cn/2008/08/18/%e5%8f%b2%e4%b8%8a%e6%9c%80%e7%89%9b%e7%9a%84%e4%b8%ad%e6%96%87%e9%aa%8c%e8%af%81%e7%a0%81%ef%bc%8c2%e8%bf%87%e8%85%be%e8%ae%af%ef%bc%81.shtml http://www.sunboyu.cn/2008/08/18/%e5%8f%b2%e4%b8%8a%e6%9c%80%e7%89%9b%e7%9a%84%e4%b8%ad%e6%96%87%e9%aa%8c%e8%af%81%e7%a0%81%ef%bc%8c2%e8%bf%87%e8%85%be%e8%ae%af%ef%bc%81.shtml#comments Mon, 18 Aug 2008 15:39:02 +0000 admin http://www.sunboyu.cn/?p=282 测试地址 http://www.sunboyu.cn/sourse/nbcode.php

下载地址 http://www.sunboyu.cn/sourse/nbcode.rar

]]>
http://www.sunboyu.cn/2008/08/18/%e5%8f%b2%e4%b8%8a%e6%9c%80%e7%89%9b%e7%9a%84%e4%b8%ad%e6%96%87%e9%aa%8c%e8%af%81%e7%a0%81%ef%bc%8c2%e8%bf%87%e8%85%be%e8%ae%af%ef%bc%81.shtml/feed
使用mysql保存session,并建立在线用户列表 http://www.sunboyu.cn/2008/08/15/%e4%bd%bf%e7%94%a8mysql%e4%bf%9d%e5%ad%98session%ef%bc%8c%e5%b9%b6%e5%bb%ba%e7%ab%8b%e5%9c%a8%e7%ba%bf%e7%94%a8%e6%88%b7%e5%88%97%e8%a1%a8.shtml http://www.sunboyu.cn/2008/08/15/%e4%bd%bf%e7%94%a8mysql%e4%bf%9d%e5%ad%98session%ef%bc%8c%e5%b9%b6%e5%bb%ba%e7%ab%8b%e5%9c%a8%e7%ba%bf%e7%94%a8%e6%88%b7%e5%88%97%e8%a1%a8.shtml#comments Fri, 15 Aug 2008 15:02:21 +0000 admin http://www.sunboyu.cn/?p=280 写OA,使用mysql存储session,这样,是为了获得在线用户的列表,为做一个web im做准备。

首先创建表,注,这里使用了adodb中数据字典的描述方法:

  1. $Session_Fields = "
  2. session_id VARCHAR(100) NOTNULL,
  3. session_value X DEFAULT '',
  4. session_expires I(10) DEFAULT NULL,
  5. userid I(5) DEFAULT NULL
  6. ";
  7. $Session_Tables = array('mysql' => "ENGINE = MYISAM CHARACTER SET utf8 COLLATE utf8_unicode_ci COMMENT = 'session表'");
  8. $dict = NewDataDictionary(GetDB());
  9. $sqlarray = $dict->CreateTableSQL($_CFG['table']['session'], $Session_Fields, $Session_Tables);
  10. $dict->ExecuteSQLArray($sqlarray);

然后session类:

  1. <?php
  2. /*  Session.Class.php
  3.  *  Session Manager
  4.  *  @link        http://www.sunboyu.cn
  5.  *  @package     OA
  6.  *  @version     V1.0
  7.  *
  8.  *  2008 08 14  sunboyu@gmail.com
  9.  */
  10. class Session
  11. {
  12. var $lifetime;
  13. var $db = null;
  14. function __construct()
  15. {
  16. #return adodb lite connetction
  17. $this->db = GetDB();
  18. }
  19. #open
  20. function open( $savepath , $session_name )
  21. {
  22. $this->lifetime =  get_cfg_var("session.gc_maxlifetime");
  23. return true;
  24. }
  25. #close
  26. function close()
  27. {
  28. return true;
  29. }
  30. #read
  31. function read( $session_id )
  32. {
  33. global $_CFG;
  34. $sql = sprintf("SELECT * FROM %s WHERE session_id = %s",$_CFG['table']['session'],GetSqlString( $session_id ));
  35. $rs = $this->db->Execute( $sql );
  36. if($rs->RecordCount()>0)
  37. {
  38. $result = $rs->fields;
  39. return $result['session_value'];
  40. }
  41. else
  42. {
  43. return null;
  44. }
  45. }
  46. #write
  47. function write( $session_id , $session_value )
  48. {
  49. global $_CFG;
  50. $sql = sprintf("SELECT session_id FROM %s WHERE session_id = %s",$_CFG['table']['session'],GetSqlString( $session_id ));
  51. $rs = $this->db->Execute( $sql );
  52. if($rs->RecordCount()==0)
  53. {
  54. $newsql = sprintf("INSERT INTO %s SET session_id = %s , session_value = %s , session_expires = %d",
  55. $_CFG['table']['session'],
  56. GetSqlString( $session_id ),
  57. GetSqlString( $session_value ),
  58. GetSqlString( $this->lifetime+time() , "int" ));
  59. }
  60. else
  61. {
  62. $newsql = sprintf("UPDATE %s SET session_value = %s , session_expires = %d WHERE session_id = %s",
  63. $_CFG['table']['session'],
  64. GetSqlString( $session_value ),
  65. GetSqlString( $this->lifetime+time() , "int" ),
  66. GetSqlString( $session_id ));
  67. }
  68. return $this->db->Execute( $newsql );
  69. }
  70. #destroy
  71. function destroy( $session_id )
  72. {
  73. global $_CFG;
  74. $delsql = sprintf("DELETE FROM %s WHERE session_id = %s",$_CFG['table']['session'],GetSqlString( $session_id ));
  75. return $this->db->Execute( $delsql );
  76. }
  77. #gc
  78. function gc()
  79. {
  80. global $_CFG;
  81. $gcsql = sprintf("DELETE FROM %s WHERE session_expires < %d",$_CFG['table']['session'],time());
  82. return $this->db->Execute( $gcsql );
  83. }
  84. }
  85. ?>

session机制,之前已经介绍,实现代码如下

  1. $session = new Session();
  2. session_set_save_handler(array(&$session,"open"),
  3. array(&$session,"close"),
  4. array(&$session,"read"),
  5. array(&$session,"write"),
  6. array(&$session,"destroy"),
  7. array(&$session,"gc"));
  8. session_start();

把session与用户id对应,使用以下语句即可

  1. sprintf("UPDATE %s SET userid = %d WHERE session_id = %s",$_CFG['table']['session'],GetSqlString($rs['id'],'int'),GetSqlString(session_id(),'text'))
]]>
http://www.sunboyu.cn/2008/08/15/%e4%bd%bf%e7%94%a8mysql%e4%bf%9d%e5%ad%98session%ef%bc%8c%e5%b9%b6%e5%bb%ba%e7%ab%8b%e5%9c%a8%e7%ba%bf%e7%94%a8%e6%88%b7%e5%88%97%e8%a1%a8.shtml/feed
完美的用户登录验证流程 http://www.sunboyu.cn/2008/08/07/%e5%ae%8c%e7%be%8e%e7%9a%84%e7%94%a8%e6%88%b7%e7%99%bb%e5%bd%95%e9%aa%8c%e8%af%81%e6%b5%81%e7%a8%8b.shtml http://www.sunboyu.cn/2008/08/07/%e5%ae%8c%e7%be%8e%e7%9a%84%e7%94%a8%e6%88%b7%e7%99%bb%e5%bd%95%e9%aa%8c%e8%af%81%e6%b5%81%e7%a8%8b.shtml#comments Thu, 07 Aug 2008 04:52:18 +0000 admin http://www.sunboyu.cn/?p=246
登  录  ────────── →  多域

写 session  ────────── →  写cookie
↓                                  \
用户session列表  →  在线用户列表      cookie登录
\  在线踢人

]]>
http://www.sunboyu.cn/2008/08/07/%e5%ae%8c%e7%be%8e%e7%9a%84%e7%94%a8%e6%88%b7%e7%99%bb%e5%bd%95%e9%aa%8c%e8%af%81%e6%b5%81%e7%a8%8b.shtml/feed
使用Mysql来存储Session http://www.sunboyu.cn/2008/07/31/%e4%bd%bf%e7%94%a8mysql%e6%9d%a5%e5%ad%98%e5%82%a8session.shtml http://www.sunboyu.cn/2008/07/31/%e4%bd%bf%e7%94%a8mysql%e6%9d%a5%e5%ad%98%e5%82%a8session.shtml#comments Thu, 31 Jul 2008 14:39:29 +0000 admin http://www.sunboyu.cn/?p=236 接上篇,我们已经知道session的具体存储机制,我们来尝试修改一下这个机制,让数据存储在mysql数据库中。

mysql有三部分的内容,session session_data session_expires分别为session的id session的内容,session的过期时间。

创建这样一个数据库

CREATE TABLE IF NOT EXISTS `sessions` (
`session` varchar(255) character set utf8 collate utf8_bin NOT NULL,
`session_expires` int(10) unsigned NOT NULL default ‘0′,
`session_data` mediumtext collate utf8_unicode_ci,
KEY `session` (`session`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

相对于文件方式的session存储,这两个函数是不用动的
function open($save_path, $session_name)
{
global $sess_save_path;

$sess_save_path = $save_path;
return(true);
}

function close()
{
return(true);
}
而需要修改的是读,写,删,过期操作的函数

读的操作,很简单,只是从数据库中,根据sessionid,读出date字段中的内容
function read($sessID) {
global $php_errormsg;
// fetch session-data
$query = ”
SELECT session_data FROM sessions
WHERE session = ‘$sessID’
AND session_expires >
“.time();
$result = $this->mdb2->query($query);
// return data or an empty string at failure
if (MDB2::isError($result)) {
$php_errormsg .= $result->getMessage();
$php_errormsg .= $result->getDebugInfo ();
return false;
}
list($value)=@$result->fetchrow();
return $value;
}
同理,写的操作就是update数据,destory的操作为删除session的记录,另外有个gc的操作是删除过期的session。
具体的代码没有去实现,但在PHP手册上都有。同时手册还介绍了memcache储存的方式,效率应该会不错的。

这是本月最后一篇日志,也算为下月找个题。

]]>
http://www.sunboyu.cn/2008/07/31/%e4%bd%bf%e7%94%a8mysql%e6%9d%a5%e5%ad%98%e5%82%a8session.shtml/feed
PHP session机制详解 http://www.sunboyu.cn/2008/07/31/php-session%e6%9c%ba%e5%88%b6%e8%af%a6%e8%a7%a3.shtml http://www.sunboyu.cn/2008/07/31/php-session%e6%9c%ba%e5%88%b6%e8%af%a6%e8%a7%a3.shtml#comments Thu, 31 Jul 2008 12:27:05 +0000 admin http://www.sunboyu.cn/?p=235 http://cn.php.net/manual/en/function.session-set-save-handler.php

php的session函数非常好用,使用非常简单,$_SESSION[$name] = **  直接写session,而$_SESSION[$name]就可以直接读session。现在剖析一下简单背后,php是如何工作的。看上边的链接,

bool session_set_save_handler ( callback $open , callback $close , callback $read , callback $write , callback $destroy , callback $gc )

此函数有六个动作,关于session的初始化,结束,读,写,删,和超时处理。

open:初始化session存储路径信息。

close:关闭session。

read:读session的内容

write:写session的内容

destroy:删除session内容

gc:删除过期session

可以看这些函数实现,使用了file操作,在服务端写数据保存session。而这些数据以session专有的格式进行存储,类似cookie的,大家可以试着分解一下。

我找了个session,在editplus下打开 是这样的:

UserID|s:1:”1″;UserName|s:5:”admin”;

]]>
http://www.sunboyu.cn/2008/07/31/php-session%e6%9c%ba%e5%88%b6%e8%af%a6%e8%a7%a3.shtml/feed
sunboyu-amp-mod-V1.0 alpha http://www.sunboyu.cn/2008/07/26/sunboyu-amp-mod-v10-alpha.shtml http://www.sunboyu.cn/2008/07/26/sunboyu-amp-mod-v10-alpha.shtml#comments Sat, 26 Jul 2008 05:37:47 +0000 admin http://www.sunboyu.cn/?p=222 重新做了个模块版的,这次apache使用动态编译

sunboyu-amp-isapi-v10-alpha

]]>
http://www.sunboyu.cn/2008/07/26/sunboyu-amp-mod-v10-alpha.shtml/feed
sunboyu-amp-fastcgi-V1.0 Alpha版本发布 http://www.sunboyu.cn/2008/07/24/sunboyu-amp-fastcgi-v10-alpha%e7%89%88%e6%9c%ac%e5%8f%91%e5%b8%83.shtml http://www.sunboyu.cn/2008/07/24/sunboyu-amp-fastcgi-v10-alpha%e7%89%88%e6%9c%ac%e5%8f%91%e5%b8%83.shtml#comments Thu, 24 Jul 2008 06:04:45 +0000 admin http://www.sunboyu.cn/?p=218 sunboyu-amp-fastcgi-v10-alpha

基本都配置完毕了,但整体流程没有彻底自动化,适当的时候会作出stable版本。
# author:sunboyu@gmail.com
# qq:176300676 msn:sunboyu@gmail.com
# http://www.sunboyu.cn

#!/bin/sh
h_path = “/root/”
url=”http://www.sunboyu.cn/sourse/”
install_dir=”/opt/”
mkdir $install_dir

termcap_sourse_name=”termcap-1.3.1″

mysql_sourse_name=”mysql-5.0.22″
mysql_install_dir=$install_dir$mysql_sourse_name

openssl_sourse_name=”openssl-0.9.8g”
openssl_install_dir=$install_dir$openssl_sourse_name

httpd_sourse_name=”httpd-2.2.9″
httpd_install_dir=$install_dir$httpd_sourse_name

fastcgi_sourse_name=”mod_fastcgi-2.4.6″
fastcgi_install_dir=$install_dir$fastcgi_sourse_name

fcgid_sourse_name=”mod_fcgid.2.2″

libxml2_sourse_name=”libxml2-2.6.30″
libxml2_install_dir=$install_dir$libxml2_sourse_name

zlib_sourse_name=”zlib-1.2.3″

jpeg_sourse_name=”jpegsrc.v6b”
jpeg_install_dir=$install_dir$jpeg_sourse_name

libpng_sourse_name=”libpng-1.2.29″
libpng_install_dir=$install_dir$libpng_sourse_name

freetype_sourse_name=”freetype-2.3.7″
freetype_install_dir=$install_dir$freetype_sourse_name

php_sourse_name=”php-5.2.6″
php_install_dir=$install_dir$php_sourse_name

gd_sourse_name=”gd-2.0.36RC1″
gd_install_dir=$install_dir$gd_sourse_name

###MYSQL依赖库
wget ${url}${termcap_sourse_name}”.tar.gz”
tar -zxvf $termcap_sourse_name”.tar.gz”
cd $termcap_sourse_name
./configure
make && make install
cd ..
#rm -rf ${termcap_sourse_name}*
###openssl
wget ${url}${openssl_sourse_name}”.tar.gz”
tar -zxvf $openssl_sourse_name”.tar.gz”
cd $openssl_sourse_name
./Configure –prefix=$openssl_install_dir
make && make install
cd ..
#rm -rf ${openssl_sourse_name}*
###libxml
wget ${url}${libxml2_sourse_name}”.tar.gz”
tar -zxvf $libxml2_sourse_name”.tar.gz”
cd $libxml2_sourse_name
./configure –prefix=$libxml2_install_dir
make && make install
cd ..
#rm -rf ${libxml2_sourse_name}*
###zlib
wget ${url}${zlib_sourse_name}”.tar.gz”
tar -zxvf $zlib_sourse_name”.tar.gz”
cd $zlib_sourse_name
./configure
make && make install
cd ..
cp /usr/lib/libz.so.1 /usr/lib/libz.so
#rm -rf ${zlib_sourse_name}*
###jpeg
wget ${url}${jpeg_sourse_name}”.tar.gz”
tar -zxvf $jpeg_sourse_name”.tar.gz”
cd jpeg-6b
./configure
mkdir /usr/local/man/
mkdir /usr/local/man/man1/
mkdir /usr/local/man/man1/cjpeg/
make && make install
cp /usr/lib/libjpeg.so.62 /usr/lib/libjpeg.so
cp jpeglib.h /usr/include/jpeglib.h
cp jconfig.h /usr/include/jconfig.h
cp jmorecfg.h /usr/include/jmorecfg.h
cp jerror.h /usr/include/jerror.h
cd ..
#rm -rf ${jpeg_sourse_name}.tar.gz
#rm -rf jpeg-6b
###png
wget ${url}${libpng_sourse_name}”.tar.gz”
tar -zxvf $libpng_sourse_name”.tar.gz”
cd $libpng_sourse_name
./configure –prefix=$libpng_install_dir
make && make install
cp png* /usr/include/
cd ..
#rm -rf ${libpng_sourse_name}*
###freetype
wget ${url}${freetype_sourse_name}”.tar.gz”
tar -zxvf $freetype_sourse_name”.tar.gz”
cd $freetype_sourse_name
./configure –prefix=$freetype_install_dir
make && make install
cd ..
#rm -rf ${freetype_sourse_name}*
###GD2
wget ${url}${gd_sourse_name}”.tar.gz”
tar -zxvf $gd_sourse_name”.tar.gz”
cd $gd_sourse_name
./configure –prefix=$gd_install_dir –with-png=/opt/libpng-1.2.29 –with-freetype=/opt/freetype-2.3.7 –with-jpeg=/usr/lib/libjpeg.so
make && make install
cd ..
#rm -rf ${gd_sourse_name}*
###MYSQL
groupadd mysql
useradd -g mysql mysql
wget ${url}${mysql_sourse_name}”.tar.gz”
tar -zxvf $mysql_sourse_name”.tar.gz”
cd $mysql_sourse_name
./configure –prefix=$mysql_install_dir –without-debug –with-unix-socket-path=/tmp/mysql.sock –with-client-ldflags=-all-static –with-mysqld-ldflags=-all-static –enable-local-infile –enable-largefile –with-charset=utf8 –with-pic –with-mysqld-libs –with-comment –with-query-cache –with-bench –with-big-tables –with-innodb –with-mysqld-use=mysql
make && make install
cp ./support-files/my-medium.cnf /etc/my.cnf
cp ./support-files/mysql.server /etc/init.d/mysqld
cd ..
#mkdir $mysql_install_dir/var/
#$mysql_install_dir/bin/mysql_install_db –user=mysql &
#$mysql_install_dir/bin/mysqld_safe –user=mysql &

echo ${mysql_install_dir}”/bin/mysqld_safe –user=mysql &”>>/etc/rc.local
#rm -rf ${mysql_sourse_name}*
###APACHE
wget ${url}${httpd_sourse_name}”.tar.gz”
tar -zxvf $httpd_sourse_name”.tar.gz”
cd $httpd_sourse_name
./configure –prefix=$httpd_install_dir –enable-authz-dbm –enable-log-config –enable-headers –enable-setenvif –with-ssl=$openssl_install_dir –enable-static-ab –enable-http –enable-mime –enable-status –enable-suexec –enable-vhost-alias –enable-dir –enable-rewrite –with-mpm=worker
make && make install
cd ..
ln -s $httpd_install_dir/bin/apachectl /etc/init.d/httpd
echo $httpd_install_dir/bin/apachectl start>>/etc/rc.local
chkconfig –level 345 httpd on
#rm -rf ${httpd_sourse_name}*
###fastcgi
wget ${url}${fastcgi_sourse_name}”.tar.gz”
tar -zxvf $fastcgi_sourse_name”.tar.gz”
cd $fastcgi_sourse_name
sed ’s/\/usr\/local\/apache2/\/opt\/httpd-2.2.9\//g’ Makefile.AP2 > Makefile
make && make install
cd ..
###fcgid
wget ${url}${fcgid_sourse_name}”.tgz”
tar -zxvf $fcgid_sourse_name”.tgz”
cd $fcgid_sourse_name
mv Makefile Makefile.AP2
sed ’s/\/usr\/local\/apache2/\/opt\/httpd-2.2.9\//g’ Makefile.AP2 > Makefile
make && make install
cd ..
echo LoadModule fcgid_module modules/mod_fcgid.so>>$httpd_install_dir/conf/httpd.conf
echo AddHandler fcgid-script .php>>$httpd_install_dir/conf/httpd.conf
echo “FCGIWrapper “${php_install_dir}”/bin/php-cgi .php”>>$httpd_install_dir/conf/httpd.conf
#rm -rf ${fastcgi_sourse_name}*
###PHP
wget ${url}${php_sourse_name}”.tar.gz”
tar -zxvf $php_sourse_name”.tar.gz”
cd $php_sourse_name
cp php.ini-dist php.ini
./configure –prefix=$php_install_dir –with-libxml-dir=$libxml2_install_dir –enable-cli –enable-cgi –enable-fastcgi –enable-force-cgi-redirect –enable-discard-path –enable-path-info-check –with-openssl –with-pcre-regex –enable-calendar –enable-dom –enable-ftp –with-openssl-dir=/usr/local/ssl –enable-gd-jis-conv –enable-hash –with-iconv –enable-json –enable-mbstring –enable-mbregex –enable-pdo –enable-posix –enable-libxml=$xml2_install_dir –enable-simplexml –with-sqlite –enable-tokenizer –enable-xmlreader –enable-xmlwriter –with-zlib –with-freetype-dir=$freetype_install_dir –with-gd=$gd_install_dir –with-jpeg-dir=/usr/lib/libjpeg.so –with-libpng-dir=/opt/libpng-1.2.29/lib/libpng12.so –with-zlib-dir=/usr/lib/libz.so –with-mime-magic –with-mysql=$mysql_install_dir –with-zlib-dir=/usr/lib/libz.so –with-pdo-mysql=$mysql_install_dir –with-pdo-sqlite –enable-posix –enable-soap
make && make install
cp php.ini $php_install_dir/lib/
cd ..
$mysql_install_dir/bin/mysql_install_db –user=mysql &

service httpd start
service mysqld start

]]>
http://www.sunboyu.cn/2008/07/24/sunboyu-amp-fastcgi-v10-alpha%e7%89%88%e6%9c%ac%e5%8f%91%e5%b8%83.shtml/feed
Apache2 PHP5 FastCgi配置终于完成 http://www.sunboyu.cn/2008/07/23/apache2-php5-fastcgi%e9%85%8d%e7%bd%ae%e7%bb%88%e4%ba%8e%e5%ae%8c%e6%88%90.shtml http://www.sunboyu.cn/2008/07/23/apache2-php5-fastcgi%e9%85%8d%e7%bd%ae%e7%bb%88%e4%ba%8e%e5%ae%8c%e6%88%90.shtml#comments Wed, 23 Jul 2008 14:12:57 +0000 admin http://www.sunboyu.cn/?p=213 这次是使用的mod_fastcgi的一个替代品:fcgid http://fastcgi.coremail.cn/ 在功能上完全可以取代fastcgi,在性能和稳定性上还优于fastcgi(据说),不过配置起来也比fastcgi的简单,只需要加上 loadmodule fcgid_module SetHandler fcgid-script
FCGIWrapper /usr/local/bin/php-cgi .php 即可。
权限方面,呵呵,还没有测试。留档,加到我的amp的shell里。

LoadModule fcgid_module modules/mod_fcgid.so
AddHandler fcgid-script .php
FCGIWrapper /opt/php5/bin/php-cgi .php

]]>
http://www.sunboyu.cn/2008/07/23/apache2-php5-fastcgi%e9%85%8d%e7%bd%ae%e7%bb%88%e4%ba%8e%e5%ae%8c%e6%88%90.shtml/feed
amp自动安装脚本安装部分已经完成 http://www.sunboyu.cn/2008/07/22/amp%e8%87%aa%e5%8a%a8%e5%ae%89%e8%a3%85%e8%84%9a%e6%9c%ac%e5%ae%89%e8%a3%85%e9%83%a8%e5%88%86%e5%b7%b2%e7%bb%8f%e5%ae%8c%e6%88%90.shtml http://www.sunboyu.cn/2008/07/22/amp%e8%87%aa%e5%8a%a8%e5%ae%89%e8%a3%85%e8%84%9a%e6%9c%ac%e5%ae%89%e8%a3%85%e9%83%a8%e5%88%86%e5%b7%b2%e7%bb%8f%e5%ae%8c%e6%88%90.shtml#comments Tue, 22 Jul 2008 04:04:41 +0000 admin http://www.sunboyu.cn/?p=207 做个版本存档

myshell_demo

]]>
http://www.sunboyu.cn/2008/07/22/amp%e8%87%aa%e5%8a%a8%e5%ae%89%e8%a3%85%e8%84%9a%e6%9c%ac%e5%ae%89%e8%a3%85%e9%83%a8%e5%88%86%e5%b7%b2%e7%bb%8f%e5%ae%8c%e6%88%90.shtml/feed
LAMP自动安装脚本 http://www.sunboyu.cn/2008/07/15/lamp%e8%87%aa%e5%8a%a8%e5%ae%89%e8%a3%85%e8%84%9a%e6%9c%ac.shtml http://www.sunboyu.cn/2008/07/15/lamp%e8%87%aa%e5%8a%a8%e5%ae%89%e8%a3%85%e8%84%9a%e6%9c%ac.shtml#comments Tue, 15 Jul 2008 15:08:39 +0000 admin http://www.sunboyu.cn/?p=200 mysql,apache的基本搞定了,php的还有很多问题,先放出这些代码,方便自己操作。PHP部分正在调试。

#!/bin/sh
h_path = “/root/”
url=”http://www.sunboyu.cn/sourse/”
install_dir=”/opt/”
mkdir $install_dir

termcap_sourse_name=”termcap-1.3.1″

mysql_sourse_name=”mysql-5.0.22″
mysql_install_dir=$install_dir$mysql_sourse_name

openssl_sourse_name=”openssl-0.9.8g”
openssl_install_dir=$install_dir$openssl_sourse_name

httpd_sourse_name=”httpd-2.2.9″
httpd_install_dir=$install_dir$httpd_sourse_name

fastcgi_sourse_name=”mod_fastcgi-2.4.6″
fastcgi_install_dir=$install_dir$fastcgi_sourse_name

libxml2_sourse_name=”libxml2-2.6.30″
libxml2_install_dir=$install_dir$libxml2_sourse_name

zlib_sourse_name=”zlib-1.2.3″
zlib_install_dir=$install_dir$zlib_sourse_name

jpeg_sourse_name=”jpegsrc.v6b”
jpeg_install_dir=$install_dir$jpeg_sourse_name

libpng_sourse_name=”libpng-1.2.29″
libpng_install_dir=$install_dir$libpng_sourse_name

freetype_sourse_name=”freetype-2.3.7″
freetype_install_dir=$install_dir$freetype_sourse_name

php_sourse_name=”php-5.2.6″
php_install_dir=$install_dir$php_sourse_name

###MYSQL
wget ${url}${termcap_sourse_name}”.tar.gz”
tar -zxvf $termcap_sourse_name”.tar.gz”
cd $termcap_sourse_name
./configure
make && make install
cd ..
rm -rf ${termcap_sourse_name}*

groupadd mysql
useradd -g mysql mysql

wget ${url}${mysql_sourse_name}”.tar.gz”
tar -zxvf $mysql_sourse_name”.tar.gz”
cd $mysql_sourse_name
./configure –prefix=$mysql_install_dir –enable-thread-safe-client –enable-local-infile –enable-largefile –with-charset=utf8 –with-uca –with-gnu-ld –with-pic –with-mysqld-libs –with-comment –with-query-cache –with-bench –with-big-tables –with-innodb –with-mysqld-use=mysql
make && make install
cd ..
rm -rf ${mysql_sourse_name}*

###APACHE

wget ${url}${openssl_sourse_name}”.tar.gz”
tar -zxvf $openssl_sourse_name”.tar.gz”
cd $openssl_sourse_name
./configure –prefix=$openssl_install_dir
make && make install
cd ..
rm -rf ${openssl_sourse_name}*

wget ${url}${httpd_sourse_name}”.tar.gz”
tar -zxvf $httpd_sourse_name”.tar.gz”
cd $httpd_sourse_name
./configure –prefix=$httpd_install_dir –enable-authz-dbm –enable-log-config –enable-headers –enable-setenvif –with-ssl=$openssl_install_dir –enable-static-ab –enable-http –enable-mime –enable-status –enable-suexec –enable-vhost-alias –enable-dir –enable-rewrite –with-mpm=worker
make && make install
cd ..
rm -rf ${httpd_sourse_name}*

wget ${url}${fastcgi_sourse_name}”.tar.gz”
tar -zxvf $fastcgi_sourse_name”.tar.gz”
cd $fastcgi_sourse_name
sed ’s/\/usr\/local\/apache2/\/opt\/httpd-2.2.9\//g’ Makefile.AP2 > Makefile
make && make install
cd ..
rm -rf ${fastcgi_sourse_name}*

###PHP
wget ${url}${libxml2_sourse_name}”.tar.gz”
tar -zxvf $libxml2_sourse_name”.tar.gz”
cd $libxml2_sourse_name
./configure –prefix=$libxml2_install_dir
make && make install
cd ..
rm -rf ${libxml2_sourse_name}*

wget ${url}${zlib_sourse_name}”.tar.gz”
tar -zxvf $zlib_sourse_name”.tar.gz”
cd $zlib_sourse_name
./configure –prefix=$zlib_install_dir
make && make install
cd ..
rm -rf ${zlib_sourse_name}*

wget ${url}${jpeg_sourse_name}”.tar.gz”
tar -zxvf $jpeg_sourse_name”.tar.gz”
cd $jpeg_sourse_name
cp makefile.unix Makefile
make && make install
cd ..
rm -rf ${jpeg_sourse_name}*

wget ${url}${libpng_sourse_name}”.tar.gz”
tar -zxvf $libpng_sourse_name”.tar.gz”
cd $libpng_sourse_name
./configure –prefix=$libpng_install_dir
make && make install
cd ..
rm -rf ${libpng_sourse_name}*

wget ${url}${freetype_sourse_name}”.tar.gz”
tar -zxvf $freetype_sourse_name”.tar.gz”
cd $freetype_sourse_name
./configure –prefix=$freetype_install_dir
make && make install
cd ..
rm -rf ${freetype_sourse_name}*

wget ${url}${php_sourse_name}”.tar.gz”
tar -zxvf $php_sourse_name”.tar.gz”
./php-5.2.6/configure –enable-cli –enable-cgi –enable-fastcgi –enable-force-cgi-redirect –enable-discard-path –enable-path-info-check –with-openssl –with-pcre-regex –enable-calendar –enable-dom –enable-ftp –with-openssl-dir=/usr/local/openssl –enable-gd-jis-conv –enable-hash –with-iconv –enable-json –enable-mbstring –enable-mbregex –enable-pdo –enable-posix –enable-libxml –enable-simplexml –with-sqlite –enable-tokenizer –enable-xmlreader –enable-xmlwriter –with-zlib=/usr/local/zlib –with-freetype-dir=/usr/local/freetype –with-gd –with-jpeg-dir=/usr/lib/libjpeg.so.62.0.0

]]>
http://www.sunboyu.cn/2008/07/15/lamp%e8%87%aa%e5%8a%a8%e5%ae%89%e8%a3%85%e8%84%9a%e6%9c%ac.shtml/feed
打造全能优化的Linux+Apache+PHP+Mysql服务器(3) http://www.sunboyu.cn/2008/07/15/%e6%89%93%e9%80%a0%e5%85%a8%e8%83%bd%e4%bc%98%e5%8c%96%e7%9a%84linuxapachephpmysql%e6%9c%8d%e5%8a%a1%e5%99%a8%ef%bc%883%ef%bc%89.shtml http://www.sunboyu.cn/2008/07/15/%e6%89%93%e9%80%a0%e5%85%a8%e8%83%bd%e4%bc%98%e5%8c%96%e7%9a%84linuxapachephpmysql%e6%9c%8d%e5%8a%a1%e5%99%a8%ef%bc%883%ef%bc%89.shtml#comments Tue, 15 Jul 2008 06:30:24 +0000 admin http://www.sunboyu.cn/?p=199 apache部分

先安装openssl

./configure –enable-authz-dbm –enable-log-config –enable-headers –enable-setenvif –with-ssl=/usr/local/ssl  –enable-static-ab –enable-http –enable-mime –enable-status –enable-suexec –enable-vhost-alias –enable-dir –enable-rewrite –with-mpm=worker

fastcgi

cp Makefile.AP2 Makefile
make make install

]]>
http://www.sunboyu.cn/2008/07/15/%e6%89%93%e9%80%a0%e5%85%a8%e8%83%bd%e4%bc%98%e5%8c%96%e7%9a%84linuxapachephpmysql%e6%9c%8d%e5%8a%a1%e5%99%a8%ef%bc%883%ef%bc%89.shtml/feed
打造全能优化的Linux+Apache+PHP+Mysql服务器(2) http://www.sunboyu.cn/2008/07/15/%e6%89%93%e9%80%a0%e5%85%a8%e8%83%bd%e4%bc%98%e5%8c%96%e7%9a%84linuxapachephpmysql%e6%9c%8d%e5%8a%a1%e5%99%a8%ef%bc%882%ef%bc%89.shtml http://www.sunboyu.cn/2008/07/15/%e6%89%93%e9%80%a0%e5%85%a8%e8%83%bd%e4%bc%98%e5%8c%96%e7%9a%84linuxapachephpmysql%e6%9c%8d%e5%8a%a1%e5%99%a8%ef%bc%882%ef%bc%89.shtml#comments Tue, 15 Jul 2008 03:33:13 +0000 admin http://www.sunboyu.cn/?p=197 MYsql的安装

mysql 编译参数
./configure –enable-thread-safe-client –enable-local-infile –enable-largefile –with-charset=utf8  –with-uca –with-gnu-ld –with-pic –with-mysqld-libs –with-comment –with-query-cache –with-bench –with-big-tables –with-innodb –with-mysqld-use=mysql

/usr/local/bin/mysql_install_db

/usr/local/bin/mysqld_safe  –user mysql

如果安装时候有错误提示,也许是缺少这个组件  http://www.sunboyu.cn/sourse/termcap-1.3.1.tar.gz

]]>
http://www.sunboyu.cn/2008/07/15/%e6%89%93%e9%80%a0%e5%85%a8%e8%83%bd%e4%bc%98%e5%8c%96%e7%9a%84linuxapachephpmysql%e6%9c%8d%e5%8a%a1%e5%99%a8%ef%bc%882%ef%bc%89.shtml/feed
打造全能优化的Linux+Apache+PHP+Mysql服务器(1) http://www.sunboyu.cn/2008/07/13/%e6%89%93%e9%80%a0%e5%85%a8%e8%83%bd%e4%bc%98%e5%8c%96%e7%9a%84linuxapachephpmysql%e6%9c%8d%e5%8a%a1%e5%99%a8%ef%bc%881%ef%bc%89.shtml http://www.sunboyu.cn/2008/07/13/%e6%89%93%e9%80%a0%e5%85%a8%e8%83%bd%e4%bc%98%e5%8c%96%e7%9a%84linuxapachephpmysql%e6%9c%8d%e5%8a%a1%e5%99%a8%ef%bc%881%ef%bc%89.shtml#comments Sun, 13 Jul 2008 13:05:51 +0000 admin http://www.sunboyu.cn/?p=196 fastcgi   http://www.fastcgi.com/dist/mod_fastcgi-2.4.6.tar.gz
apache2   http://apache.mirror.phpchina.com/httpd/httpd-2.2.9.tar.gz
mysql5    http://dev.mysql.com/get/Downloads/MySQL-5.0/mysql-5.0.51b.tar.gz/from/http://mysql.mirrors.arminco.com/
php5      http://cn2.php.net/distributions/php-5.2.6.tar.gz
libxml2
gd-jpeg   ftp://192.48.96.9/graphics/jpeg/jpegsrc.v6b.tar.gz
freetype  http://voxel.dl.sourceforge.net/sourceforge/freetype/freetype-2.3.7.tar.gz
libpng    http://voxel.dl.sourceforge.net/sourceforge/libpng/libpng-1.2.29.tar.gz
zend      http://www.zend.com/download/55

memcached  http://www.danga.com/memcached/dist/memcached-1.2.5.tar.gz
memcache   http://pecl.php.net/get/memcache-3.0.1.tgz
libevent   http://www.monkey.org/~provos/libevent-1.2a.tar.gz

目前想到的功能大概有这些,想到再加。

目前正在研究每一个组件的性能和参数。

]]>
http://www.sunboyu.cn/2008/07/13/%e6%89%93%e9%80%a0%e5%85%a8%e8%83%bd%e4%bc%98%e5%8c%96%e7%9a%84linuxapachephpmysql%e6%9c%8d%e5%8a%a1%e5%99%a8%ef%bc%881%ef%bc%89.shtml/feed
程序调式N多招 http://www.sunboyu.cn/2008/07/08/%e7%a8%8b%e5%ba%8f%e8%b0%83%e5%bc%8fn%e5%a4%9a%e6%8b%9b.shtml http://www.sunboyu.cn/2008/07/08/%e7%a8%8b%e5%ba%8f%e8%b0%83%e5%bc%8fn%e5%a4%9a%e6%8b%9b.shtml#comments Tue, 08 Jul 2008 12:00:13 +0000 admin http://www.sunboyu.cn/?p=184 最近在群里扯淡,好多小鸟提的问题其实很简单,程序本身的报错机制就能告诉你错误。现在列出所有能给你提示的方法.

  1. 打开PHP的报错。在php.ini(win下)中,寻找  error_reporting   ,设置 error_reporting  =  E_ALL & ~E_NOTICE,好像默认就是这个。
  2. 如果还是找不到,那么在你程序的头上加上:error_reporting(2047),这样错误也都会出来。

这两条是程序有硬伤的时候,直接报出来。如果逻辑上的错误,咋调呢?我的方法比较奔,但的确有效。

  1. 输入echo “aaa”;break; 这样,可以判断出程序是哪里出问题而中断了。
  2. print_r($var);这样去跟踪你认为出错的数据,用肉眼监视+大脑计算,去对比程序的计算,只要涉及变量值可能改变的地方,都得去对比。

这是程序差错的方法。mysql就更简单了,把你认为有错误的sql语句echo出来,放到phpmyadmin里去执行,看那个报错就行了。

最后一点:下载个星际译王,当然是指英文不太利索的。

]]>
http://www.sunboyu.cn/2008/07/08/%e7%a8%8b%e5%ba%8f%e8%b0%83%e5%bc%8fn%e5%a4%9a%e6%8b%9b.shtml/feed
多语言风格网站的语言模块处理 http://www.sunboyu.cn/2008/07/05/%e5%a4%9a%e8%af%ad%e8%a8%80%e9%a3%8e%e6%a0%bc%e7%bd%91%e7%ab%99%e7%9a%84%e8%af%ad%e8%a8%80%e6%a8%a1%e5%9d%97%e5%a4%84%e7%90%86.shtml http://www.sunboyu.cn/2008/07/05/%e5%a4%9a%e8%af%ad%e8%a8%80%e9%a3%8e%e6%a0%bc%e7%bd%91%e7%ab%99%e7%9a%84%e8%af%ad%e8%a8%80%e6%a8%a1%e5%9d%97%e5%a4%84%e7%90%86.shtml#comments Sat, 05 Jul 2008 14:57:27 +0000 admin http://www.sunboyu.cn/?p=181 奥运来了,流行国际化,网站也趋向于国际化。多语言网站成了流行,这里,我总结了一下多语言网站的设计。

首先,要设计多个语言包,打个比方,一个cn的,代表汉语,一个en的,代表英语。然后建立一个映射关系。比如,helloword,你好世界,英文,中文,我们给这个短句定一个ID,ID=’HW’,在英文语言包里,HW=’helloword’,在汉语语言包里,HW=’你好世界’。以此类推,语言包就做好了。

然后,我们要确定当前页面是调用哪个语言包。可以由读者去确定,比如,默认是英文,然后用户可以手工设置为汉语。可以通过session来设定一个变量,进行控制,但大多数是通过cookie。也可以根据域名,比如 http://cn.sunboyu.cn ,解析主机名,cn 即为汉语。  得到了客户端语言的标志,我们就可以确定调用哪个语言包。

最后说一下实现机制。最简单的方式,就是定义成数据,比如 $Lang['cn']['HW']=’你好世界’  $Lang['en']['HW'] ,这样,通过数据二级的键值就可以取出值。Smarty支持一个功能,就是config_load的功能,只要模板里有个语言种类变量,就可以动态调用语言包。还有,就是php的gettext扩展,都是一样的道理,只是存储不同。

做好你的语言包,做好语言选择控制,多语言网站就可以出炉了。

]]>
http://www.sunboyu.cn/2008/07/05/%e5%a4%9a%e8%af%ad%e8%a8%80%e9%a3%8e%e6%a0%bc%e7%bd%91%e7%ab%99%e7%9a%84%e8%af%ad%e8%a8%80%e6%a8%a1%e5%9d%97%e5%a4%84%e7%90%86.shtml/feed
WEB开发中分层的概念 http://www.sunboyu.cn/2008/06/26/web%e5%bc%80%e5%8f%91%e4%b8%ad%e5%88%86%e5%b1%82%e7%9a%84%e6%a6%82%e5%bf%b5.shtml http://www.sunboyu.cn/2008/06/26/web%e5%bc%80%e5%8f%91%e4%b8%ad%e5%88%86%e5%b1%82%e7%9a%84%e6%a6%82%e5%bf%b5.shtml#comments Thu, 26 Jun 2008 06:24:13 +0000 admin http://www.sunboyu.cn/?p=154 这些日子一直在分析刚完工的项目,总得来说,能交付测试。但离产品阶段,还是差很差一截。

产品化,即一个项目可以轻松复制,交付给不同用户。

产品化的软件一个关键是不是可以轻松迁移,而轻松迁移就取决于迁移需要修改的参数接口是不是更加灵活。这在于我们在设计产品之前有没有合理开发一些关键参数,进行迁移。

在这个层面上说的分层,可理解为软件主题跟用户接口的分层。我们把软件-接口=开发者-用户这样的结构理解为两层。

程序层面上的分层,看此篇   PHP工厂方式的三层结构

另一个产品化的标识,就是方便修改,主要是风格方面。因此,在程序前端部分,需要合理设计我们的VIEW层代码。

VIEW层分层,主要是分成HTML(DIV)+CSS,CSS决定页面的风格,这样,只要重新CSS就能快速修改页面风格。

JS分层。如果是试用标准的xhtml标准或者DOM格式的代码,那可以方便得把事件和函数写在附加的js文件中。

]]>
http://www.sunboyu.cn/2008/06/26/web%e5%bc%80%e5%8f%91%e4%b8%ad%e5%88%86%e5%b1%82%e7%9a%84%e6%a6%82%e5%bf%b5.shtml/feed
Mysql备份SHELL v1.0demo版问世 http://www.sunboyu.cn/2008/06/22/mysql%e5%a4%87%e4%bb%bdshell-v10demo%e7%89%88%e9%97%ae%e4%b8%96.shtml http://www.sunboyu.cn/2008/06/22/mysql%e5%a4%87%e4%bb%bdshell-v10demo%e7%89%88%e9%97%ae%e4%b8%96.shtml#comments Sat, 21 Jun 2008 20:57:40 +0000 admin http://www.sunboyu.cn/?p=130 虽然功能不是很完善,应该很不完善,但还是放出来让大家批评一下。

感谢PHP开源支持者的鼓励,感谢杜江老师的鼓励。mysqldump v1.0 demo 下载 版权所有,欢迎盗版!

源代码

#!/usr/local/bin/php -q
# mysql cron manager system
# sunboyu@gmail.com
# v1.0
define(’SUN_FILE_NAME’,'bak.sh’);
define(’SUN_BAK_PATH’,’./’); #bak path
define(’SUN_CFG_PATH’,’./’); #config file path
define(’SUN_LOG_PATH’,’./’); #log file path
define(’SUN_DATABASE_CHARACTER’,'UTF-8′); #mysql character
define(’SUN_SHELL_EXEC’,”system”);
define(’SUN_IS_TAR’,0);
#save temp argv in session
session_start();

Main::mains();

class Main
{
//main()
public static function mains()
{
KernelInfo::version();
self::getUserInput();
}
//for user’s inpyt
public function getUserInput()
{
while(($u_char = KernelBase::cgetchar(’shell’))&&($u_char != ‘quit’))
{
switch($u_char)
{
case “–help”:
KernelInfo::help();
break;
case “–version”:
KernelInfo::version();
break;
case “–check”:
KernelInfo::checksystem();
break;
case “–mysqldump”:
Mysql::MysqlGuide();
break;
default:
print(”error input!\n”);
break;
}
}
}
}

class KernelBase
{
//get input string
public function cgetchar( $cue = false )
{
if( $cue )
{
print($cue.”:”);
}
$string = trim(fgets(STDIN));
return $string;
}
//get argvs
public function cgetargv( $string )
{
if(!empty($string))
{
$argvs = explode( ” ” , $string );
$reargvs = false;
for( $i = 0; $i < count($argvs) ; $i++ )
{
if( $argvs[$i][0]==’-’ && $argvs[$i][1]==’-’ )
{
$reargvs[$argvs[$i]] = true;
$x++;
}
else if( $argvs[$i][0]==’-’ && $argvs[$i][1]!=’-’ )
{
$reargvs[$argvs[$i]] = isset($argvs[($i+1)])&&($argvs[($i+1)][0]!=’-')&&($argvs[($i+1)][0]!=”) ? $argvs[($i+1)] : ”;
isset($argvs[($i+1)])&&($argvs[($i+1)][0]!=’-')&&($argvs[($i+1)][0]!=”) ? $i++ : ”;
}
}
return $reargvs;
}
else
{
return false;
}
}
}

class KernelIO
{
//write file
public function write_file( $filename , $content )
{
$handle = fopen( $filename );
fwrite( $handle , $content );
fclose( $handle );
}
}
class KernelInfo
{
//show version
public function version()
{
print(”##################################\n”);
print(”# Mysql Back Cron Manage Shell #\n”);
print(”# Auth: sunboyu #\n”);
print(”# Version: v1.0 #\n”);
print(”##################################\n”);
}
//show help
public function help()
{
print(sprintf(”%s [--version] [--help] [--check]\n”,SUN_FILE_NAME));
print(” –version Show\n”);
print(” –help This Help\n”);
print(” –check This Help\n”);
}
//check system info
public function checksystem()
{
print(”System:”.$_GLOBAL['System'].”\n”);
$check_dir = array( SUN_BAK_PATH , SUN_CFG_PATH , SUN_LOG_PATH );
foreach($check_dir as $key => $value)
{
if(is_writable($value))
{
print(”The dir ‘”.$value.”‘ is writable!\n”);
}
else
{
print(”The dir ‘”.$value.”‘ is unwritable.Please check the power!\n”);
print(”The shell is stop!”);
exit();
}
}
$shell_exec = SUN_SHELL_EXEC;
if($shell_exec(’ls’))
{
print(”The shell can execute “.SUN_SHELL_EXEC.”;\n”);
}
else
{
print(”The shell can’t execute “.SUN_SHELL_EXEC.”;\n”);
print(”The shell is stop!”);
exit();
}
print(”The Shell can work in this system!\n”);
}
//check is writeable the dir
public function is_writeable( $dir )
{
return @is_writable( $dir );
}
}

#Mysql Dump
class Mysql
{
function MysqlGuide()
{
$mysqlargv = array(
‘-host’ => false,
‘-username’ => false,
‘-password’ => false,
‘-datebase’ => false,
‘-otherargv’ => false
);
$argvs = KernelBase::cgetargv(KernelBase::cgetchar(”input argv”));
foreach($argvs as $key => $value)
{
$mysqlargv[$key] = empty($value) ? ” : $value;
}
if($mysqlargv['-host']&&$mysqlargv['-username']&&$mysqlargv['-datebase'])
{
self::Mysqldump( $mysqlargv['-host'] , $mysqlargv['-username'] , $mysqlargv['-password'] , $mysqlargv['-datebase'] , $mysqlargv['-otherargv'] );
}
else
{
print(”error vars!\n”);
}
}
function Mysqldump( $host = false , $username = false , $password = ” , $datebase = false , $otherargv = false )
{
$shell_exec = SUN_SHELL_EXEC;
if($host&&$username&&$datebase)
{
$command = “mysqldump –opt “.$datebase.” -u”.$datebase.” -p”.$db_password.( $otherargv ? $otherargv : ” ).” > “.SUN_BAK_PATH.”db_bak.sql”;
$feedback = $shell_exec( $command );
print($feedback.”\n”);
}
}
}

?>

]]>
http://www.sunboyu.cn/2008/06/22/mysql%e5%a4%87%e4%bb%bdshell-v10demo%e7%89%88%e9%97%ae%e4%b8%96.shtml/feed
基于PHP-CLI的数据库备份管理软件今日奠基 http://www.sunboyu.cn/2008/06/20/%e5%9f%ba%e4%ba%8ephp-cli%e7%9a%84%e6%95%b0%e6%8d%ae%e5%ba%93%e5%a4%87%e4%bb%bd%e7%ae%a1%e7%90%86%e8%bd%af%e4%bb%b6%e4%bb%8a%e6%97%a5%e5%a5%a0%e5%9f%ba.shtml http://www.sunboyu.cn/2008/06/20/%e5%9f%ba%e4%ba%8ephp-cli%e7%9a%84%e6%95%b0%e6%8d%ae%e5%ba%93%e5%a4%87%e4%bb%bd%e7%ae%a1%e7%90%86%e8%bd%af%e4%bb%b6%e4%bb%8a%e6%97%a5%e5%a5%a0%e5%9f%ba.shtml#comments Fri, 20 Jun 2008 15:37:57 +0000 admin http://www.sunboyu.cn/?p=128 确定了基本的功能

  • 创建任务mysql数据库备份任务
  • 管理cron任务跟备份任务的结合
  • 任务管理

基本能满足一个网管备份mysql的日常操作。

由于是第一个版本,没做太多的功能,实现再说。

这个东东也是展示下PHP功能的强大。PHP代替Perl也不是不可能的。

]]>
http://www.sunboyu.cn/2008/06/20/%e5%9f%ba%e4%ba%8ephp-cli%e7%9a%84%e6%95%b0%e6%8d%ae%e5%ba%93%e5%a4%87%e4%bb%bd%e7%ae%a1%e7%90%86%e8%bd%af%e4%bb%b6%e4%bb%8a%e6%97%a5%e5%a5%a0%e5%9f%ba.shtml/feed
关于require和require_once的研究 http://www.sunboyu.cn/2008/06/16/%e5%85%b3%e4%ba%8erequire%e5%92%8crequire_once%e7%9a%84%e7%a0%94%e7%a9%b6.shtml http://www.sunboyu.cn/2008/06/16/%e5%85%b3%e4%ba%8erequire%e5%92%8crequire_once%e7%9a%84%e7%a0%94%e7%a9%b6.shtml#comments Mon, 16 Jun 2008 15:12:04 +0000 admin http://www.sunboyu.cn/?p=123 前几天写程序蹦出个问题,研究一下。

先创建文件 a.php

<?php
$a = “test”;
?>

再创建 b.php

<?php
function a()
{
require_once(”a.php”);
echo $a;
echo “-”;
}
function b()
{
require_once(”a.php”);
echo $a;
echo “-”;
}
a();
b();
?>

运行结果是  test–

然后修改为

<?php
function a()
{
require(”a.php”);
echo $a;
echo “-”;
}
function b()
{
require(”a.php”);
echo $a;
echo “-”;
}
a();
b();
?>

则执行结果是 test-test-

—————————————

结论:require_once这个动作,加载一次是相对于一个页面,在函数a中包含一次,a.php中变量$a的作用域只是函数a()的内部,而无法在b()中使用,而b()虽然require_once(’a.php’),但由于页面中a()中先包含了一次,而在b()中却不再执行包含操作。

因此,当两个函数内部都需要使用调用页面的变量时,要不调用在函数外,global的方式调用,或者使用require()多次调用。

不错推荐第一种方式

]]>
http://www.sunboyu.cn/2008/06/16/%e5%85%b3%e4%ba%8erequire%e5%92%8crequire_once%e7%9a%84%e7%a0%94%e7%a9%b6.shtml/feed
PHP error_reporting()研究 http://www.sunboyu.cn/2008/06/16/php-error_reporting%e7%a0%94%e7%a9%b6.shtml http://www.sunboyu.cn/2008/06/16/php-error_reporting%e7%a0%94%e7%a9%b6.shtml#comments Mon, 16 Jun 2008 13:40:37 +0000 admin http://www.sunboyu.cn/?p=121 PHP错误处理与反馈机制,是使用set_error_handler(”myErrorHandler”); 使程序出错时调用此函数。

此函数有4个参数,myErrorHandler($errno, $errstr, $errfile, $errline),$error-错误号,$errstr-错误描述,$errfile-错误文件,$errline-出错的行号。
用此方法,可以捕捉并记录详细的错误信息,可以根据项目需求进行错误级别评定。

WordPress的报错声明
// Add define(’WP_DEBUG’,true); to wp-config.php to enable display of notices during development.
if (defined(’WP_DEBUG’) and WP_DEBUG == true) {
error_reporting(E_ALL);
} else {
error_reporting(E_ALL ^ E_NOTICE ^ E_USER_NOTICE);
}

插件的报错
error_reporting( E_ALL ^ E_NOTICE );

升级程序的报错
error_reporting( E_ALL ^ E_NOTICE );

]]>
http://www.sunboyu.cn/2008/06/16/php-error_reporting%e7%a0%94%e7%a9%b6.shtml/feed
PHP中工厂方式的三层结构 http://www.sunboyu.cn/2008/06/14/php%e4%b8%ad%e5%b7%a5%e5%8e%82%e6%96%b9%e5%bc%8f%e7%9a%84%e4%b8%89%e5%b1%82%e7%bb%93%e6%9e%84.shtml http://www.sunboyu.cn/2008/06/14/php%e4%b8%ad%e5%b7%a5%e5%8e%82%e6%96%b9%e5%bc%8f%e7%9a%84%e4%b8%89%e5%b1%82%e7%bb%93%e6%9e%84.shtml#comments Sat, 14 Jun 2008 14:38:23 +0000 admin http://www.sunboyu.cn/?p=114 项目即将收尾,但有些代码乱七八糟,不少东西是为了赶时间而写成了流水程序。功能出来了,但代码可读性和可维护性却相当差。当然拿出少量时间给代码排个版是很有必要的,这里我一直主张工厂模式三层结构的方法。

网站基本是传统的机构,数据库,web,在这里,我们只讨论web中程序的结构。

三层,主要是指子类,抽象工厂方法,业务逻辑处理。

子类:子类是所有跟程序之外对象进行交互的类,包括跟数据库,磁盘存储,xml等的处理。子类有个特征,就是可以迁移到任意的项目中进行复用,也就是整个项目中最底层的一些操作。

工厂方法:工厂方法就是使用子类提供的功能进行整合,构造出能够满足一些业务具体功能的方法。

业务处理:业务处理主要是UI部分,根据用户的请求来选择合适的工厂方法,把工厂方法的返回产品数据输出给用户。

]]>
http://www.sunboyu.cn/2008/06/14/php%e4%b8%ad%e5%b7%a5%e5%8e%82%e6%96%b9%e5%bc%8f%e7%9a%84%e4%b8%89%e5%b1%82%e7%bb%93%e6%9e%84.shtml/feed
PHP中数据有效性验证 http://www.sunboyu.cn/2008/06/14/php%e4%b8%ad%e6%95%b0%e6%8d%ae%e6%9c%89%e6%95%88%e6%80%a7%e9%aa%8c%e8%af%81.shtml http://www.sunboyu.cn/2008/06/14/php%e4%b8%ad%e6%95%b0%e6%8d%ae%e6%9c%89%e6%95%88%e6%80%a7%e9%aa%8c%e8%af%81.shtml#comments Sat, 14 Jun 2008 12:54:57 +0000 admin http://www.sunboyu.cn/?p=113 在php的开发过程中,我们的error_reporting()开到最严格,2047,因此,好多php本身可避免的报错也都会出来,就跟C一样让在在强类型状态下工作。

为了尽量使程序兼容,我们对每个变量的有效性进行严格判断。

我一般使用 isset($a) ? $a : ”;这种方式对变量进行判断,如果变量不存在的话初始化变量。

当然在其他的地方也可以使用该方法检验变量有效性。

底下是大部分进行验证的函数。

检测变量状态: isset()   empty()

检测变量类型 is_array() is_double() is_float() is_real()  is_long() is_int() is_integer() is_string() is_object()

具体使用可以查下手册

PHP并不比C或者其他语言差,关键在于你编程的态度.

]]>
http://www.sunboyu.cn/2008/06/14/php%e4%b8%ad%e6%95%b0%e6%8d%ae%e6%9c%89%e6%95%88%e6%80%a7%e9%aa%8c%e8%af%81.shtml/feed