Archive for the ‘PHP’ Category
Monday, May 31st, 2010
最近开发一个项目,需要用到饼图显示统计数据,而且每个扇区要有不同的超链接。和以往一样,秉承“他山之石,可以攻玉”的理念,我直接去 www.phpclasses.org 上开始淘宝,由于一年来开发任务繁忙,我的电子信箱里积压了差不多200封来自phpclasses的电子邮件,全部都是介绍最新php类库的订阅邮件,或许里面就有很好的饼图生成类,遗憾的是我现在实在来不及一一查看了,直接在phpclasses上搜索吧。这里也提醒我自己该找个空闲时间,把那些宝贝程序祛其糟粕,取其精华,充实代码库,还方便后续开发。
搜索结果比较理想,找到一个大胡子兄弟写好的类库。下载配置一下,运行结果看似比较理想。但是放到生产环境后,问题接踵而来。
第一:图片写入汉字存在问题,具有中国特色的问题,我们自己解决;
第二:调试扇区超链接时用firebug无法看到扇区图片映射关系;
第三:扇区超链接使用了图片映射方法,当扇区面积大于90度时,出现错误;
第四:当各个扇区代表的数字比较大时,出现错误。
从后面几个问题看来,大胡子兄弟写这个类的时候也没有仔细测试过,或许当时他完成这个类库的时候,需求很简单,各个扇区分布均匀,而且统计数字值也不大。好了,我们开始一个一个解决问题就是。
问题1:
原来类库里写入字符串使用的是:imagestring()方法,我们换用imagettftext()方法,再把/usr/share/fonts/chinese/TrueType/uming.ttf拷贝到类库根目录下,原代码是:
imagestring($image,2,2.13*$r+$r/20,.71*$r+($r/15)*$j-2,$this->elements[$j]."-".$this->elementnames[$j],$black);
修改后的代码为:
$fontFile = dirname(__FILE__)."/uming.ttf";
$str = $this->elementnames[$j]."-".$this->typeStr.":".$this->displayElements[$j];
imagettftext($image,10,0,2.13 * $r + $r / 20,.71 * $r + ( $r / 15 ) * ($j * 2) + 13,$black,$fontFile,$str);
同时在编译安装php的时候,--enable-gd-jis-conv这个参数要去掉,才能正确在图片中写入汉字。
问题2:
用无敌的firebug看一下,如图:
很明显,有空坐标,所以firebug也显示不出映射关系,那么我们看一下原始代码:
$Coo[$j]['coords'] .= ",$tmpx,$tmpy,";
呵呵,原来如此,后面多了一个逗号,去掉问题解决。
问题3:
当某个扇区角度大于90度甚至大于180度时,扇区映射的范围会出现问题,如图:
很明显,映射构建多边形时,连线构成的面积侵占了其他扇区的空间,按照html标准,扇区之间会覆盖,造成的后果就是,点击这个扇区,结果真实点击的是其他扇区的链接。
现在我们看一下原始代码:
$Coo[$j]['coords'] = "$x1,$y1,$x22,$y22,$x33,$y33";
if ($part > 90) {
for ($k=30;$k 90) {
$Coo[$j]['coords'] = "$x1,$y1,$x22,$y22";
} else {
$Coo[$j]['coords'] = "$x1,$y1,$x22,$y22,$x33,$y33";
}
if ...
Posted in PHP | No Comments »
Tuesday, April 27th, 2010
最近开发的一个项目涉及到大量的数组和字符串重组排序,整天都被这些东西纠缠,好在随做随总结,发现有些东西万变不离其中。重组排序翻来覆去归根结底也是那么多的需求,多翻翻php手册,很多内置的方法既巧妙又方便,对于一些成了规律的东西,我们封装一下再重复利用岂不妙哉!下面记录一个数组处理类,以后会陆续更新的... ...
Posted in PHP | 1 Comment »
Friday, October 23rd, 2009
程序设计思路:j2me程序以http方式发送GET请求给服务器,服务器上的php程序返回xml格式的数据,j2me解析xml并处理数据。
备注:以下测试都基于模拟器,只是介绍实现思路,真机实现需要考虑的问题更多,例如http请求需要首先过滤中国移动的资费页面,汉字参数需要使用urlencode等等。
先解决几个问题:
问题一:为什么使用xml,而不是json?
解答:
php内置了处理json的方法,例如:
Posted in J2ME, JAVA, Architecture, PHP | No Comments »
Wednesday, October 7th, 2009
lightphp适合熟练的phper进行企业级应用开发,如果单纯论及代码自动生成,ORM模型和yml载入之类功能,lightphp无法跟一些成熟的框架(例如symfony)相比。我们的目的是,按需定制,性能优先。
如果做访问量不高且功能简单的应用,lightphp就不是明智的选择,建议使用成熟的框架和数据操作方案,例如:symfony + Doctrine。但是一个入门教程又不可能写得太复杂,所以还是用构建小型blog应用做例子,麻雀虽小,但五脏俱全,基本涵盖了lightphp的开发流程,希望起到抛砖引玉的作用。
(本教程基于linux + apache + mysql + php平台)
1.下载安装lightphp
zip
tar.gz
解压缩lightphp1.0.zip到你的web目录,配置虚拟主机为:
DocumentRoot "/home/htdocs/framework/lightphp/blog/0.2/control"
ServerName blog.lightphp.com
DirectoryIndex index.php
Options Indexes FollowSymLinks
AllowOverride All
Order deny,allow
Allow from all
修改/etc/hosts,加入:
127.0.0.1 blog.lightphp.com
重新启动网络和apache服务器,在浏览器里输入http://blog.lightphp.com既可以访问到lightphp的欢迎界面。
2.blog数据库设计
数据库名就叫:lightphp_blog,由于功能实现很简单,所以我们只需要两个表即可实现。
文章表
lightphp_article{
recordID:(int(8))
title:(varchar(100))
...
Posted in lightphp, PHP | No Comments »
Wednesday, October 7th, 2009
lightphp使用原生php语法,所以框架api很少,只用到了最基本的内容。
1.load_config($file)
功能:载入配置文件
实例:
载入/config/custom.config.php文件
load_config('custom.config');
2.load_lib($file)
功能:载入方法或者类
实例:
载入/lib/mysql.db.class.php文件
load_lib('mysql.db.class');
3.template($tpl,$data = "")
功能:输出模板
实例:
动作程序:/module/default/index.php,
Posted in lightphp, PHP | No Comments »
Sunday, October 4th, 2009
一直以来,从php嵌套html开发到最终使用法国造symfony这个重型开发框架,我还一直没有碰到有关性能的问题,直到后来使用symfony1.2.7开发的项目竟然不堪重负,虽然团队伙伴最终发现是因为symfony1.2开启了路由缓存导致cpu占用过高,symfony官方网站也给出了解决办法,但是从这件事情看来,用别人的东西,尤其是一个非常复杂的东西,总是不保险的。由此我也萌生了开发一个最简单php框架的想法。
轻量级php框架lightphp主要特点
1.本框架使用面向过程(在处理某些特殊功能需求时还是会用到面向对象知识,例如图像处理类)的php开发模式;
lightphp之所以采用面向过程的架构设计,主要是参考了康盛创想uchome系列产品的设计思路,有的时候,使用底层的技术,虽然代码可读性和程序灵活性上差强人意,但是性能的提升是不可忽略的。
2.本框架使用者最好是已经使用PHP一年以上者,推荐新手去使用那些面向对象且方便开发的PHP框架,例如symfony;
lightphp中很多东西需要开发者去考虑,去实施,例如配置虚拟主机使url友好,如何规划项目方法库和类库,如何重构模板等等,这一切都不会像symfony等重型框架那样帮你去完成。所以需要使用者有一定的开发经验。
2.使用MVC模式实现,模板拼装需要手工完成;
MVC是比较流行而高效的开发模式,lightphp使用MVC设计思想来实现模型层、视图层和控制器之间的配合,lightphp没有使用模板引擎,而是在模板中使用了普通的php语法,也没有引入模板缓存方案。
3.取消文件自动载入功能,手工载入需要的文件;
文件自动载入可以方便开发,但是却在牺牲性能,所以我们抛弃这种方案。
4.友好的url路由规则使用手写.htaccess文件实现,推荐将其复制到虚拟主机配置中加快速度;
网站需要友好的url,这已经是做网站必须考虑的,一些重型框架可以通过yml文件配置而实现url重写,但是这种路由规则实现方案过于耗费系统资源,会降低性能,所以我们改为开发中使用.htaccess文件实现url重写,建议在最终发布产品时把重写规则粘贴到虚拟主机配置中加快访问速度。
5.数据操作使用原始sql查询,没有ORM,建议自己封装一个数据操作类使用即可;
propel和doctrine在使用上很便捷,但方便开发是以牺牲效率为代价的,所以数据查询推荐使用普通sql查询,当然lightphp可以安装ORM,但我们不推荐这样做。
6.取消yml文件载入配置信息方式,一切使用php常量和数组实现;
一些重型php框架配置信息载入使用yml文件为载体,lightphp中用到的配置信息全部以php常量或数组实现。
Posted in lightphp, PHP | No Comments »
Friday, September 11th, 2009
网站架构加入mysql读写分离,是流行的做法。下面记录一下如何如何让采用symfony框架的产品加入mysql读写分离,我们使用doctrine实现数据操作。
在database.yml里输入:
all:
master:
class: sfDoctrineDatabase
param:
dsn: 'mysql:host=localhost;dbname=mydb'
username: master
password: master
option: charset=utf8
slave:
class: sfDoctrineDatabase
param:
dsn: 'mysql:host=localhost;dbname=mydb'
...
Posted in PHP, symfony | No Comments »
Wednesday, September 9th, 2009
最近开发一个使用symfony框架的产品,并且需要把这个项目作为一个应用添加到ucenter系列产品中,以前做过的都是康盛家族产品的整合和二次开发,还没有试验过把php框架开发的项目整合到ucenter中,整合的过程就记录在这里了。
(以下实验基于symfony1.2.7,ucenter1.0,uchome1.5版本)
康盛官方提供了一个ucenter开发包,里面包含一份电子版手册,一个uc客户端软件包,还有一个实例程序包。实际上我们现在要整合symfony项目到ucenter中,就是把实例程序改写成symfony框架程序格式,然后调用uc客户端软件包即可实现。那么首先,我们分析一下ucenter的通讯机制。
登录ucenter管理界面,只要你点击了“应用管理”选项卡,ucenter就会分别发出对应的请求给应用项目来测试通讯是否通畅。例如,我们安装了ucenter和uchome两个产品,那么ucenter就发出一个请求给uchome,uchome项目里的通讯客户端程序接受请求并返回一个常量API_RETURN_SUCCEED,如此即为我们看到的“通讯成功”。具体可以通过抓包分析并阅读ucenter的源代码查看细节。
以登录同步为例,假如我们安装了ucenter、uchome和discuz三个产品,现在我们访问uchome并登录,同步登录机制会同时让discuz的用户会话写入,即我们看到的同步登录实现。访问实例程序并抓包试验一下,原来客户端软件包在登录时通过与ucenter通讯获取了js代码,来发送登录请求给其他项目,即uchome登录时,uchome自己写入了会话,同时通js发送请求给discuz的通讯客户端程序,discuz的通讯客户端程序在验证是同步登录请求后,把会话写入了当前浏览器,由此实现了同步登录。
明白了这些基本原理,我们后面的工作就是把这套实现机制引入symfony程序了。
开发流程:
1.定义symfony路由规则
在routing.yml里加入如下代码:
url: /api/uc.php
param: { module: sync, action: ping }
url: /login
param: { module: sync, action: login }
2.构建module和action
创建sync模块和两个动作ping和login
3.加入uc客户端软件包,加入相应类文件
把client通讯包拷贝到项目lib目录下,把以下配置代码加到client.php中:
// 与 UCenter 的通信密钥, 要与 UCenter 保持一致
define('UC_KEY', sfConfig::get('app_ucenter_key'));
// UCenter 的 IP
define('UC_IP', '');
//同步登录 Cookie 设置
define('UC_CHARSET', 'utf8');// UCenter 的字符集
$cookiedomain = '';// cookie 作用域
$cookiepath = '/';// cookie 作用路径
//center的url地址
define('UC_API',sfConfig::get('app_center_url'));
把实例程序包api/uc.php中的方法authcode()封装成一个类放到apps/frontend/lib下,注意通讯密钥要被authcode()访问到
4.开发动作代码
首先写通讯代码,pingAction.class.php代码如下:
Posted in PHP, symfony | No Comments »
Thursday, August 13th, 2009
最近一直在使用symfony + Doctrine,碰到两个问题,困扰了1天时间,记录在这里。
场景1: 运行代码如下:
$query = new Table();
foreach ($array as $key => $value)
{
$query->field1 = $value['field1'];
$query->field2 = $value['field2'];
$query->save();
}
结果倒好,$array里有7个记录需要插入,结果变成了最后一条插入,其他的不知所踪。(中间省略了查资料,改配置的文字... ...)最后我实在想不出哪里出问题了,干脆,打开doctrine的源代码,找到unitofwork.php(symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection),在function saveGraph()的$this->insert($record)和$this->update($record)各加入中断代码,看看到底怎么回事。等结果打印在屏幕上了,我马上明白了,代码执行成了一次插入,后面紧跟六次修改记录,无怪乎只有最后一条记录了。现在修改代码如下,执行正常了。
foreach ($array as $key => $value)
{
$query = new Table();
$query->field1 = $value['field1'];
$query->field2 = $value['field2'];
$query->save();
}
场景2:插入一条记录后,可以获取last insert id,在网上找了doctrine的资料,说$obj->save();后执行$obj->id;即可获取last insert id,实际中却只能获取一个空数组,又是一顿解决问题(省略查资料,改配置的文字... ...),最后发现这里耽误的时间过多了,干脆,把doctrine源代码record.php(symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine)和unitofwork.php(symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection)都改了,直接让$obj->save()返回last insert id搞定,先暂时这样吧,或许以后能找到不动doctrine源代码的解决办法。
Posted in PHP, symfony | 2 Comments »
Wednesday, July 15th, 2009
首先声明,没出血。稍微夸大点,提醒我以后注意... ...仅此而已。
最近使用symfony1.2做一个项目,使用了ORM doctrine。还是老路子,基于数据库生成schema.yml文件,再生成model类,最后操作数据。可是就在这里出了问题,项目需要连结两个不同的数据库,这两个数据库名不一样,里面的表结构有一些不同,但是里面的表名都一样,为了区别操作,我在schema.yml里指定了connection: master或者connection: client属性,可是这以后无论我怎么重新构建model,甚至重新构建schema.yml,改写database.yml,数据库连结就是不按照我的想法去进行,它总是连结database.yml里最后的那个数据库。两天时间,逼得我重新把doctrine和symfony官方网站上所有的文档又看了一遍,实在是不知道怎么办了。
最后请来了蚂蚱,刚开始他也觉得很诧异,为什么这里会出问题呢?他看了又看,忽然他说道:“谁让你这么干的?”我一愣,只见他指着config/doctrine/目录下的copy of schema.yml一脸惊讶得说道:“谁让你这么做备份的?把这个删除了就好了!”
用框架,千万小心自动载入功能,要牢记!
Posted in PHP, symfony | 1 Comment »
Friday, May 8th, 2009
昨天晚上没事可干,躺在床上抱着小黑看uchome的源代码,边调试边看,发现uchome的分页方法很巧妙,正好手痒,就把这个方法改装成一个类,改装完毕后,再完善一下,使之可以支持symfony。记录在这里了。
Posted in PHP | 1 Comment »
Sunday, November 23rd, 2008
web开发技术一日千里,传统的lamp架构逐步被lnmp架构替代,或许几年后,nginx/lighttpd会大面积替代apache,但是我们不会忘记apache这个老伙伴,它陪伴我们走过了无数个日夜,兢兢业业得在无数个服务器上运行着,实现着众多企业家的“技术变现”战略... ...我谨以此文纪念我的老伙伴——Apache。
测试环境:
CentOS 5.2 i386 无包安装操作系统
CentOS 5.3 x86_64 安装开发库和开发工具
Fedora 10 i386 无包安装操作系统
CentOS 5.5 x86_64 安装开发工具和开发库
安装前说明:
使用无包安装的CentOS会出现某些缺包错误,具体解决方法下面都已经写好。如果在安装CentOS时安装好了开发库和开发工具,则不会出现缺包错误。
安装前确保已经安装了gcc(包含在开发工具中),无包安装CentOS是不带gcc的。
yum安装开发工具和开发库,安装速度取决于网络环境,一般在安装操作系统时进行安装:
yum groupinstall 'Development Tools'
yum groupinstall 'Development Libraries'
安装Apache服务器
如果CentOS安装了图形界面,即使选择无包安装操作系统,但是由于包依赖关系,系统还是会自动安装Apache,所以需要首先卸载掉Apache。当然,我们可以先验证一下:
rpm -qa | grep httpd
然后再删除Apache:
yum remove httpd
不安装图形界面的CentOS不存在这个问题,开始安装apache。
tar zxvf httpd-2.2.14.tar.gz
cd httpd-2.2.14
cd srclib/apr
./configure --prefix=/usr/local/apr && make && make install
cd ..
cd apr-util
./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr && ...
Posted in mysql, CentOS, PHP | No Comments »
Wednesday, May 14th, 2008
Yesterday I took one hour to study PHP GD lib.I read this book's chapter which is about PHP Advanced Pic Technology.The picture which can descripe this book is below.
After reading it,I felt it is easy to operate pic using PHP GD.When I home,I suddenly wanted to write a PHP Class ...
Posted in PHP | No Comments »
Wednesday, May 14th, 2008
昨天拿一个小时研究了一下PHP GD类库的使用方法,实际就是看了这本书
中的PHP图像技术一章节,感觉PHP利用GD类库操作图片的确很方便。晚上回家忽然萌生了写一个PHP图片验证码类的想法。所以就有了下面的代码,呵呵,现在贴出来,请大家多提宝贵意见,谢谢!
Posted in PHP | No Comments »
Thursday, March 13th, 2008
最近一直在试验symfony,今天偶然发现了module命名的一个小问题。写下来大家一起讨论一下。
做法:新建项目,建立myapp,然后创建moduel,名字取default,这个时候访问项目url(最好使用开发模式url),显示见下图:
这个时候在module default的action里actions.class.php文件里加一个方法,例如list,list的功能随便你定义,可以从数据库里随便取几个数据,当然了,要创建对应的listSuccess.php模板来显示对应动作传的数据;然后修改默认方法index的$this->forward('default',module);为$this->forward('default','list');。这一切都做完后,修改myproject/apps/myapps/config/routing.yml路由协议文件中的homepage部分为param: { module: default, action: list}。当这一切都做好后,运行symfony cc清除所有缓存。
现在访问项目url,展现在你眼前的页面只是default module的动作actions.class.php中list方法对应的listSuccess.php模板内容,没有layout.php的内容。
如果你是用除default以外的名字命名module,目前为止还没出现过上面的情况。此类问题在学习官方手册时也没见有提醒命名规则的内容。个人感觉symfony的内部处理机制在转到layout.php布局时存在一个默认的module和控制动作,名字应该就是default。
以上只是个人的理解,如果有不同意见,请留言。
Posted in PHP, symfony | 2 Comments »