2009年5月15日星期五

大型网站的优化策略

在搜索引擎优化中,SEO策略影响到最终的优化效果。SEO策略不管对中小网站还是大型网站都是重要的,而对于大型网站,制定一个好的SEO策略尤为重要。

一、首先我们来看第一部分:关键词分析。

关键词分析是所有SEO必须掌握的一门功课,大型网站虽然有海量的数据,但是每个页面都需要进行关键词分析,除了SEO之外,策划、编辑也需要具备一定的关键词分析能力。

我们来看关键词分析的基本原则:

1、 调查用户的搜索习惯:这是一个重要的方面,只有了解用户的搜索习惯,我们才能把我用户的搜索需求,用户喜欢搜索什么?用什么搜索引擎?等等

2、 关键词不能过于宽泛:关键词过于宽泛会导致竞争激烈,耗费大量时间却不一定得到想要的效果,并且可能降低了关键词的相关性。关键词的相关性要参考百度相关关键字.例如在百度搜索深圳市招调工信息

http://www.baidu.com/s?ie=gb2312&bs=%D5%D0%B5%F7%B9%A4%BF%BC%CA%D4+0755333&sr=&z=&cl=3&f=8&wd=%C9%EE%DB%DA%CA%D0%D5%D0%B5%F7%B9%A4%D0%C5%CF%A2%CD%F8&ct=0

那么在这页面的下面有相关搜索,点击更多相关搜索可以获得更多的相关性关键字.

3、 关键词不能过冷:想想,没有用户搜索的关键词,还值得去优化吗?

4、 关键词要与页面内容保持高度的相关性:这样既有利于优化又有利于用户。

我们再来看关键词挑选的步骤:

1、 确定核心关键词:我们应该考虑的是哪一个词或者两个词能够最准确的描述网页的内容?哪一个词用户搜索次数最多?

2、 核心关键词定义上的扩展:例如核心关键词的别名、仅次于核心关键词的组合等、核心关键词的辅助等。

3、 模拟用户思维设计关键词:把自己假想为用户,那么我会去搜索什么关键词呢?

4、 研究竞争者的关键词:分析一下排名占有优势的竞争对手的网页,他们都使用了什么关键词?

二、我们再来看第二部分:页面逆向优化。

为什么要做逆向优化?因为在大型网站中,页面的优化价值一般不同于中小网站。考虑到各种综合因素(例如品牌、页面内容、用户体验等),大型网站的页面优化价值大多数呈现逆向顺序,即:最终页>专题页>栏目页>频道页>首页。

如何针对各页面进行关键词分配呢?通常情况是这样的:

1、 最终页:针对长尾关键词

2、 专题页:针对热门关键词,例如“周杰伦”

3、 栏目页:针对固定关键词,例如“音乐试听”

4、 频道页:针对核心关键词,例如 “音乐”

5、 首页:不分配关键词,而是以品牌为主。

在进行关键词分配后,我们可以在最终页中添加匹配的内链作为辅助,这是大型网站内链的优势。

三、第三部分,前端搜索引擎友好,包括UI设计的搜索友好和前端代码的搜索友好两点。

1、首先我们来看UI设计的搜索引擎友好:主要是做到导航清晰,以及flash和图片等的使用,一般来说,导航以及带有关键词的部分不适合使用flash及图片,因为大多数搜索引擎无法抓取flash及图片中的文字。

2、然后是前端代码的搜索引擎友好:包含以下几点

a、代码的简洁性:搜索引擎喜欢简洁的html代码,这样更有利于分析。

b、重要信息靠前:指带关键词的及经常更新的信息尽量选择出现在html的靠前位置。

c、过滤干扰信息:大型网站的页面一般比较复杂,各种广告、合作、交换内容以及其他没有相关性的信息比较多,我们应该选择使用js、iframe等搜索引擎无法识别的代码过滤掉这一部分信息。

d、代码的基础SEO:这是基础的SEO工作,避免html错误以及语义化标签。

四、第四部分,内部链接策略:

为什么要强调内部链接策略?因为内链具有以下优势:

1、 大型网站海量的数据使内链的优势远远大于外链。外链的数量可能几千几万几十万,但是大型网站拥有成百万上千万甚至上亿的海量网页内容,如果用这些海量的网页做内链的建设,优势是很明显的。

2、 网站内的网页间导出链接是一件很容易的事情。

3、 提高搜索引擎对网站的爬行索引效率,增强收录,也有利于PR的传递。

4、 集中主题,使该主题的关键词在搜索引擎中具有排名优势。

在内链建设中,我们应该遵循以下原则:

1、 控制文章内链数量:穿插于文章内的链接可以根据内容的多少控制在3—8个左右。

2、 链接对象的相关性要高。

3、 给重要的网页更多的关注:使重要的更有关键词价值的网页得到更好的排名。

4、 使用绝对路径。

五、第五部分,外部链接策略:

我们强调大型网站的内链建设,但是我们同时也不能太忽视了外链的建设。外链的建设虽然没有中小网站那么重要,但是也具有很高的价值。我们通常可以通过交换链接、制造链接诱饵、投放带链接的软文等方法来建设外链。

1、 我们来看交换链接应该要遵循哪些原则:

a、 链接文字中包含关键词

b、 尽量与相关性高的站点、频道交换链接

c、 对方网站导出链接数量不能过多,过多的话没有太大的价值

d、 避免与未被收录以及被搜索引擎惩罚的网站交换链接

2、 制造链接诱饵:制造链接诱饵是一件省力的工作,这使得对方网站主动的为我们添加链接。制造链接诱饵的技巧很多,但是可以用两个字来概括:创意。

3、 带链接的软文投放。指的是在商务推广或者为专门为了得到外链而进行的带链接的软文投放。

六、第六部分,网站地图策略:

有很多大型网站不重视网站地图的建设,不少大型网站的网站地图只是敷衍了事,做一个摆设。其实网站对于大型网站是很重要的,大型网站海量的数据、复杂的网站导航结构、极快的更新频率使得搜索引擎并不能完全抓取所有的网页。这就是为什么有的大型网站拥有百万千万甚至上亿级的数据量,但是却只被搜索引擎收录了网站数据量的一半、三分之一甚至更少的一个重要原因。连收录都保证不了,怎么去做排名?

Html地图:

1、 为搜索引擎建立一个良好的导航结构。

2、 Html地图中可以分为横向和纵向导航,横向导航主要是频道、栏目、专题等链接,纵向导航主要是针对关键词。

3、 每个页面都有指向网站地图的链接。

Xml网站地图:

主 要针对Google、yahoo、live等搜索引擎。因为大型网站数据量太大,单个的sitemap会导致sitemap.xml文件太大,超过搜索引 擎的容忍度。所以我们要将sitemap.xml拆分为数个,每个拆分后的sitemap.xml则保持在搜索引擎建议的范围内。

七、第七部分,搜索引擎友好写作策略:

搜索引擎友好写作是创造海量数据对取得好的搜索引擎排名的很关键的一部分。而SEO人员不可能针对每个网页都提出SEO建议或者方案,所以对写作人员的培训尤为重要。如果所有写作人员都按照搜索引擎友好的原则去写作,则产生的效果是很恐怖的。

1、 对写作人员要进行反复培训:写作人员不是SEO,没有经验,不可能一遍就领悟SEO的写作技巧。所以要对写作人员进行反复的培训才能达到效果。

2、 创造内容先思考用户会去搜索什么,针对用户的搜索需求而写作。

3、 重视title、meta写作:例如Meta虽然在搜索引擎的权重已经很低,但是不好的meta写作例如堆积关键词、关键词与内容不相关等行为反而会产生负作用。而Title的权重较高,尽量在Title中融入关键词。

4、 内容与关键词的融合:在内容中要适当的融入关键词,使关键词出现在适当的位置,并保持适当的关键词密度。

5、 为关键词加入链接很重要:为相关关键词加入链接,或者为本网页出现的其他网页的关键词加入链接,可以很好的利用内链优势。

6、 为关键词使用语义化标签:

八、第八部分,日志分析与数据挖掘:

日志分析与数据挖掘常常被我们所忽视,其实不管是大型网站还是中小网站,都是一件很有意义的工作。只是大型网站的日志分析和数据挖掘工作难度要更高一些,因为数据量实在太大,所以我们要具备足够的耐心来做该项工作,并且要有的放矢。

1、 网站日志分析:网站日志分析的的种类有很多,如访问来源、浏览器、客户端屏幕大小、入口、跳出率、PV等。跟SEO工作最相关的主要有以下三种:

a、 搜索引擎流量导入

b、 搜索引擎关键词分析

c、 用户搜索行为统计分析

2、 热点数据挖掘:我们可以通过自身的网站日志分析以及一些外在的工具和SEO自己对热点的把握能力来进行热点数据的挖掘。热点数据的挖掘主要有以下手段:

a、 把握行业热点,可以由编辑与SEO共同完成

b、 预测潜在热点,对信息的敏感度要求较高,能够预测潜在的热门信息。

c、 自己创造热点,如炒作等

d、 为热点制作专题

九、第九部分,为关键词创作专题:

除 了最终页面,各种针对热门的关键词所制作的专题应该作为网站的第二大搜索引擎流量来源。我们在对热点数据进行挖掘后,就可以针对这些热门关键词制作专题 了。制作的专题页的内容从何而来?我们一般通过程序实现对应关键词相关的信息进行筛选聚合,这样就使得内容与关键词高度匹配,为用户、为搜索引擎都提供了 所需要的内容。
当然,仅仅建立一个专题而没有辅助手段是很难保证专题的搜索引擎排名的,我们可以通过文章内链、频道页推荐、或者最终页的专题推荐来获得链接达到效果。(本文来自天梯网网站策划运营社区 http://www.tntbbs.com

1、为热点关键词制作专题

2、关键词相关信息的聚合

3、辅以文章内链导入链接

2009年5月11日星期一

更好地使用Google的服务

网上有很多关于Google的使用技巧,大多数不外乎是传授如何使用搜索语法,比如使用“+”号、“-”号等。在刚才做的一份关于可能吧读者的调查里,很多人喜欢看技巧型文章。

这篇文章里说的内容都和Google相关,但并不是针对某一Google服务,大多数都是我平时使用记事本记录下来的一些小技巧,这里和大家分享一些。

基于我个人在经营一个博客,很多技巧是和网站/博客相关的,但事实上那只是它们的其中一个用法,你完全可以举一反三。

一、普通技巧

1、使用google.com,而非google.cn

可能有不少人不愿意使用经常出现“根据当地法律法规,部分结果未予显示”的google.cn,我个人是更愿意使用Google.com的,然而,直接在浏览器输入google.com会被重置到google.cn。

要想不被重置,方法很简单,使用这个URL:http://www.google.com/ncr

ncr的意思是:No Country Redirect

接下来,在Preference里选择Chinese即可使用中文版的Google.com.

2、我经常使用的搜索式子

(1)keywords site:example.com

使用site来将搜索结果定位到example.com内

(2)1 usd=?rmb

我经常使用这个搜索式子来查看汇率,当然,你还可以使用154rmb=?hkd这样的搜索式子

(3)北京天气

查询天气预报的最快方法

(4)搜索手机归属地

在google搜索框直接输入手机号,第一条结果即为手机归属地

3、有https尽量使用https

由于GFW的存在,Google的服务是经常被重置的。使用Https方式能有效避过GFW。如果一个服务提供有https方式访问,建议尽量使用https方式,经常使用的提供https方式的Google服务是:

4、使用Gmail集中管理其它所有Email

毫无疑问,Gmail是最好用的邮箱之一。然而,相信很多人和我一样,Gmail并不是我们第一个邮箱,登录多个邮箱查收邮件是比较麻烦的

在“Gmail实用技巧3则”里,我已经详细介绍了如何使用Gmail来接收其它邮箱邮件的方法,这里不再阐述。

5、在Gmail里使用Twitter

Twitter非常非常流行,在“Twitter进阶手册”里我介绍了一些Twitter客户端, 后来,我发现了这个非常有趣的Twitter Gmail Gadget,可以在Gmail里直接使用Twitter,非常方便。

使用方法是,现在Gmail labs里启动Gadget(Add any gadget by URL)功能,接着在Gadget里填入如下地址:

按提示进行下一步操作即可。

6、将Google当作代理服务器来使用

这是一个可能导致Google App Engines被屏蔽的做法,请慎用。

Google App Engines平台允许开发者在App Engines上免费搭建应用程序,于是有人开发了基于App Engines的代理服务器程序:GAppProxy

使用Google作为代理服务器的好处是显而易见的:

(1)不管是教育网还是公网,都可以直连Google

(2)被屏蔽的几率较低

(3)速度有保障

(4)自己代理自己管理,不受制于其他人

具体的使用和安装方法这里不作介绍,你可以参看小众软件的搭建教程

还是那句话,翻墙工具请慎用

7、生成自定义搜索

很多网站提供站内搜索功能,比如可能吧,你能在页面右顶部看到搜索框。每次进行搜索都要打开这个网站是非常麻烦的,这时你可以考虑一下安装Google工具栏,然后在搜索框里右击,选择“生成自定义搜索”。

之后,工具栏上会生成这个网站的搜索按钮,在工具栏输入关键词,点击该按钮即可进行站内搜索。

这是我使用自定义搜索工具生成的一些快捷搜索按钮:

8、使用英文搜索图片

经常有人问我博客文章里的图片哪里来,除了一部分是截图之外,其它大多数是在Google搜索的。我的搜索图片步骤是这样的:

(1)将搜索对象用英语描述

(2)使用和搜索对象相似、意义相同的单词来搜索

比如,在“去世后网络帐户和关系怎么办”里使用的图片,我使用的关键词不是"die",而是"disappear"。

9、其它相关技巧

下面的技巧之前用单篇文章来介绍过,有兴趣的朋友可以点击详细阅读。

(1)善用Google日历,让事情完成得更高效

(2)关于Picasa你可以不知道的功能

(3)Gmail的8个技巧

(4)使用Google Sync来同步手机通信录和Gmail通信录

二、网站/博客相关

1、使用Google Docs创建在线调查表单

我刚刚邀请了Twitter上的朋友做了“可能吧”读者调查,有兴趣的朋友可以协助填写这份匿名的调查

这份调查就是使用Google Docs来制作的。新建一个Form:

接着设置相关的调查内容即可。

使用Google Docs创建在线调查表的优势在于,表单数据是即时更新的,你能在Docs后台看到数据在不断变化,第二是调查结果非常直观,这是可能吧读者调查的结果。第三是调查表可以嵌入到网页里

2、使用Google Chart API生成图表

这是我经常使用的一个Google API。

制作图表是比较麻烦的,Google提供了快捷生成图表的API,对于大多数人来说,使用起来并不复杂,因为只需在URL里填写一下参数。可能吧读者调查结果里的图表都是用Chart API生成的。

这是一个最简单的生成图表URL:

http://chart.apis.google.com/chart?cht=p3&chd=t:77,23&chs=250×100&chl=yes|no

生成的图片是这样的:

更多详细的配置请参考Google的帮助文档

3、调用Google 的javascript库

Google将一些常用的Javascript库存放到自己服务器,并免费提供外部调用,使网站主节省一定的开销。这些Javascript库包括jQuery等流行库。你可以在Google Code上找到使用方式

4、获取博客反链信息

如果你在写博客,想必你会很想知道有哪些博客链接到了你的博客。这时你可以使用Google博客搜索,搜索类似link:www.kenengba.com这样的式子,然后点击左侧的RSS或Atom,在阅读器里它们。

接下来,你就可以在阅读器里看到博客的反链情况了:

5、用Google CSE替代博客内部搜索

对于Wordpress来说,站内搜索的功能是十分糟糕的,不但匹配度差,搜索结果不会按照权重排列,同时也会消耗数据库资源

如果你的博客被Google收录良好,可以尝试使用Google CSE来替代博客的内置搜索,可能吧07年就开始这么做了。

使用Google CSE除了能解决前面提到的WP内置搜索的缺点外,还可以和Google Adsense结合,如果有人点击里搜索结果里的广告,你可以获得广告分成。

6、Google Analytics的高级群体功能

Google Analytics的高级群体是一个十分优秀的功能,它允许你将一部分访客抽取出来,观察这部分访客的浏览情况。

比如,你可以看看“使用Google搜索到达自己网站并且使用Firefox浏览器的人”,和“使用Google搜索到达自己网站并且使用IE浏览器的人”的人的区别,你可以在Analytics里创建这两个高级群体,然后将它们应用到数据中并进行比较。

这是可能吧的“IE浏览者”和“Firefox浏览者”群体的“网站停留时间”比较:

三、告诉我们你使用的Google技巧

如果你有更好的使用Google服务的技巧,不妨告诉我们,让大家都可以提高办事效率。

水煮互联网创业

鞋厂理论:世界上有无数家鞋厂,制造着各自的鞋子,销售给各自的客户。

在网络上,当某个生意已经有人在做的时候,就想想皮鞋理论,你会发现:在大多数情况下,即使有很多人在做鞋子,也并不意味着你就不能再去做鞋子了,别人做了耐克,你可以做李宁,不行就做安踏啥的,即使不知名的杂牌也在三线城市卖的不错。

如果其他的鞋厂都在赚钱,那么你也有机会在这个市场里分一杯羹;如果其他鞋厂都在亏钱,那么你要想办法把他们亏掉的钱赚到自己手上。把成本、产品、 服务、渠道、营销都做好,你就有机会超过现有的竞争对手。赚钱的生意,往往都是已经有很多人都在做的生意。如果某种生意只有你一个人在做,也许说明你的生 意没法赚钱,所以没人看得上。

杂货店理论:很多大型的卖场或公司,比如沃尔玛、八佰伴、麦当劳等,最初都是从一家小店起家的,从小蚂蚁逐渐做到巨无霸。

在网络上,很多人相信,在没有VC的时候,公司亏钱是正常的,等某一天拿了巨额的VC,扩大规模、全国连锁,就肯定会赚钱,于是公司的核心团队把时 间精力都花在了各类投资经理身上。这时候,就该想想杂货店理论,如果你经营一家小杂货店却一直亏钱,那么,如果有人帮你做到了7-11那样的全球连锁,你 会亏得更多。

除去那些具有技术革命性的公司(比如3G、云计算、光存储啥的),在大部分情况下,一个好的公司、或者说一个好的商业模式,如果在大范围内可以赚 钱,那么缩小到一个小范围去运营,也应该是赚钱的。这样的公司,尽管前期需要少量的初始资本和时间来配置人员、软硬件,但绝不会把自己的未来寄托在虚无缥 缈的巨额投资和全球扩张上。沉浸在VC幻想里的孩子们,不如先去经营个杂货店,会比见VC学到更多东西。

户口本悖论:警察局有当地所有居民的户口档案,但是警察局能从中赚钱么?

在网络上,很多人都把“抓用户”作为唯一的追求(或者作为前几年的唯一追求),而忽略了构建真正可行的健康的盈利模式。这时候,你就该想想户口本理 论:警察局拥有那么多用户的详细资料,详细到血型、电话和住址门牌号,你的网站能比警察局更牛逼么?如果你以为靠那点用户的email就能赚钱的话,警察 局早就可以去纳斯达克了。

当然,我不否认一定基数的用户的确是赚钱的重要条件之一,但是光养用户、不思现金流是没有意义的。有很多手持几百万注册用户的网站还看不到任何赚钱 的希望,而有些才几万人的小站却每天有稳健的现金入账。所以,如果赚不到钱的话,建议别再到处炫耀有xx百万用户了,搞那么多用户还不赚钱,只能证明两个 字:无能。

沸水理论:把水煮沸后,看上去热气腾腾,但水的总量不会增加,而且需要供热成本。

在网络上,很多人不择手段地去追求用户的“活跃度”,却不考虑活跃度到底能带来什么收益。活跃度本质上有两种:跟业务相关的活跃度,比如经常上淘宝 看流行商品的活跃用户,一般来说会增加购买的几率;另一种则是与业务无关的活跃度,假设淘宝搞了个跟购物无关的免费网游,结果每天有几百万人上线来玩(产 品经理可以报上很漂亮的activation rate和retention rate),但这些人单纯迷恋网游的人转去淘宝购物的机会有多大呢?由网游带来的收益是否能超过开发和维护网游服务器的成本呢?没人知道。

这时候想想一桶沸水,为了维持一个看上去热腾腾的活跃度,你需要不断添柴、加火,这些供暖成本很高的,而由此产生的热气却无法增加额外的水量,那么 还要煮沸它做什么呢。特蕾莎修女说,一个人的逝去是个悲剧,而一群人的逝去只是一个数字。 在网络上,当我们看到一群人的活跃是个漂亮数字的时候,应该去看看每个人活跃的背后到底意味着什么价值。

热水器理论:有很多人愿意花钱购买热水器,也有很多人愿意花钱维修出故障的热水器。

在网络上,很多人相信,如果一个网络产品不是人们的必需品,那么就很难收费。的确,网络上的用户已经习惯了免费的生活,正如人们习惯了免费的空气、 免费的马路一样。这个时候你就该想想热水器理论,热水器也不是生活必需品,人们完全可以洗免费的冷水澡,甚至不洗澡,为啥家家都有一台动辄上千元的热水器 呢?

很简单,因为人类有意愿追求高质量的生活体验(包括但不限于洗澡),而热水器没有更廉价的替代品。如果你的网络产品或服务能够给人们带来真正高质量的生活体验,同时又没有廉价的替代品,那么一样有人愿意付钱。比如,我很愿意为Gmail的手机客户端付钱,很愿意为Pandora的在线音乐付钱,很愿意为Yeeyan的高质量译文付钱,当然也愿意为Tucia的设计服务付钱。跟我一样的人还有很多,请不要对互联网绝望。

油条铺现象:如果你去跟街上卖油条、卖煎饼的师傅聊一聊,你会发现他们每月的收入很稳定,有的甚至可以月入几万。

网上总说创业99%会失败,什么九死一生,什么倾家荡产都用来形容创业者。这时候,想想卖油条煎饼的创业者,人家在街边随便摆个三轮车,就能养活一 家人了。再去看看大街上的餐厅、奶茶铺、手机配件店、杂货店、床上用品店。。。。为什么这些创业者大部分都活得好好的?而号称IT创业精英的大学生反而一 分钱都赚不到?

如果把“能够养活一家人”作为最低成功标准的话,那么大街上的普通人的创业成功率超过80%,而我们还用“创业九死一生、失败也正常”来安慰自己的无能,真他妈窝囊!

2009年5月3日星期日

让图片快速被搜索引擎收录的方法

看到对手的公司图片在网上到处可见,我也想让我们公司的图片可以各大搜索引擎上找到,尤其是百度。在ALT标签里加上图片的描述,这样可以被百度搜到,但是需要不短的时间。

今天发现一个可以让百度快速收录图片的方法:

在 百度空间的相册里建立一个专辑,专辑名和专辑的简介要认真的填写,然后上传你想要被搜索引擎收录的图片,图片的名称也要认真填写(可以填写关键词)。然后 过一天或两天(我是在两天后去搜的)你再去百度图片里搜索就能搜到了。(可以在图片上加上自己的网址,公司名称等信息,这样更有利于宣传)

新浪博客可以让博文快速被收录,但是图片却很难被收录。

其它的博客就更不用说了,就算能被搜索引擎收到,但也需要一段很长的时间。

2009年4月29日星期三

伪静态URL重写技术实现方法

伪静态用到知识很简单一旦学会,快乐无穷,只需要正则和服务器设置。
先说iis如何设置吧,往下看
下载(IIS Rewrite模块): http://www.isapirewrite.com/,先把产品下载下来,安装在服务器上,记住目录,会有类似Rewrite.dll的文件生成,MMC→IIS信息服务管理器→网站→您的站点→属性,在“ISAPI筛选器”项点击 “添加”, 筛选器名称填入Rewrite,可执行文件为Rewrite.dl这个文件.

然后修改httpd.ini配置文件,如果不太熟悉,就在http://www.isapirewrite.cn/docs看看手册,研究去,如此:

[ISAPI_Rewrite]
CacheClockRate 3600
RewriteRule ^(.*)/([a-z0-9A-Z\-]+\.html)$ $1/default.asp\?id=$2

这个配置好了就能在default.asp获取参数了,没问题把,顺便一说,正则用法里面最重要的符号^匹配开头,$匹配结尾,\w匹配任何字符,\s匹配空白,+匹配至少一,*匹配至少0,[x,]匹配至少x,()是分组技术,汗,这东西不说了,太弱了.



下面说apache(Unix平台最流行的WEB服务器平台)的重写技术,基本类似,只不过,apaceh支持更灵活的.htaccess,你创建一个文件,文件名就是.htaccess:内容:


RewriteEngine On
RewriteRule ^([a-z0-9A-Z\-]+\.html)$ default.php\?id=$1



就这样,搞定之.注意,必须要空间支持 Rewrite 以及对站点目录中 .htaccess 的文件解析,才有效.

如何让空间支持Rewrite 和 .htaccess 的文件解析呢 往下看

第一步:我们要找到apache(Unix平台最流行的WEB服务器平台)安装目录下的httpd.cof文件,在里面找到


Options FollowSymLinks
AllowOverride none

把none改all,

第二步:找到一下内容

#LoadModule rewrite_module modules/mod_rewrite.so

改为

LoadModule rewrite_module modules/mod_rewrite.so

第三步就是最困难的,保存重启apache(Unix平台最流行的WEB服务器平台)了。 需要自己用心研究了。

剩下的就是测试了。。以上设置我都测试通过了。

2009年4月26日星期日

php smarty简单的例子

在招聘网站上经常看到招PHP程序员的公司很多都要求会SMARTY,虽然我对SMARTY没有太多好感(主要还是太过繁琐,没有直接写PHP代码来得直接),但似乎它已经成了一个事实上的标准,且在团队合作中也有必要用到,没法,学习学习吧,先从简单的开始:

实例1:

先来看一个简单的例子。
=====================================================
index.tpl
=====================================================
{* 显示是smarty变量识符里的用*包含的文字为注释内容 *}
{include file="header.tpl"}{*页面头*}
大家好,我叫{$name}, 欢迎大家阅读我的smarty学习材料。
{include file="foot.tpl"}{*页面尾*}
上边的这个例子是一个tpl模板,其中:

1. {**}是模板页的注释,它在smarty对模板进行解析时不进行任何输出,仅供模板设计师对模板进行注释。
2. {include file="xxx.tpl"}使用此句将一个模板文件包含到当前页面中,例子中将在网站中公用事的head.tpl与foot.tpl进行了包含,你可以这样想,使用这一句将xxx.tpl中的内容全部复制在当前语句处。当然,你不使用这一句也可以,将XXX.tpl中的内容复制到当前语句处也是完全可以了。
3.{$name}: 模板变量,smarty中的核心组成,采用smarty定义的左边界符{与右边界符}包含着、以PHP变量形式给出,在smarty程序中将使用$smarty->assign("name", "疯癫";将模板中的$name替换成“疯癫”三个字。

整个实例源程序如下:
=============================
header.tpl
=============================
<html>
<head>
<title>smarty教程</title>
</head>
<body>

===============================
foot.tpl
===============================
<hr>
<center> CopyRight(C) by 2007年12月</center>
<hr>
</body>
</html>

=====================================================
index.tpl
=====================================================
{* 显示是smarty变量识符里的用*包含的文字为注释内容 *}
{include file="header.tpl"}{*页面头*}
大家好,我叫{$name}, 欢迎大家阅读我的smarty学习材料。
{include file="foot.tpl"}{*页面尾*}

================================================
index.php
================================================
<?php
include_once("./comm/Smarty.class.php"); //包含smarty类文件
$smarty = new Smarty(); //建立smarty实例对象$smarty
$smarty->templates("./templates"); //设置模板目录
$smarty->templates_c("./templates_c"); //设置编译目录
//----------------------------------------------------
//左右边界符,默认为{},但实际应用当中容易与JavaScript
//相冲突,所以建议设成<{}>或其它。
//----------------------------------------------------
$smarty->left_delimiter = "{";
$smarty->right_delimiter = "}";
$smarty->assign("name", "疯癫"); //进行模板变量替换
//编译并显示位于./templates下的index.tpl模板
$smarty->display("index.tpl");
?>;

最终执行这个程序时将显示为:
================================
执行index.php
================================
<html>
<head>
<title>smarty教程</title>
</head>
<body>

大家好,我叫疯癫, 欢迎大家阅读我的smarty学习材料。
<hr>
<center> CopyRight(C) by 2007年12月</center>
<hr>
</body>
</html>

the second part

这个例子是综合使用smarty模板参数的一个例子,这些参数用来控制模板的输出,我只选其中几个,其它的参数你去看参考吧。

================================================
exmple2.tpl
================================================
<html>
<head><title>smarty示例2</title></head>
<body>

1. 第一句首字母要大写:{$str1|capitalize}<br>
2. 第二句模板变量 + 疯癫:{$str2|cat:"疯癫"}<br>
3. 第三句输出当前日期:{$str3|date_format:"%Y年%m月%d日"}
4. 第四句.php程序中不处理,它显示默认值:{$str4|default:"没有值!"}
5. 第五句要让它缩进8个空白字母位,并使用"*"取替这8个空白字符:<br>
{$str5|indent:8:"*"}}<br>
6. 第六句把hd_lj@163.com全部变为小写:{$str6|lower}<br>
7. 第七句把变量中的Crazy Hand替换成:疯癫:{$str7|replace:"Crazy Hand":"疯癫"}<br>
8. 第八句为组合使用变量修改器:{$str8|capitalize|cat:"这里是新加的时间:"|date_format:"%Y年%m月%d日"|lower}

</body>
</html>

===============================================
example2 .php
===============================================
<?php
include_once("./Smarty.class.php"); //包含smarty类文件
$smarty = new Smarty(); //建立smarty实例对象$smarty
$smarty->templates("./templates"); //设置模板目录
$smarty->templates_c("./templates_c"); //设置编译目录

//----------------------------------------------------
//左右边界符,默认为{},但实际应用当中容易与JavaScript
//相冲突,所以建议设成<{}>或其它。
//----------------------------------------------------

$smarty->left_delimiter = "{";
$smarty->right_delimiter = "}";
$smarty->assign("str1", "my name is Crazy Hand."); //将str1替换成My Name Is Crazy Hand.
$smarty->assign("str2", "我的名字叫:"); //输出: 我的名字叫:疯癫

$smarty->assign("str3", "公元"); //输出公元2008年X月X日(我的当前时间)

//$smarty->assign("str4", ""); //第四句不处理时会显示默认值,如果使用前面这一句则替换为""
$smarty->assign("str5", "前边8个*"); //第五句输出:********前边8个*
$smarty->assign("str6", "hd_lj@163.com"); //这里将输出hd_lj@163.com
$smarty->assign("str7", "this is Crazy Hand"); //在模板中显示为:this is 疯癫
$smarty->assign("str8", "HERE IS COMBINING:");

//编译并显示位于./templates下的index.tpl模板
$smarty->display("example2.tpl");
?>

最终输出效果:
======================================================
example2.php输出效果:
======================================================
<html>
<head><title>smarty示例2</title></head>
<body>

1. 第一句首字母要大写:My Name Is Crazy Hand.<br>
2. 第二句模板变量 + 疯癫:我的名字叫:疯癫<br>
3. 第三句输出当前日期:公元2008年X月X日<br>
4. 第四句.php程序中不处理,它显示默认值:没有值!<br>
5. 第五句要让它缩进8个空白字母位,并使用"*"取替这8个空白字符:<br>
********前边8个*<br>
6. 第六句把hd_lj@163.com全部变为小写:hd_lj@163.com<br>
7. 第七句把变量中的Crazy Hand替换成:疯癫:this is 疯癫<br>
8. 第八句为组合使用变量修改器:Here is Combining:这里是新加的时间:2008年X月X日
</body>
</html>



2009年4月24日星期五

[转]header 函式的使用

标头 (header) 是服务器以 HTTP 协义传 HTML 资料到浏览器前所送出的字串,在标头
与 HTML 文件之间尚需空一行分隔。有关 HTTP 的详细说明,可以参 RFC 2068 官方文件
(http://www.w3.org/Protocols/rfc2068/rfc2068)。在 PHP 中送回 HTML 资料前,需先
传完所有的标头。

注意: 传统的标头一定包含下面三种标头之一,并只能出现一次。

Content-Type: xxxx/yyyy
Location: xxxx:yyyy/zzzz
Status: nnn xxxxxx

在新的多型标头规格 (Multipart MIME) 方可以出现二次以上。

使用范例

范例一: 本例使浏览器重定向到 PHP 的官方网站。
Header("Location: http://www.php.net");
exit;


范例二: 要使用者每次都能得到最新的资料,而不是 Proxy 或 cache 中的资料,可以使用下列的标头
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");


范例三: 让使用者的浏览器出现找不到档案的信息。
header("Status: 404 Not Found");


范例四:让使用者下载档案。

header("Content-type: application/x-gzip");
header("Content-Disposition: attachment; filename=文件名");
header("Content-Description: PHP3 Generated Data");

2009年4月21日星期二

不可不知的生活中18个有用潜规则

人情世故是我们日常生活中积累的约定俗成的行为规则,属于社会知识的范畴。这些知识大半来源于与不同人群的社会交际,也来源于社会冲突与社会发展。在有专业知识与技能的情况下,人情世故能够帮助我们个人缓和与其他人之间的紧张度,也比较容易让其他人感到与我们交往的愉悦感与适度感。这里例举出对于我们每个人也许都能用到的日常生活中的18个人情世故,而这些人情世故也经常被很多年轻人忽略。

1、即使不是大人物,我们也经常能用请教的态度与口吻与他们说话,因为人不可貌相,很多实用的良师益友往往来自不起眼的生活与工作中。

2、在吃饭的场合做主动做点菜者,不适合请主人与主宾点菜,因为那不是尊贵者通常做的事情,但是请注意询问他们的喜好,而不是只管点自己爱吃的东西。但是这需要平时研究菜单,积累点菜的经验。

3、经常找到朋友、伙伴与同事(甚至小孩子)值得肯定的方面,注意哦,即使老板也需要被你肯定,但是尽量在私下场合,而对于一般朋友与同时则应公开赞扬。

4、在受到别人对自己的相貌、事情、人品赞扬时,不要表现出理所当然的样子,也不要假意否认,合适的方式是表示感谢,尤其感谢朋友的肯定与支持。

5、学会使用便条,包括借条、领条、请假条、申请信,如果你很主动地使用这些便条会让其他人感到你很规范,而且如果你懂得请其他人这样做,你和未来更好与他们有凭有据地与他们打交道。会写便条会让别人刮目相看。

6、即使你不是服务人员,在朋友或者同事有客人开的时候主动倒水,会让朋友与同事很有面子,也会让客人觉得你的朋友与同事很有威望。这会让你的朋友与同事特别感谢你的姿态。

7、虽然你觉得你是新手或者地位比较低的人,但是你要勇于不耻下问,也要做到主动询问别人的需要,而不要等领导或者资深的同事对你表现出亲和,因为他们这样表现往往需要特别的努力。

8、记得在别人不在座位的时候很热情地帮助接听与记录电话、接受信件、传递信息,对团队的同事与同学,提醒他们一些你知道的重要日程。

9、在征询了别人意见之后才进入别人的房间,看别人的书架或者室内物品,在经别人同意的情况下才用别人的电脑,坐在别人的私人座位上,但通常不去翻动别人的笔记本。

10、出席别人需要有邀请,如果不能出席应提前通知,迟到的话要在适当的时间点上通知主人,到了以后要解释,带未经邀请的朋友要事前通知主人。

11、不适合向别人索要礼物,收到别人的礼品不管是不是喜欢要表示感谢,因为送礼者会很在乎你的反应,不适合把一处的礼物转送给另一处,尤其还保留原来送礼者的符号与痕迹就显得很没有礼貌了。

12、在有多个出席者的场合,主动介绍自己的朋友给其他人,或者主动在你认识的朋友之间穿针引线。

13、有不同地位的朋友在的场合,都要保持微笑,体贴地招呼下那些内向的、不为人注意的、可能有点自卑感的朋友,在社交中对弱势者的帮助会得到别人特别的感激。在其他社会场合,对于社会地位较低者,尤其在有你不能适应的生活条件与生活习惯时,要克制自己所想表现出的不适感与负面表情。尽量主动向社会地位较低者打招呼。

14、有好东西吃的时候不要吃独食,主动地告诉他们你知道的好消息,在有好事情的时候能想到别人。

15、有人做错了事情或者你发现其他做错了事情,不要用情绪性的方式批评别人,尤其要注意就事来评价,避免评价了别人的人格、个性与家庭教养。批评时能提出解决方案,批评就更有建设性。也不要只有批评,批评不忘肯定别人的长处。如果批评时能比较幽默,往往负面效果就更少。被批评或者遇到尴尬的时候能幽默自嘲,也能提高交流的建设性。

16、好汉不吃眼前亏。但是在另外很多时候,如果问题争执不下,也不要继续火上浇油,冷静下来,多收集一些数据材料与想更明白点再说。

17、在你不能有充分把握的时候,用“争取”与“尽量”这样的口吻回答别人的邀约,承诺了就要最大限度去履行。

18、虽然在商言商,但是我们要尽量不谈回报地先为别人做点什么,这样就赢得了在心理上比别人优越的债权感。一个人的社会地位是别人对他负有的社会债务感的总和。

2009年4月17日星期五

[转]PHP:Snoopy抓取页面以及模拟提交表单

snoopy是一个很好的远程抓取类库,在淘宝的开放API中也有用到,不过自己也还不是很熟悉,所以先摘录下来,以备日后验证使用。

PHP代码


<?php
$url = "http://www.taoav.com";
include("snoopy.php");
$snoopy = new Snoopy;
$snoopy->fetch($url); //获取所有内容
echo $snoopy->results; //显示结果
//可选以下
$snoopy->fetchtext //获取文本内容(去掉html代码)
$snoopy->fetchlinks //获取链接
$snoopy->fetchform //获取表单
?>

表单提交


<?php
$formvars["username"] = "admin";
$formvars["pwd"] = "admin";

$action = "http://www.taoav.com";//表单提交地址
$snoopy->submit($action,$formvars);//$formvars为提交的数组
echo $snoopy->results; //获取表单提交后的 返回的结果
//可选以下
$snoopy->submittext; //提交后只返回 去除html的 文本
$snoopy->submitlinks;//提交后只返回 链接
?>

既然已经提交的表单 那就可以做很多事情 接下来我们来伪装ip,伪装浏览器

伪装


<?php
$formvars["username"] = "admin";
$formvars["pwd"] = "admin";
$action = "http://www.taoav.com";
include "snoopy.php";
$snoopy = new Snoopy;
$snoopy->cookies["PHPSESSID"] = 'fc106b1918bd522cc863f36890e6fff7'; //伪装sessionid
$snoopy->agent = "(compatible; MSIE 4.01; MSN 2.5; AOL 4.0; Windows 98)"; //伪装浏览器
$snoopy->referer = http://www.php100.com; //伪装来源页地址 http_referer
$snoopy->rawheaders["Pragma"] = "no-cache"; //cache 的http头信息
$snoopy->rawheaders["X_FORWARDED_FOR"] = "127.0.0.101"; //伪装ip
$snoopy->submit($action,$formvars);
echo $snoopy->results;
?>

原来我们可以伪装session 伪装浏览器 ,伪装ip, haha 可以做很多事情了。例如 带验证码,验证ip 投票, 可以不停的投。ps:这里伪装ip ,其实是伪装http头, 所以一般的通过 REMOTE_ADDR 获取的ip是伪装不了,反而那些通过http头来获取ip的(可以防止代理的那种) 就可以自己来制造ip。

关于如何验证码 ,简单说下:

首先用普通的浏览器, 查看页面 , 找到验证码所对应的sessionid,同时记下sessionid和验证码值,接下来就用snoopy去伪造 。

原理:由于是同一个sessionid 所以取得的验证码和第一次输入的是一样的。

有时我们可能需要伪造更多的东西,snoopy完全为我们想到了


<?php
$snoopy->proxy_host = "www.php100.com";
$snoopy->proxy_port = "8080"; //使用代理
$snoopy->maxredirs = 2; //重定向次数
$snoopy->expandlinks = true; //是否补全链接 在采集的时候经常用到
// 例如链接为 /images/taoav.gif 可改为它的全链接 http://www.taoav.com/images/taoav.gif
$snoopy->maxframes = 5 //允许的最大框架数
//注意抓取框架的时候 $snoopy->results 返回的是一个数组
$snoopy->error //返回报错信息
?>

ASP编程常用的代码

1. ASP与Access数据库连接:


<%
dim conn,mdbfile
mdbfile=server.mappath("数据库名称.mdb")
set conn=server.createobject("adodb.connection")
conn.open "driver={microsoft access driver (*.mdb)};uid=admin;pwd=数据库密码;dbq="&mdbfile
%>

2. ASP与SQL数据库连接:


<%
dim conn
set conn=server.createobject("ADODB.connection")
con.open "PROVIDER=SQLOLEDB;DATA SOURCE=SQL服务器名称或IP地址;UID=sa;PWD=数据库密码;DATABASE=数据库名称
%>

建立记录集对象:


set rs=server.createobject("adodb.recordset")
rs.open SQL语句,conn,3,2

3. SQL常用命令使用方法:

1) 数据记录筛选:


sql="select * from 数据表 where 字段名=字段值 order by 字段名 "
sql="select * from 数据表 where 字段名 like ‘%字段值%‘ order by 字段名 "
sql="select top 10 * from 数据表 where 字段名 order by 字段名 "
sql="select * from 数据表 where 字段名 in (‘值1‘,‘值2‘,‘值3‘)"
sql="select * from 数据表 where 字段名 between 值1 and 值2"

(2) 更新数据记录:


sql="update 数据表 set 字段名=字段值 where 条件表达式"
sql="update 数据表 set 字段1=值1,字段2=值2 …… 字段n=值n where 条件表达式"

(3) 删除数据记录:


sql="delete from 数据表 where 条件表达式"
sql="delete from 数据表" (将数据表所有记录删除)

(4) 添加数据记录:


sql="insert into 数据表 (字段1,字段2,字段3 …) valuess (值1,值2,值3 …)"
sql="insert into 目标数据表 select * from 源数据表" (把源数据表的记录添加到目标数据表)

(5) 数据记录统计函数:


AVG(字段名) 得出一个表格栏平均值
COUNT(*|字段名) 对数据行数的统计或对某一栏有值的数据行数统计
MAX(字段名) 取得一个表格栏最大的值
MIN(字段名) 取得一个表格栏最小的值
SUM(字段名) 把数据栏的值相加

引用以上函数的方法:


sql="select sum(字段名) as 别名 from 数据表 where 条件表达式"
set rs=conn.excute(sql)

用 rs("别名") 获取统的计值,其它函数运用同上。

(5) 数据表的建立和删除:

CREATE TABLE 数据表名称(字段1 类型1(长度),字段2 类型2(长度) …… )

例:CREATE TABLE tab01(name varchar(50),datetime default now())

DROP TABLE 数据表名称 (永久性删除一个数据表)

(6) 记录集对象的方法:


rs.movenext 将记录指针从当前的位置向下移一行
rs.moveprevious 将记录指针从当前的位置向上移一行
rs.movefirst 将记录指针移到数据表第一行
rs.movelast 将记录指针移到数据表最后一行
rs.absoluteposition=N 将记录指针移到数据表第N行
rs.absolutepage=N 将记录指针移到第N页的第一行
rs.pagesize=N 设置每页为N条记录
rs.pagecount 根据 pagesize 的设置返回总页数
rs.recordcount 返回记录总数
rs.bof 返回记录指针是否超出数据表首端,true表示是,false为否
rs.eof 返回记录指针是否超出数据表末端,true表示是,false为否
rs.delete 删除当前记录,但记录指针不会向下移动
rs.addnew 添加记录到数据表末端
rs.update 更新数据表记录

判断所填数据是数字型


if not isNumeric(request("字段名称")) then
response.write "不是数字"
else
response.write "数字"
end if

2009年4月13日星期一

如何自定义ucenter、discuz用户列表?

UCENTER修改:

1、格式化日期 我不喜欢UCENTER的那个日期格式,想替换掉,方法如下:找到control\admin\user.php这个文件,搜索function _format_userlist(&$userlist)这个函数,把$userlist[$key]['regdate'] = $this->date($user['regdate']);替换成$userlist[$key]['regdate'] = date("Y-m-d H:i",$user['regdate']); OK,问题解决。 

2、按日期排序 其实方法也很简单,同样是user.php这个文件,找到$sqladd = $sqladd ? " WHERE 1 $sqladd" : '';这段语句,在下边增加: $sqladd = $sqladd . "order by regdate desc"; OK,问题解决。

想增加其它列表,只要参考上面的方式加以扩展就行了。


给DISCUZ后台的用户列表增加日期并以日期排序:

涉及文件:admin/members.inc.php 
操作方法:
1、找到46行,把:
$query = $db->query("SELECT uid, username, adminid, groupid, credits, regdate, extcredits1, extcredits2,
   extcredits3, extcredits4, extcredits5, extcredits6, extcredits7, extcredits8, posts FROM {$tablepre}members WHERE $conditions LIMIT $start_limit, $memberperpage");
改成
$query = $db->query("SELECT uid, username, adminid, groupid, credits, regdate, extcredits1, extcredits2,
   extcredits3, extcredits4, extcredits5, extcredits6, extcredits7, extcredits8, posts FROM {$tablepre}members WHERE $conditions order by regdate desc LIMIT $start_limit, $memberperpage");
2、找到73行,把:
showsubtitle(array('', 'username', 'credits', 'posts', 'admingroup', 'usergroup', ''));
改成
showsubtitle(array('', 'username','regdate', 'credits', 'posts', 'admingroup', 'usergroup', ''));
3、不要忘记给模板文件中的admincp.lang.php中增加一个regdate=>'注册时间';的字段哦。

2009年4月8日星期三

在discuz7.0正式版的注册页面上加入QQ必选字段

经客户要求,要在discuz7.0正式版的注册页面上加上QQ必选字段,到discuz的论坛里找了半天也没找到一个合适的,然后就自己研究起来,discuz的代码真够错综复杂的,不过,还是出了结果,具体修改方法如下:

涉及到的四个文件:templates/你的模板文件夹/register.htm;templates/你的模板文件夹/messages.lang.php;ajax.php;register.php

register.htm

找到如下代码:


<label><em>{lang email}:</em><input type="text" name="email" autocomplete="off" size="25" id="email" onBlur="checkemail()" tabindex="1" class="txt" /> *</label>

在它下面添加:


<!-- 增加QQ注册 -->
<label><em>QQ:</em><input type="text" id="qq" name="qq" onBlur="checkqq()" autocomplete="off" size="25" maxlength="15" value="" tabindex="1" class="txt" /> *</label>

并在文件低部加一个js的QQ验证函数:


//验证QQ
function checkqq() {
var qq = trim($('qq').value);
if(qq == '' || qq == lasteqq) {
return;
} else {
lastqq = qq;
}
ajaxget('ajax.php?infloat=register&handlekey=register&action=checkqq&qq=' + qq, 'returnmessage4');
}

register.php

找到如下代码:


$db->query("REPLACE INTO {$tablepre}memberfields (uid, authstr $fieldadd1) VALUES ('$uid', '$authstr' $fieldadd2)");

改成:


$db->query("REPLACE INTO {$tablepre}memberfields (uid, qq, authstr $fieldadd1) VALUES ('$uid', '$qq', '$authstr' $fieldadd2)");

ajax.php

找到:


elseif($action == 'checkemail') {

$email = trim($email);

require_once DISCUZ_ROOT.'./uc_client/client.php';

$ucresult = uc_user_checkemail($email);
if($ucresult == -4) {
showmessage('profile_email_illegal', '', 1);
} elseif($ucresult == -5) {
showmessage('profile_email_domain_illegal', '', 1);
} elseif($ucresult == -6) {
showmessage('profile_email_duplicate', '', 1);
}
}

在它下面添加一个QQ验证方法:


///验证QQ
elseif($action == 'checkqq') {
$qq = trim($qq);
$len = strlen($qq);
if(!preg_match( "/^[0-9]+$/",$qq) or $len<5 ){
showmessage('profile_qq_duplicate', '', 1);
}
}

messages.lang.php

添加一行:


'profile_qq_duplicate' => 'QQ号必须为数字,且不小于 5 位数',

2009年4月1日星期三

8个最常用的PHP服务器变量

PHP的超级全局变量名 $_SERVER 是一个数组,这个数组里的很多变量对于你的PHP项目是非常有用的,在这里,我打算介绍一些你在进行PHP项目开发时最常用的几个变量。


8个最常用的PHP服务器变量

1) $_SERVER['REQUEST_URI'] - 它返回一个URL中的文件名和参数,如果你的URL是“http://www.example.com/product.php?id=5”,那么,$_SERVER['REQUEST_URI']将返回“/product.php?id=5″.

2) $_SERVER['DOCUMENT_ROOT'] - 返回服务器提供服务的根目录。在Linux里,这个变量通常返回类似于“/usr/yoursite/www”这样的路径名,在Windows里则返回“D:/xamps/xampp/htdocs” 这样的路径名。

3) $_SERVER['HTTP_HOST'] - 返回http头部的服务器名称。当你通过地址栏访问类似于“http://example.com”或“http://www.example.com”时这个变量通常分别返回“example.com”或者“www.example.com”。这个变量对于你起用PHP的Session时,可以有效判断对方是进入到“http://example.com”还是“http://www.example.com”.

4) $_SERVER['HTTP_USER_AGENT'] - 返回客户端用户浏览器信息。我们可以通过strpos($_SERVER["HTTP_USER_AGENT"],”MSIE”)来验证是否是IE或者通过strpos($_SERVER["HTTP_USER_AGENT"],”Firefox”)来验证是否是Firefox。

5) $_SERVER['PHP_SELF'] - 返回当前你的文件名及目录。当你访问的URL地址是“http://www.example.com/product.php?id=5”,那么$_SERVER['PHP_SELF']返回“/product.php”,而如果你访问的是“http://www.example.com/abc/product.php?id=5”,则返回“/abc/product.php”。

6) $_SERVER['QUERY_STRING'] - 返回当前URL的查询参数。URL查询参数是指“?”号之后的字符串。如果你当前的URL是“http://www.example.com/index.php?id=5&page=product”,那么它将返回“id=5&page=product”。

7) $_SERVER['REMOTE_ADDR'] - 返回当前你访问的页面的远程服务器地址。但你不能通过$_SERVER['REMOTE_ADDR']变量来取得当前客户端的IP地址。

8 ) $_SERVER['SCRIPT_FILENAME'] - 返回当前你访问页面在服务器端的绝对路径。它返回的路径在Linux主机里类似“var/example.com/www/product.php”,在Windows里类似“D:/xampp/xampp/htdocs/test/example.php”。

能掌握好以上基于$_SERVER的八个变量,相信对你的PHP项目来说,又简化了好多!

2009年3月31日星期二

通过js实现DIV随机排列

最新帮深圳北大青鸟的网站做一个随机实现公司网址排名的JS脚本,原来用的是sort方法,但这种方法实现起来最终会导致最后的DIV出现在第一个的频率达50%,无法公平、公正。以下我写的代码实现了公平、公正原则,呵呵,秀一下。

<HTML><HEAD><TITLE>深圳北大青鸟/北大青鸟/电脑学校/IT培训/培训/计算机学校</TITLE>
<META http-equiv=Content-Type content=\\\"text/html; charset=gb2312\\\">
<META content=深圳北大青鸟是北大青鸟电脑学校专业做IT培训的计算机学校 name=description>
<META content=深圳北大青鸟,北大青鸟,电脑学校,IT培训,培训,计算机学校 name=keywords>
<STYLE type=text/css>
.body {
FONT-SIZE: 12px; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif,宋体
}
TABLE {
FONT-SIZE: 12px; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif,宋体
}
TD {
FONT-SIZE: 12px; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif,宋体
}
A {
COLOR: #000; TEXT-DECORATION: none
}
A:hover {
COLOR: #000; BOTTOM: 1px; POSITION: relative; TEXT-DECORATION: none; outline: none
}
A:unknown {
outline: none
}
A:visited {
outline: none
}
.STYLE1 {
FONT-WEIGHT: bold; COLOR: #ff0000
}
#main {
WIDTH: 680px
}
#main DIV {
MARGIN-TOP: 0px; FLOAT: left; MARGIN-LEFT: 0px; WIDTH: 680px
}
DIV TABLE {
WIDTH: 100%
}
body {
margin-left: 0px;
margin-top: 0px;
margin-right: 0px;
margin-bottom: 0px;
}
</STYLE>

<SCRIPT type=text/javascript charset=GB2312>

function arrRand(obj){
var a = new Array();
var x = new Array();
for(var i = 0;i < obj;i++){
a[i] = i + 1;
}
for(var i=0; i<obj;i++){
x[i] = a.splice (Math.floor (Math.random () * a.length) , 1);
}
return x;
}

function randTable(){
var c = arrRand(len);
for(var k = 0;k < len;k ++){
divs[c[k] - 1].innerHTML = b[k];
}
}

var b = new Array();
var divs = new Object;
var len;

window.onload = function(){
divs = document.getElementById(\\\"main\\\").getElementsByTagName(\\\"div\\\");
len = divs.length;
for(var j = 0;j < len;j++){
b[j] = divs[j].innerHTML;
}
randTable();
}
</SCRIPT>

<META content=\\\"MSHTML 6.00.2900.3492\\\" name=GENERATOR></HEAD>
<BODY bgColor=transparent>
<DIV id=main>

<DIV>
<TABLE cellSpacing=0 cellPadding=0 width=\\\"100%\\\" border=0>
<TBODY>
<TR>
<TD height=28><A title=罗湖(软件)校区 href=\\\"http://www.0755accp.com/\\\"
target=_blank><SPAN
class=STYLE1>罗湖(软件)校区:</SPAN>深圳市罗湖区宝安北路桃园商业大厦7楼南区(罗湖人才市场旁)</A></TD>
</TR></TBODY></TABLE></DIV>
<DIV>
<TABLE cellSpacing=0 cellPadding=0 width=\\\"100%\\\" border=0>
<TBODY>
<TR>
<TD height=28><A title=地王书城(软件)校区 href=\\\"http://www.benet-wh.com.cn/\\\"
target=_blank><SPAN
class=STYLE1>地王书城(软件)校区:</SPAN>深圳市罗湖区宝安南路嘉宾花园四楼(地王大厦斜对面,深圳书城旁)</A></TD>
</TR></TBODY></TABLE></DIV>
<DIV>
<TABLE cellSpacing=0 cellPadding=0 width=\\\"100%\\\" border=0>
<TBODY>
<TR>
<TD height=28><A title=福田华强北(软件)校区 href=\\\"http://www.sz-aptech.com/\\\" target=_blank><SPAN
class=STYLE1>福田华强北(软件)校区:</SPAN>深圳市深南中路爱华大厦14楼(华强北兴华宾馆西侧)</A></TD>
</TR></TBODY></TABLE></DIV>
<DIV>
<TABLE cellSpacing=0 cellPadding=0 width=\\\"100%\\\" border=0>
<TBODY>
<TR>
<TD height=28><A title=福田(网络)校区 href=\\\"http://www.sz-aptech.com/\\\"
target=_blank><SPAN
class=STYLE1>福田(网络)校区:</SPAN>深圳市深南中路爱华电脑大厦5楼(华强北兴华宾馆西侧)</A></TD>
</TR></TBODY></TABLE></DIV>
<DIV>
<TABLE cellSpacing=0 cellPadding=0 width=\\\"100%\\\" border=0>
<TBODY>
<TR>
<TD height=28><A title=宝安(软件)校区 href=\\\"http://www.szaptech.com.cn\\\"
target=_blank><SPAN
class=STYLE1>宝安(软件)校区:</SPAN>深圳市宝安区25区商业步行街华丰时代广场5楼(海雅百货旁)</A></TD>
</TR>
</TBODY>
</TABLE>
</DIV>
<DIV>
<TABLE cellSpacing=0 cellPadding=0 width=\\\"100%\\\" border=0>
<TBODY>
<TR>
<TD height=28><A title=南山科技园(网络)校区 href=\\\"http://www.sz-benet.net\\\"
target=_blank><SPAN
class=STYLE1>南山科技园(网络)校区:</SPAN>深圳市南山区科技园深南花园C座三楼</A></TD>
</TR></TBODY></TABLE></DIV>
<DIV>
<TABLE cellSpacing=0 cellPadding=0 width=\\\"100%\\\" border=0>
<TBODY>
<TR>
<TD height=28><A title=南头(网络)校区 href=\\\"http://www.szaptech.com.cn/\\\"
target=_blank><SPAN
class=STYLE1>南头(网络)校区:</SPAN>深圳市南山区南头南新天桥钰龙园D座3楼(国美电器旁)</A></TD>
</TR></TBODY></TABLE></DIV>
<DIV>
<TABLE cellSpacing=0 cellPadding=0 width=\\\"100%\\\" border=0>
<TBODY>
<TR>
<TD height=28><A title=福田(测试)校区 href=\\\"http://www.sz-aptech.com\\\"
target=_blank><SPAN
class=STYLE1>福田(测试)校区:</SPAN>深圳市福田区深南中路核电大厦三楼(深圳华强北兴华宾馆对面)</A></TD>
</TR></TBODY></TABLE></DIV>
<DIV>
<TABLE cellSpacing=0 cellPadding=0 width=\\\"100%\\\" border=0>
<TBODY>
<TR>
<TD height=28><A title=南山(测试)校区 href=\\\"http://www.sz-test.com\\\"
target=_blank><SPAN
class=STYLE1>南山(测试)校区:</SPAN>深圳市南山区科技园南区创维大厦A座17楼</A></TD>
</TR>
</TBODY>
</TABLE>
</DIV>
<DIV>
<TABLE cellSpacing=0 cellPadding=0 width=\\\"100%\\\" border=0>
<TBODY>
<TR>
<TD height=28><A title=南山深圳大学(软件)校区 href=\\\"http://www.sz-accp.net/\\\"
target=_blank><SPAN
class=STYLE1>南山深圳大学(软件)校区:</SPAN>深圳市南山区学府路西部电子时代广场四楼(深圳大学旁)</A></TD>
</TR></TBODY></TABLE></DIV>
</DIV>
</BODY>
</HTML>

2009年3月26日星期四

PHP+Apache在Windows上的安装配置

该方法目前主要针对php5.2.6 + apache2.2.9,不过我想,更高的版本也应该适用,其中apache使用的Window安装版本,php使用的是zip版本。


具体如下:
1、Apatech安装(由于是自动安装版,就不多说了,一直下一步,过程中适当配置一下就OK)

2、PHP安装 -> 解压 -> 更改extension_dir = “./”为extension_dir = “D:/PHP/PHP/ext” -> 设置环境变量(PHP目录与PHP ext目录[;D:\phpserver\php;D:\phpserver\php\ext]) -> 开启想要的扩展

设置检索目录 DirectoryIndex index.php index.html

#************************************
# apatech2.2.9
#************************************
PHPIniDir "e:/phpserver/php"   //实际路径需要自己修改
LoadModule php5_module "e:/phpserver/php/php5apache2_2.dll"  //实际路径需要自己修改
addType application/x-httpd-php .php

php.ini配置内容(增加Xdebug功能):
************************************************************
[Xdebug]
extension=php_xdebug-2.0.3-5.2.5.dll
xdebug.auto_trace=on
xdebug.collect_params=on
xdebug.collect_return=on
xdebug.trace_output_dir=E:\phpdebug //日志输出文件夹
xdebug.profiler_enable=on
xdebug.profiler_output_dir=E:\phpdebug //日志输出文件夹

*************************************************************

Apache显示目录httpd.conf配置方法:
#去掉Indexes则不显示目录
Options Indexes FollowSymLinks
AllowOverride None
Order deny,allow
Allow from all

其它说明:
1、关于“You don't have permission to access / on this server.”的错误处理:
配置文件:
Options FollowSymLinks
AllowOverride None
Order deny,allow
deny from all
Satisfy all
然后试着把deny from all中的deny改成了allow,保存后重起了apache,然后再一测试我的网页,哈哈!居然问题就出在这,访问测试网站完全正常了。

2、要用rewrite去掉index.php,需要把 AllowOverride None 改成 AllowOverride all。
同时启用rewrite模块,并写.htaccess这个文件:
RewriteEngine on
RewriteCond $1 !^(index\.php|images|styles|javascripts|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]

注意第二行的images|sytles|javascripts|,要加上它进行过滤才能正确获得相关目录的链接
去掉Kohana配置文件中的:$config['index_page'] = 'index.php'; 为 $config['index_page'] = '';



PDO参数说明

因为自己PHPCORE的核心框架是用PDO进行数据库驱动的,所以,对于它的一些基本配置参数必须有一定的了解,以下是收集到部分内容,供日后参考使用:


(备注:PDO是一个“数据库访问抽象层”,作用是统一各种数据库的访问接口,与mysql和mysqli的函数库相比,PDO让跨数据库的使用更具有亲和力;与ADODB和MDB2相比,PDO更高效。目前而言,实现“数据库抽象层”任重而道远,使用PDO这样的“数据库访问抽象层”是一个不错的选择。 )



PDO->beginTransaction() — 标明回滚起始点 
PDO->commit() — 标明回滚结束点,并执行SQL 
PDO->__construct() — 建立一个PDO链接数据库的实例 
PDO->errorCode() — 获取错误码 
PDO->errorInfo() — 获取错误的信息 
PDO->exec() — 处理一条SQL语句,并返回所影响的条目数 
PDO->getAttribute() — 获取一个“数据库连接对象”的属性 
PDO->getAvailableDrivers() — 获取有效的PDO驱动器名称 
PDO->lastInsertId() — 获取写入的最后一条数据的主键值 
PDO->prepare() — 生成一个“查询对象” 
PDO->query() — 处理一条SQL语句,并返回一个“PDOStatement” 
PDO->quote() — 为某个SQL中的字符串添加引号 
PDO->rollBack() — 执行回滚 
PDO->setAttribute() — 为一个“数据库连接对象”设定属性 
PDOStatement->bindColumn() — Bind a column to a PHP variable 
PDOStatement->bindParam() — Binds a parameter to the specified variable name 
PDOStatement->bindValue() — Binds a value to a parameter 
PDOStatement->closeCursor() — Closes the cursor, enabling the statement to be executed again. 
PDOStatement->columnCount() — Returns the number of columns in the result set 
PDOStatement->errorCode() — Fetch the SQLSTATE associated with the last operation on the statement handle 
PDOStatement->errorInfo() — Fetch extended error information associated with the last operation on the statement handle 
PDOStatement->execute() — Executes a prepared statement 
PDOStatement->fetch() — Fetches the next row from a result set 
PDOStatement->fetchAll() — Returns an array containing all of the result set rows 
PDOStatement->fetchColumn() — Returns a single column from the next row of a result set 
PDOStatement->fetchObject() — Fetches the next row and returns it as an object. 
PDOStatement->getAttribute() — Retrieve a statement attribute 
PDOStatement->getColumnMeta() — Returns metadata for a column in a result set 
PDOStatement->nextRowset() — Advances to the next rowset in a multi-rowset statement handle 
PDOStatement->rowCount() — Returns the number of rows affected by the last SQL statement 
PDOStatement->setAttribute() — Set a statement attribute 
PDOStatement->setFetchMode() — Set the default fetch mode for this statement 

从函数列表可以看出,操作基于不同的对象,“PDO”表示的是一个数据库连接对象(new PDO产生),“PDOStatement”表示的是一个查询对象(PDO->query()产生)或者是一个结果集对象(PDO->prepare()产生)。 
一个“数据库连接对象”的例子,返回“PDO”: 
$dbh = new PDO('mysql:host=localhost;dbname=test', 'root', ''); 
?> 

一个“查询对象”的例子,返回“PDOStatement”: 
$sql = "Insert INTO `test`.`table` (`name` ,`age`)VALUES (?, ?);"; 
$stmt = $dbh->prepare($sql); 
?> 

一个“结果集对象”的例子,返回“PDOStatement”: 
$sql = "Select * FROM `table` Where `name` = 'samon'"; 
$stmt = $dbh->query($sql); 
?> 

在test库里面生成table表,并写入一些数据: 
$dbh = new PDO('mysql:host=localhost;dbname=test', 'root', ''); 
$dbh->query('set names utf8;'); 

$sql = " 
Drop TABLE IF EXISTS `table`; 
Create TABLE `test`.`table` ( 
`id` INT( 10 ) NOT NULL AUTO_INCREMENT PRIMARY KEY, 
`name` VARCHAR( 255 ) NOT NULL , 
`age` VARCHAR( 255 ) NOT NULL 
) ENGINE = InnoDB DEFAULT CHARSET=utf8; 
Insert INTO `test`.`table` (`name` ,`age`)VALUES ('samon', '27'); 
Insert INTO `test`.`table` (`name` ,`age`)VALUES ('leo', '26'); 
Insert INTO `test`.`table` (`name` ,`age`)VALUES ('ben', '28'); 
"; 
$dbh->query($sql); 
?> 

PDO->exec()方法的作用是处理一条SQL语句,并返回所影响的条目数。 

PDO->query()方法的作用是处理一条SQL语句,并返回一个“PDOStatement”。 

PDO->prepare()方法的作用是生成一个“查询对象”。 

PDO->lastInsertId()方法的作用是获取写入的最后一条数据的主键值。 
$dbh = new PDO('mysql:host=localhost;dbname=test', 'root', ''); 
$dbh->query('set names utf8;'); 

$sql = "Insert INTO `test`.`table` (`name` ,`age`)VALUES ('mick', 22);"; 
$dbh->query($sql); 
$lid = $dbh->lastInsertId($sql); 
print_r($lid); // 显示主键的值 
?> 

PDO->quote()方法的作用是为某个SQL中的字符串添加引号。PDO->quote()方法有两个参数,第一个参数是字符串,第二个参数表示参数的类型。 

PDO->getAttribute()方法的作用是获取一个“数据库连接对象”的属性。PDO->setAttribute()方法的作用是为一个“数据库连接对象”设定属性。 
// 修改默认的错误显示级别 
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); 
?> 

属性列表: 
PDO::PARAM_BOOL 
    表示一个布尔类型 
PDO::PARAM_NULL 
    表示一个SQL中的NULL类型 
PDO::PARAM_INT 
    表示一个SQL中的INTEGER类型 
PDO::PARAM_STR 
    表示一个SQL中的SQL CHAR,VARCHAR类型 
PDO::PARAM_LOB 
    表示一个SQL中的large object类型 
PDO::PARAM_STMT 
    表示一个SQL中的recordset类型,还没有被支持 
PDO::PARAM_INPUT_OUTPUT 
    Specifies that the parameter is an INOUT parameter for a stored procedure. You must bitwise-OR this value with an explicit PDO::PARAM_* data type. 
PDO::FETCH_LAZY 
    将每一行结果作为一个对象返回 
PDO::FETCH_ASSOC 
    仅仅返回以键值作为下标的查询的结果集,名称相同的数据只返回一个 
PDO::FETCH_NAMED 
    仅仅返回以键值作为下标的查询的结果集,名称相同的数据以数组形式返回 
PDO::FETCH_NUM 
    仅仅返回以数字作为下标的查询的结果集 
PDO::FETCH_BOTH 
    同时返回以键值和数字作为下标的查询的结果集 
PDO::FETCH_OBJ 
    以对象的形式返回结果集 
PDO::FETCH_BOUND 
    将PDOStatement::bindParam()和PDOStatement::bindColumn()所绑定的值作为变量名赋值后返回 
PDO::FETCH_COLUMN 
    表示仅仅返回结果集中的某一列 
PDO::FETCH_CLASS 
    表示以类的形式返回结果集 
PDO::FETCH_INTO 
    表示将数据合并入一个存在的类中进行返回 
PDO::FETCH_FUNC 
PDO::FETCH_GROUP 
PDO::FETCH_UNIQUE 
PDO::FETCH_KEY_PAIR 
    以首个键值下表,后面数字下表的形式返回结果集 
PDO::FETCH_CLASSTYPE 
PDO::FETCH_SERIALIZE 
    表示将数据合并入一个存在的类中并序列化返回 
PDO::FETCH_PROPS_LATE 
    Available since PHP 5.2.0 
PDO::ATTR_AUTOCOMMIT 
    在设置成true的时候,PDO会自动尝试停止接受委托,开始执行 
PDO::ATTR_PREFETCH 
    设置应用程序提前获取的数据大小,并非所有的数据库哦度支持 
PDO::ATTR_TIMEOUT 
    设置连接数据库超时的值 
PDO::ATTR_ERRMODE 
    设置Error处理的模式 
PDO::ATTR_SERVER_VERSION 
    只读属性,表示PDO连接的服务器端数据库版本 
PDO::ATTR_CLIENT_VERSION 
    只读属性,表示PDO连接的客户端PDO驱动版本 
PDO::ATTR_SERVER_INFO 
    只读属性,表示PDO连接的服务器的meta信息 
PDO::ATTR_CONNECTION_STATUS 
PDO::ATTR_CASE 
    通过PDO::CASE_*中的内容对列的形式进行操作 
PDO::ATTR_CURSOR_NAME 
    获取或者设定指针的名称 
PDO::ATTR_CURSOR 
    设置指针的类型,PDO现在支持PDO::CURSOR_FWDONLY和PDO::CURSOR_FWDONLY 
PDO::ATTR_DRIVER_NAME 
    返回使用的PDO驱动的名称 
PDO::ATTR_ORACLE_NULLS 
    将返回的空字符串转换为SQL的NULL 
PDO::ATTR_PERSISTENT 
    获取一个存在的连接 
PDO::ATTR_STATEMENT_CLASS 
PDO::ATTR_FETCH_CATALOG_NAMES 
    在返回的结果集中,使用自定义目录名称来代替字段名。 
PDO::ATTR_FETCH_TABLE_NAMES 
    在返回的结果集中,使用自定义表格名称来代替字段名。 
PDO::ATTR_STRINGIFY_FETCHES 
PDO::ATTR_MAX_COLUMN_LEN 
PDO::ATTR_DEFAULT_FETCH_MODE 
    Available since PHP 5.2.0 
PDO::ATTR_EMULATE_PREPARES 
    Available since PHP 5.1.3. 
PDO::ERRMODE_SILENT 
    发生错误时不汇报任何的错误信息,是默认值 
PDO::ERRMODE_WARNING 
    发生错误时发出一条php的E_WARNING的信息 
PDO::ERRMODE_EXCEPTION 
    发生错误时抛出一个PDOException 
PDO::CASE_NATURAL 
    回复列的默认显示格式 
PDO::CASE_LOWER 
    强制列的名字小写 
PDO::CASE_UPPER 
    强制列的名字大写 
PDO::NULL_NATURAL 
PDO::NULL_EMPTY_STRING 
PDO::NULL_TO_STRING 
PDO::FETCH_ORI_NEXT 
    获取结果集中的下一行数据,仅在有指针功能时有效 
PDO::FETCH_ORI_PRIOR 
    获取结果集中的上一行数据,仅在有指针功能时有效 
PDO::FETCH_ORI_FIRST 
    获取结果集中的第一行数据,仅在有指针功能时有效 
PDO::FETCH_ORI_LAST 
    获取结果集中的最后一行数据,仅在有指针功能时有效 
PDO::FETCH_ORI_ABS 
    获取结果集中的某一行数据,仅在有指针功能时有效 
PDO::FETCH_ORI_REL 
    获取结果集中当前行后某行的数据,仅在有指针功能时有效 
PDO::CURSOR_FWDONLY 
    建立一个只能向后的指针操作对象 
PDO::CURSOR_SCROLL 
    建立一个指针操作对象,传递PDO::FETCH_ORI_*中的内容来控制结果集 
PDO::ERR_NONE (string) 
    设定没有错误时候的错误信息 
PDO::PARAM_EVT_ALLOC 
    Allocation event 
PDO::PARAM_EVT_FREE 
    Deallocation event 
PDO::PARAM_EVT_EXEC_PRE 
    Event triggered prior to execution of a prepared statement. 
PDO::PARAM_EVT_EXEC_POST 
    Event triggered subsequent to execution of a prepared statement. 
PDO::PARAM_EVT_FETCH_PRE 
    Event triggered prior to fetching a result from a resultset. 
PDO::PARAM_EVT_FETCH_POST 
    Event triggered subsequent to fetching a result from a resultset. 
PDO::PARAM_EVT_NORMALIZE 
    Event triggered during bound parameter registration allowing the driver to normalize the parameter name. 

PDO->getAvailableDrivers()方法的作用是获取有效的PDO驱动器名称。 

PDO->errorInfo()方法的作用获取错误的信息,PDO->errorCode()方法的作用是获取错误码。 
$dbh = new PDO('mysql:host=localhost;dbname=test', 'root', ''); 
$dbh->query('set names utf8;'); 
$sql = "Insert INTO `test`.`table` (`name` ,`ageeeeee`)VALUES ('mick', 22);"; 
$dbh->query($sql); 
print_r($dbh->errorInfo()); 
/** 
* Array 
* ( 
*     [0] => 42S22 
*     [1] => 1054 
*     [2] => Unknown column 'ageeeeee' in 'field list' 
* ) 
*/ 
?> 

PDO->__construct()方法的作用是建立一个PDO链接数据库的实例。 

PDO->beginTransaction(),PDO->commit(),PDO->rollBack()这三个方法是在支持回滚功能时一起使用的。PDO->beginTransaction()方法标明起始点,PDO->commit()方法标明回滚结束点,并执行SQL,PDO->rollBack()执行回滚。 
try { 
    $dbh = new PDO('mysql:host=localhost;dbname=test', 'root', ''); 
    $dbh->query('set names utf8;'); 
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

    $dbh->beginTransaction(); 
    $dbh->exec("Insert INTO `test`.`table` (`name` ,`age`)VALUES ('mick', 22);"); 
    $dbh->exec("Insert INTO `test`.`table` (`name` ,`age`)VALUES ('lily', 29);"); 
    $dbh->exec("Insert INTO `test`.`table` (`name` ,`age`)VALUES ('susan', 21);"); 
    $dbh->commit(); 
     
} catch (Exception $e) { 
    $dbh->rollBack(); 
    echo "Failed: " . $e->getMessage(); 
?> 

2009年3月24日星期二

优化PHP代码的42条建议

在网上看到了《优化PHP代码的42条建议》,对于我的PHP代码优化很有帮助,现摘录下来,好好看看:


1.如果一个方法可静态化,就对它做静态声明。速率可提升至4倍。

2.echo 比 print 快。

3.使用echo的多重参数(译注:指用逗号而不是句点)代替字符串连接。

4.在执行for循环之前确定最大循环数,不要每循环一次都计算最大值。

5.注销那些不用的变量尤其是大数组,以便释放内存。

6.尽量避免使用__get,__set,__autoload。

7.require_once()代价昂贵。

8.在包含文件时使用完整路径,解析操作系统路径所需的时间会更少。

9.如果你想知道脚本开始执行(译注:即服务器端收到客户端请求)的时刻,使用$_SERVER[‘REQUEST_TIME’]要好于time()。

10.函数代替正则表达式完成相同功能。

11.str_replace函数比preg_replace函数快,但strtr函数的效率是str_replace函数的四倍。

12.如果一个字符串替换函数,可接受数组或字符作为参数,并且参数长度不太长,那么可以考虑额外写一段替换代码,使得每次传递参数是一个字符,而不是只写一行代码接受数组作为查询和替换的参数。

13.使用选择分支语句(译注:即switch case)好于使用多个if,else if语句。

14.用@屏蔽错误消息的做法非常低效。

15.打开apache的mod_deflate模块。

16.数据库连接当使用完毕时应关掉。

17.$row[‘id’]的效率是$row[id]的7倍。

18.错误消息代价昂贵。

19.尽量不要在for循环中使用函数,比如for ($x=0; $x <>

20.在方法中递增局部变量,速度是最快的。几乎与在函数中调用局部变量的速度相当。

21.递增一个全局变量要比递增一个局部变量慢2倍。

22.递增一个对象属性(如:$this->prop++)要比递增一个局部变量慢3倍。

23.递增一个未预定义的局部变量要比递增一个预定义的局部变量慢9至10倍。

24.仅定义一个局部变量而没在函数中调用它,同样会减慢速度(其程度相当于递增一个局部变量)。PHP大概会检查看是否存在全局变量。

25.方法调用看来与类中定义的方法的数量无关,因为我(在测试方法之前和之后都)添加了10个方法,但性能上没有变化。

26.派生类中的方法运行起来要快于在基类中定义的同样的方法。

27.调用带有一个参数的空函数,其花费的时间相当于执行7至8次的局部变量递增操作。类似的方法调用所花费的时间接近于15次的局部变量递增操作。

28.用单引号代替双引号来包含字符串,这样做会更快一些。因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会。当然,只有当你不需要在字符串中包含变量时才可以这么做。

29.输出多个字符串时,用逗号代替句点来分隔字符串,速度更快。注意:只有echo能这么做,它是一种可以把多个字符串当作参数的“函数”(译注:PHP手册中说echo是语言结构,不是真正的函数,故把函数加上了双引号)。

30.Apache解析一个PHP脚本的时间要比解析一个静态HTML页面慢2至10倍。尽量多用静态HTML页面,少用脚本。

31.除非脚本可以缓存,否则每次调用时都会重新编译一次。引入一套PHP缓存机制通常可以提升25%至100%的性能,以免除编译开销。

32.尽量做缓存,可使用memcached。memcached是一款高性能的内存对象缓存系统,可用来加速动态Web应用程序,减轻数据库负载。对运算码 (OP code)的缓存很有用,使得脚本不必为每个请求做重新编译。

33.当操作字符串并需要检验其长度是否满足某种要求时,你想当然地会使用strlen()函数。此函数执行起来相当快,因为它不做任何计算,只返回在 zval 结构(C的内置数据结构,用于存储PHP变量)中存储的已知字符串长度。但是,由于strlen()是函数,多多少少会有些慢,因为函数调用会经过诸多步骤,如字母小写化(译注:指函数名小写化,PHP不区分函数名大小写)、哈希查找,会跟随被调用的函数一起执行。在某些情况下,你可以使用isset() 技巧加速执行你的代码。

(举例如下)
if (strlen($foo) < style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">(与下面的技巧做比较)
if (!isset($foo{5})) { echo “Foo is too short”$$ }

调用isset()恰巧比strlen()快,因为与后者不同的是,isset()作为一种语言结构,意味着它的执行不需要函数查找和字母小写化。也就是说,实际上在检验字符串长度的顶层代码中你没有花太多开销。

34.当执行变量$i的递增或递减时,$i++会比++$i慢一些。这种差异是PHP特有的,并不适用于其他语言,所以请不要修改你的C或Java代码并指望它们能立即变快,没用的。++$i更快是因为它只需要3条指令(opcodes),$i++则需要4条指令。后置递增实际上会产生一个临时变量,这个临时变量随后被递增。而前置递增直接在原值上递增。这是最优化处理的一种,正如Zend的PHP优化器所作的那样。牢记这个优化处理不失为一个好主意,因为并不是所有的指令优化器都会做同样的优化处理,并且存在大量没有装配指令优化器的互联网服务提供商(ISPs)和服务器。

35.并不是事必面向对象(OOP),面向对象往往开销很大,每个方法和对象调用都会消耗很多内存。

36.并非要用类实现所有的数据结构,数组也很有用。

37.不要把方法细分得过多,仔细想想你真正打算重用的是哪些代码?

38.当你需要时,你总能把代码分解成方法。

39.尽量采用大量的PHP内置函数。

40.如果在代码中存在大量耗时的函数,你可以考虑用C扩展的方式实现它们。

41.评估检验(profile)你的代码。检验器会告诉你,代码的哪些部分消耗了多少时间。Xdebug调试器包含了检验程序,评估检验总体上可以显示出代码的瓶颈。

42.mod_zip可作为Apache模块,用来即时压缩你的数据,并可让数据传输量降低80%。

2009年3月22日星期日

mysql的字符串函数

MYSQL对字符串的支持是非常强大的,很多功能直接写一段MYSQL语句就能实现,不用再写PH代码操作,以下列出一些相关函数及其用法,以备参考:


ASCII(str)
    返回字符串str的最左面字符的ASCII代码值。如果str是空字符串,返回0。如果str是NULL,返回NULL。

    mysql> select ASCII('2');
            -> 50
    mysql> select ASCII(2);
            -> 50
    mysql> select ASCII('dx');
            -> 100

    也可参见ORD()函数。
ORD(str)
    如果字符串str最左面字符是一个多字节字符,通过以格式((first byte ASCII code)*256+(second byte ASCII code))[*256+third byte ASCII code...]返回字符的ASCII代码值来返回多字节字符代码。如果最左面的字符不是一个多字节字符。返回与ASCII()函数返回的相同值。

    mysql> select ORD('2');
            -> 50
     

CONV(N,from_base,to_base)
    在不同的数字基之间变换数字。返回数字N的字符串数字,从from_base基变换为to_base基,如果任何参数是NULL,返回NULL。参数N解释为一个整数,但是可以指定为一个整数或一个字符串。最小基是2且最大的基是36。如果to_base是一个负数,N被认为是一个有符号数,否则,N被当作无符号数。 CONV以64位点精度工作。

    mysql> select CONV("a",16,2);
            -> '1010'
    mysql> select CONV("6E",18,8);
            -> '172'
    mysql> select CONV(-17,10,-18);
            -> '-H'
    mysql> select CONV(10+"10"+'10'+0xa,10,10);
            -> '40'
     

BIN(N)
    返回二进制值N的一个字符串表示,在此N是一个长整数(BIGINT)数字,这等价于CONV(N,10,2)。如果N是NULL,返回NULL。

    mysql> select BIN(12);
            -> '1100'

OCT(N)
    返回八进制值N的一个字符串的表示,在此N是一个长整型数字,这等价于CONV(N,10,8)。如果N是NULL,返回NULL。

    mysql> select OCT(12);
            -> '14'
     

HEX(N)
    返回十六进制值N一个字符串的表示,在此N是一个长整型(BIGINT)数字,这等价于CONV(N,10,16)。如果N是NULL,返回NULL。

    mysql> select HEX(255);
            -> 'FF'
     

CHAR(N,...)
    CHAR()将参数解释为整数并且返回由这些整数的ASCII代码字符组成的一个字符串。NULL值被跳过。

    mysql> select CHAR(77,121,83,81,'76');
            -> 'MySQL'
    mysql> select CHAR(77,77.3,'77.3');
            -> 'MMM'
     

CONCAT(str1,str2,...)
    返回来自于参数连结的字符串。如果任何参数是NULL,返回NULL。可以有超过2个的参数。一个数字参数被变换为等价的字符串形式。

    mysql> select CONCAT('My', 'S', 'QL');
            -> 'MySQL'
    mysql> select CONCAT('My', NULL, 'QL');
            -> NULL
    mysql> select CONCAT(14.3);
            -> '14.3'

LENGTH(str)
      
OCTET_LENGTH(str)
      
CHAR_LENGTH(str)
      
CHARACTER_LENGTH(str)
    返回字符串str的长度。

    mysql> select LENGTH('text');
            -> 4
    mysql> select OCTET_LENGTH('text');
            -> 4

    注意,对于多字节字符,其CHAR_LENGTH()仅计算一次。
LOCATE(substr,str)
      
POSITION(substr IN str)
    返回子串substr在字符串str第一个出现的位置,如果substr不是在str里面,返回0.

    mysql> select LOCATE('bar', 'foobarbar');
            -> 4
    mysql> select LOCATE('xbar', 'foobar');
            -> 0

    该函数是多字节可靠的。  

LOCATE(substr,str,pos)
    返回子串substr在字符串str第一个出现的位置,从位置pos开始。如果substr不是在str里面,返回0。

    mysql> select LOCATE('bar', 'foobarbar',5);
            -> 7

    这函数是多字节可靠的。
INSTR(str,substr)
    返回子串substr在字符串str中的第一个出现的位置。这与有2个参数形式的LOCATE()相同,除了参数被颠倒。

    mysql> select INSTR('foobarbar', 'bar');
            -> 4
    mysql> select INSTR('xbar', 'foobar');
            -> 0

    这函数是多字节可靠的。
LPAD(str,len,padstr)
    返回字符串str,左面用字符串padstr填补直到str是len个字符长。

    mysql> select LPAD('hi',4,'??');
            -> '??hi'
     

RPAD(str,len,padstr)
    返回字符串str,右面用字符串padstr填补直到str是len个字符长。  

    mysql> select RPAD('hi',5,'?');
            -> 'hi???'

LEFT(str,len)
    返回字符串str的最左面len个字符。

    mysql> select LEFT('foobarbar', 5);
            -> 'fooba'

    该函数是多字节可靠的。
RIGHT(str,len)
    返回字符串str的最右面len个字符。

    mysql> select RIGHT('foobarbar', 4);
            -> 'rbar'

    该函数是多字节可靠的。
SUBSTRING(str,pos,len)
      
SUBSTRING(str FROM pos FOR len)
      
MID(str,pos,len)
    从字符串str返回一个len个字符的子串,从位置pos开始。使用FROM的变种形式是ANSI SQL92语法。

    mysql> select SUBSTRING('Quadratically',5,6);
            -> 'ratica'

    该函数是多字节可靠的。
SUBSTRING(str,pos)
      
SUBSTRING(str FROM pos)
    从字符串str的起始位置pos返回一个子串。

    mysql> select SUBSTRING('Quadratically',5);
            -> 'ratically'
    mysql> select SUBSTRING('foobarbar' FROM 4);
            -> 'barbar'

    该函数是多字节可靠的。
SUBSTRING_INDEX(str,delim,count)
    返回从字符串str的第count个出现的分隔符delim之后的子串。如果count是正数,返回最后的分隔符到左边(从左边数) 的所有字符。如果count是负数,返回最后的分隔符到右边的所有字符(从右边数)。

    mysql> select SUBSTRING_INDEX('www.mysql.com', '.', 2);
            -> 'www.mysql'
    mysql> select SUBSTRING_INDEX('www.mysql.com', '.', -2);
            -> 'mysql.com'

    该函数对多字节是可靠的。
LTRIM(str)
    返回删除了其前置空格字符的字符串str。

    mysql> select LTRIM('  barbar');
            -> 'barbar'

RTRIM(str)
    返回删除了其拖后空格字符的字符串str。

    mysql> select RTRIM('barbar   ');
            -> 'barbar'

    该函数对多字节是可靠的。  

TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)
    返回字符串str,其所有remstr前缀或后缀被删除了。如果没有修饰符BOTH、LEADING或TRAILING给出,BOTH被假定。如果remstr没被指定,空格被删除。

    mysql> select TRIM('  bar   ');
            -> 'bar'
    mysql> select TRIM(LEADING 'x' FROM 'xxxbarxxx');
            -> 'barxxx'
    mysql> select TRIM(BOTH 'x' FROM 'xxxbarxxx');
            -> 'bar'
    mysql> select TRIM(TRAILING 'xyz' FROM 'barxxyz');
            -> 'barx'

    该函数对多字节是可靠的。
SOUNDEX(str)
    返回str的一个同音字符串。听起来“大致相同”的2个字符串应该有相同的同音字符串。一个“标准”的同音字符串长是4个字符,但是SOUNDEX()函数返回一个任意长的字符串。你可以在结果上使用SUBSTRING()得到一个“标准”的 同音串。所有非数字字母字符在给定的字符串中被忽略。所有在A-Z之外的字符国际字母被当作元音。

    mysql> select SOUNDEX('Hello');
            -> 'H400'
    mysql> select SOUNDEX('Quadratically');
            -> 'Q36324'
     

SPACE(N)
    返回由N个空格字符组成的一个字符串。

    mysql> select SPACE(6);
            -> '      '
     

REPLACE(str,from_str,to_str)
    返回字符串str,其字符串from_str的所有出现由字符串to_str代替。

    mysql> select REPLACE('www.mysql.com', 'w', 'Ww');
            -> 'WwWwWw.mysql.com'

    该函数对多字节是可靠的。
REPEAT(str,count)
    返回由重复countTimes次的字符串str组成的一个字符串。如果count <= 0,返回一个空字符串。如果str或count是NULL,返回NULL。

    mysql> select REPEAT('MySQL', 3);
            -> 'MySQLMySQLMySQL'
     

REVERSE(str)
    返回颠倒字符顺序的字符串str。

    mysql> select REVERSE('abc');
            -> 'cba'

    该函数对多字节可靠的。
INSERT(str,pos,len,newstr)
    返回字符串str,在位置pos起始的子串且len个字符长得子串由字符串newstr代替。

    mysql> select INSERT('Quadratic', 3, 4, 'What');
            -> 'QuWhattic'

    该函数对多字节是可靠的。
ELT(N,str1,str2,str3,...)
    如果N= 1,返回str1,如果N= 2,返回str2,等等。如果N小于1或大于参数个数,返回NULL。ELT()是FIELD()反运算。

    mysql> select ELT(1, 'ej', 'Heja', 'hej', 'foo');
            -> 'ej'
    mysql> select ELT(4, 'ej', 'Heja', 'hej', 'foo');
            -> 'foo'

FIELD(str,str1,str2,str3,...)
    返回str在str1, str2, str3, ...清单的索引。如果str没找到,返回0。FIELD()是ELT()反运算。

    mysql> select FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');
            -> 2
    mysql> select FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo');
            -> 0

FIND_IN_SET(str,strlist)
    如果字符串str在由N子串组成的表strlist之中,返回一个1到N的值。一个字符串表是被“,”分隔的子串组成的一个字符串。如果第一个参数是一个常数字符串并且第二个参数是一种类型为SET的列,FIND_IN_SET()函数被优化而使用位运算!如果str不是在strlist里面或如果strlist是空字符串,返回0。如果任何一个参数是NULL,返回NULL。如果第一个参数包含一个“,”,该函数将工作不正常。

    mysql> SELECT FIND_IN_SET('b','a,b,c,d');
            -> 2
     

MAKE_SET(bits,str1,str2,...)
    返回一个集合 (包含由“,”字符分隔的子串组成的一个字符串),由相应的位在bits集合中的的字符串组成。str1对应于位0,str2对应位1,等等。在str1, str2, ...中的NULL串不添加到结果中。

    mysql> SELECT MAKE_SET(1,'a','b','c');
            -> 'a'
    mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world');
            -> 'hello,world'
    mysql> SELECT MAKE_SET(0,'a','b','c');
            -> ''

EXPORT_SET(bits,on,off,[separator,[number_of_bits]])
    返回一个字符串,在这里对于在“bits”中设定每一位,你得到一个“on”字符串,并且对于每个复位(reset)的位,你得到一个 “off”字符串。每个字符串用“separator”分隔(缺省“,”),并且只有“bits”的“number_of_bits” (缺省64)位被使用。

    mysql> select EXPORT_SET(5,'Y','N',',',4)
            -> Y,N,Y,N 

LCASE(str)
      
LOWER(str)
    返回字符串str,根据当前字符集映射(缺省是ISO-8859-1 Latin1)把所有的字符改变成小写。该函数对多字节是可靠的。

    mysql> select LCASE('QUADRATICALLY');
            -> 'quadratically'
     

UCASE(str)
      
UPPER(str)
    返回字符串str,根据当前字符集映射(缺省是ISO-8859-1 Latin1)把所有的字符改变成大写。该函数对多字节是可靠的。

    mysql> select UCASE('Hej');
            -> 'HEJ'

    该函数对多字节是可靠的。
LOAD_FILE(file_name)
    读入文件并且作为一个字符串返回文件内容。文件必须在服务器上,你必须指定到文件的完整路径名,而且你必须有file权限。文件必须所有内容都是可读的并且小于max_allowed_packet。如果文件不存在或由于上面原因之一不能被读出,函数返回NULL。

    mysql> UPDATE table_name
               SET blob_column=LOAD_FILE("/tmp/picture")
               WHERE id=1;


MySQL必要时自动变换数字为字符串,并且反过来也如此:

mysql> SELECT 1+"1";
        -> 2
mysql> SELECT CONCAT(2,' test');
        -> '2 test'

如果你想要明确地变换一个数字到一个字符串,把它作为参数传递到CONCAT()。

如果字符串函数提供一个二进制字符串作为参数,结果字符串也是一个二进制字符串。被变换到一个字符串的数字被当作是一个二进制字符串。这仅影响比较。 

2009年3月20日星期五

CSS实现背景透明效果

利用CSS实现背景透明效果的方法很简单,但目前不同的浏览器有着不同的标准,现在列出一个适合于各个浏览器的CSS代码合集,以供日后备用:

#snake{
  background: #666;
  filter:alpha(opacity=50); /*IE*/
  -moz-opacity:0.5; /*MOZ , FF*/
  opacity:0.5;/*CSS3, FF1.5*/
}

<div id="snake">背景透明效果</div>  

CSS屏幕居中

如何让DIV屏幕居中呢?以下的CSS代码可以有效帮助你实现这一点:


width:200px; margin-left:-100px; height:160x; margin-top:-80px; position:absolute; top:50%; left:50%;

新网站常用登录入口

建了一个网站却无人问津是非常痛苦的,不要急,以下给出了一些常用的登录入口,让你的网站先被搜索引擎收录吧!


google大概15天左右,百度大概30天 
添加百度登陆,尽量在各大搜索引擎登记一下,另外看看你搜索的关键字是什么,会不会范围太广了,有时网上类似你网站的名词太多话的会把你网站排到后面去的,另外多做一些外部链接,搜索引擎是通过连接来抓取的,多做外部链接对你网站快速收录有帮助 

搜索登记接入口 
Google搜索:
http://www.google.com/intl/zh-CN/add_url.html 

Google网页目录:
http://directory.google.com/Top/World/Chinese_Simplified/ 

百度搜索:
http://www.baidu.com/search/url_submit.html 百度搜霸下载 免费搜索代码 

百度网址站:
http://post.baidu.com/f?kw=百度site 

226自助链:
http://link.226.cc 

爱问搜索:
http://iask.com/guest/add_url.php 

雅虎搜索:
http://misc.yahoo.com.cn/search_submit.html 

网易有道搜索:
http://tellbot.yodao.com/report?keyFrom=help 

Yahoo! :
http://submit.search.yahoo.com/free/request/ 

中国搜索:
http://service.chinasearch.com.cn/NetSearch/pageurlrecord/frontpageurl.jsp 

有道搜索:
http://tellbot.yodao.com/report 

TOM搜索:
http://search.tom.com/tools/weblog/log.php 

天网搜索:
http://home.tianwang.com/denglu.htm 

MSN:
http://beta.search.msn.com/docs/submit.aspx 

Alexa:
http://pages.alexa.com/help/webmasters/index.html#crawl_site 

alltheweb:
http://www.alltheweb.com/help/webmaster/submit_site 

Gigablast:
http://www.gigablast.com/addurl