Archive for the ‘笔记’ Category

url重写后的路径问题

Friday, October 17th, 2008

以前用FleaPHP的url_rewrite模式一直有一个很头痛的问题, 就是页面上相关资源的路径问题.

问题大概是这样的, 为了让url更加友好我们使用apache的mod_rewrite将类似

http://localhost/?controller=default&action=index&a=1

这样的路径重写成

http://localhost/default/index/a/1

或者

http://localhost/default/index/a/1.html

这样, 但是如果是这样那么浏览器请求页面相关资源的基地址就发生了改变, 从原来的documentroot下变成了documentroot/default/index/a, 如果你要在页面上显示一个图片 1.jpg, 那么原来本来应该在documentroot/1.jpg下找到的文件却变成了documentroot/default/index/a/1.jpg, 那结果肯定是找不到的.

为了解决这个问题以前用过很多方法, 用的最多的就是使用绝对路径来解决这个问题, 这是有一个前提的, 就是程序一定要放在虚拟机的根目录下, 这样在html中要将所有的资源都是用/开头, /的意思是从根目录下开始寻找, 在localhost下的任何一个程序在任何目录中使用/1.jpg都会被指向documentroot/1.jpg, 这里再强调一个概念, “./”是当前目录, “../”是上级目录, “/”是根目录.

上面这个方法实际上已经可以解决这个问题了, 但是有局限, 就是程序的目录是固定的, 一定要在虚拟机根目录下, 这样或多或少会带来一些麻烦, 至少我觉得调试不方便. 于是又有了第二个解决方案, 也就是上面方案的升级版. 我们在全局定义一个常量 define(‘PRE_DIR’, ‘/’); 这样的话要将程序中所有的资源路径都写成类似 <?php echo PRE_DIR;?>dir/filename.jpg, 这样的话资源会被定为到 /dir/filename.jpg, 如果要将程序放在二级目录 test/下的话, 只要将PRE_DIR的值改成’/test/’就可以了.

其实在这之后又有了升级版, 但是不打算介绍太多, 因为这不是重点, 在手动改目录之后大家就想到要程序自动检测当前目录, 这个以前有做过, 是个不错的想法, 代码不少, 但是找不到了.

还有个东西我觉得比较神奇的, smarty有一个自动替换的插件, 可以自动在所有模板的资源链接前面加前缀, 当然前提是你已经定义了这个前缀, 插件名不记得了, 太久不用找不到了.

还是说重点吧, 昨天bobhero给我提供了一个新的思路, 利用mod_rewrite重新对资源进行定向, 后来到网上找相关的资料, 没有找到, 只找到了一些mod_rewrite的教程什么的. 研究了一下午也没研究出来, 因为url太复杂了, 很多情况都要考虑进去, 正则说什么就写不明白了, 今天早上终于搞定了.

_________.htaccess_____________________

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^.]*)(\.html)?$ index.php/$1 [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]*)/(.*\..*)$ $2

________end of .htaccess_____________

起作用的其实就这些东西,  可能还会有错误, 不过的确生效了.简单解释一下, RewriteCond %{REQUEST_FILENAME} !-f是条件语句, 意思是说如果请求的文件不存在下面的规则才生效. 第一条规则RewriteRule ^([^.]*)(\.html)?$ index.php/$1 [L]是FLEAPHP的重写规则.

下面两条才是为了解决路径问题的, RewriteRule ^([^/]*)/(.*\..*)$ $2的作用大概是这样, 比如url是这样controller/action/page/1,那么该页的style/css.css可能变成了controller/action/page/style/css.css, 这条语句就是要将controller/action/page/style/css.css指向action/page/style/css.css, 而由于某种机制请求每更换一次目录就会再执行一次根目录下的.htaccess中的重写规则, 由于action/page/style/css.css也不存在所以又被定向到page/style/css.css, 同理page/style/css.css也不存在, 再向上 style/css.css, 由于文件存在而不再执行重写规则, 向用户返回style/css.css的内容.

总的来说最后的这个方法除了apache受点累还是很完美的, 这样大概可能每个资源请求都会被重定向4次以上, 目前还不清楚对执行效率有多大的影响.

参考资料:

竹笋炒肉:Apache的Mod_rewrite学习

使用PHP收发邮件

Tuesday, September 9th, 2008

这两天都在测试邮件, 搞得头都大了, 现在技术问题都已经解决了, 记录一下.

发送邮件一直都是一个难题, 以前没用过mail函数, 因为多数的环境下都不支持, 曾经改写过Discuz的邮件类, 也用过像PHPMailer这样的邮件发送库来解决邮件发送的问题, 但实际上用的都是SMTP. 昨天bobhero在公司内网服务器上配置了sendmail, 简单配置了之后可以使用smtp, imap和pop3. 但按照网上的教程配置了之后php的mail()函数一直都无法发送邮件, 在搜索引擎上寻找很久没有结果, 最后bobhero重新编译了配置文件, 终于成功.

编译命令

make -C /etc/mail

收邮件要比发邮件复杂的多, 网上资源巨少, 好不容易有几篇英文的帖子和我情况类似也没有解决办法.

接受邮件使用php的imap库, 遇到的问题主要在imap_open()上

连接163使用

imap_open("{pop3.163.com:110/pop3}INBOX", $username, $password);

取得的7bit数据使用imap_qprint()解码.

连接gmail使用

imap_open("imap.gmail.com:993/imap/ssl", $username, $password);

最难弄的就是连接本地的imap服务器, Outlook是可以从服务器上收取邮件的, 但是php就是收不到并返回错误Certificate failure for 102.com: Self-signed certificate or untrusted authority: OU=IMAP server, CN=imap.example.com, E=postmaster@example.com, 使用telnet链接也没有问题, 从昨天下午研究到今天中午也没解决这个错误, 网上搜不到解决办法, 最后实在没办法了, 用IP Sniffer截php.exe的数据包, 然后用telnet进行模拟, 发现php.exe在和imap服务器链接成功之后使用了TLS(一个什么传输安全协议), 刚想放弃就在php.net上看到原来imap_open()还有一个参数是/notls, 我的天, 终于得救了.

imap_open("{localhost:143/imap/notls}INBOX", $username, $password);

研究期间发现telnet很好玩, 可以用telnet检查某项服务是否开启, 比如smtp, telnet 192.168.1.102 25, 如果服务是开启的就会建立一个连接, 可以用指令进行smtp 的相关操作, 而指令内容也就是smtp协议的相关内容, 其他协议pop, imap等等都可以这么玩.

相关端口:

smtp 协议 25端口

imap 协议 143端口

imap/ssl 993端口

imap/ssl/novalidate-cert 995端口

nntp协议 119端口

相关资源:

中国协议分析网 http://www.cnpaf.net/

RFC文档 http://www.faqs.org/rfcs/

保留用户输入的错误数据

Saturday, September 6th, 2008

最近公司项目比较闲, 所以很多时间都在整理代码, 这几天就又有了一个这样的需求, 当用户提交了错误的信息, 提示错误并保留用户输入的数据。

起初第一个想法就是使用COOKIE, 后来又考虑使用$_SESSION, 其实两者无明显区别,大概流程是这样的, 每个请求的前面都加入下面的逻辑:

if(有保存的数据){

    if(数据是不是本动作产生的){

        如果是则取得数据

    }

    清空保存的数据

}

if(是一个POST请求){

    保存用户的请求数据

}

这样处理的话消息处理需要中间页跳转,就是说错误提示是一个单独的页面,这样基本可以做到将数据保存到下一个请求。这个方法后来在显示上比较麻烦,就是需要判断有没有取得的数据,有的话输出没有的话不输出, 如果使用模板引擎的话处理起来更加复杂, 于是又提出了另一种解决方案。

将表单和处理程序放在一起(可能是一个function , MVC中应该是一个action中),这样的话需要显示表单或者处理数据要准备一套结构相同的数据传给页面,然后由本页显示错误消息, 不需要使用COOKIE.

function actionCreate(){

    if(是POST请求){

        过滤数据

        验证数据并生成错误

        if(没有错误){

            向数据库插入数据

        }else{

            将错误数据提交给显示层

        }

    }else if(是GET请求并且必要参数正确){

        从数据库取得显示数据提交给显示层

    }else{
        返回一个参数错误
    }

    $this->display('create.html');

}

可以说这个方法是比较完美的, 目前来说没有什么不足之处, 但是有很多细节是需要注意的, 比如form的action要提交给自身并且携带参数, 虽然参数无作用, 但可以用来刷新页面(window.location.href=window.location.href), 显示层刷新页面的功能是必须的, 因为如果是修改操作那么输入错误之后将会保留错误的信息。

接下来还可以通过控制错误消息的结构识别错误是由哪一个表单项产生的, 如果需要还可以对错误进行自动修改等等。

Ext学习笔记(1

Thursday, August 7th, 2008

昨天用了一下午学习Ext, 搞了一下午最后连个表格都没搞出来, 今天继续, 顺便记录一下.

中文在线手册 http://www.ajaxjs.com/docs/

这里请大家注意一下, 看手册一定要看源码包里的那个docs目录里的, Ext手册版本差异很大, 不一定最新的就一定适用。

使用Ext之前需要加载Ext库, 昨天直接加载核心, 竟然不好用, 最后看例子里面是加载了两个文件, 原因还没搞清楚, 但先记下来.

<script type=”text/javascript” src=”../ext-2.2/adapter/ext/ext-base.js”></script>
<script type=”text/javascript” src=”../ext-2.2/ext-all.js”></script>

最基础的

Ext.onReady(fn);

这个和Jquery的$(fn)是一样的, 就是页面加载完毕执行fn

Ext.get(‘idName’);

这个就是Jquery中的$(‘#idName’), 返回一个Ext的Element对象.

Element.dom是该对象的DOM节点, 其他内容看手册里的Element部分

Ext.select(‘p’)

这个类似Jquery中的$(‘p’), 但是Ext中没有each, Ext.select(‘p’).methodName()直接就作用在全部对象上.

事件绑定

Element.on(‘click’, fn);

获得事件句柄

clicked = function(e){

Ext.get(e.target).highlight();//e.target为触发该事件的对象id, highlight是高亮闪烁

}

Ext.select(‘p’).on(‘click’,clicked);

消息框

Ext.MessageBox为Ext的消息对象.

Ajax

ajax部分和Jquery非常相像了

Ext.get(‘msg’).load({
url: ‘http://test/ext/data.php’,
params: ‘name=1′,
text: ‘Updating…’
});

面向对象的访问控制

Monday, May 5th, 2008

这两天有在看php5的面向对象的一些教程, 因为php4用的比较多,所以对面向对象这个概念并不是很熟悉.

这里只是简单记录一下关于public, private和protected.

public(公共的)应该比较容易理解, 完全公开, 任何地方都可以访问, 包括该类内部, 外部, 子类等等.

a = "1";
	}

	function test(){
		echo $this->a;
	}
}

class b extends a{
	function test2(){
		echo $this->a;
	}
}

$a = new a;
$a->test();
// 这里说明public属性对象内部可访问, 而该语句没报错是
// 因为test方法也可以访问, 说明方法默认为public

echo $a->a; // 这里说明public属性外部也可以访问
$b = new b;
$b->test2(); // 这里说明public属性在子类中可以访问
echo $b->a;  // 这里说明public属性在子类外部也可以访问
?>

private(私有的)可以理解为只有对象的内部可以访问, 但是其中有可比较难理解的概念, 就是继承来的public方法可以访问到父类的private方法和属性, 而且实际上private属性和方法在技术上是无法被覆写的, 这个我目前还没有研究太透彻.

a = "2";
	}

	function test(){
		echo $this->a;
	}
}

class d extends c{
	function test2(){
		echo $this->a;
	}
}

class e extends c{
	private $a="3";
	function test2(){
		echo $this->a;
	}
}

$c = new c;
$c->test();// 这里说明private属性对象内部可访问
// echo $c->a; // 这里会报错说明private属性外部不可以访问
$d = new d;
echo '[';
$d->test(); // 这里输出2,说明在test()中可以访问到class c 的$a
echo ']';
$d->test2(); // 这里没有产生输出说明private属性在子类中不可见
echo $d->a;  // 这里也没有产生输出说明private属性在子类外部也是不可见的
$e = new e;
echo '{';
$e->test();  // 这里输出2, 说明该方法可见, 但访问的是父类的$a
echo '}';
$e->test2();
// 这里输出了3说明$a被覆写了, 但其实在class e中
// 其父类的$a并不可见,所以并不是覆写而是创建
?>

protected (受保护的)我个人理解就是在对象和子对象中你想怎么用都可以, 就是不可以在外面用.

a;
	}
}

class g extends f{
	function test2(){
		echo $this->a;
	}
}
$f = new f;
$f->test(); // 这里产生了输出,说明protected属性对象内部可以访问
//echo $f->a; // 这里报错说明protected属性对象外部不可以访问
$g = new g;
$g->test2(); // 这里输出4,说明protected属性在子类中可以访问
$g->test();  // 这里输出4,说明protected属性在子类中可以访问
// echo $g->a;  //这里报错,说明protected属性在子类的外部不可访问
?>

当年我做过的面试题目

Wednesday, April 23rd, 2008

刚刚看了老陈准备的考试题, 是做留言本的, 所以想起了我以前做的一套面试题.

个人觉得这套题还是不错的, geel花了不少心思出的, 题先发出来, 答案整理过后再跟上.

__ 1.php __

__ 试题 __

XHTML和CSS方面的问题不允许借用dreamweaver之类的工具。

一、php方面

1、打开1.php,在文件里写一个类Test实现ITest接口。(如果不会实现接口可以直接改写成类)
2、在当前目录下写一个文件 1-1.php,依次调用你刚才写的Test类的所有method。
3、上述代码(interface ITest)中,public修饰符是什么意思?同类修饰符还有哪些?各有什么意义?
4、上述代码中,function前面为什么要加static关键字?php的关键字和函数区别大小写吗?
4.1、文件 1.php 中不添加结尾的 “?>” 可以运行吗?不添加 “?>” 有什么作用吗?
5、=== 和 == 有什么区别?
6、引用的利弊?一般来说各自在什么情况下用?function如何返回引用?如何给一个function传递引用?
7、一个典型web程序(例如一个论坛)的性能瓶颈通常来说在什么地方?一般采用什么什么方法来提高执行效率?
8、一般用什么办法判断当前页面是用户 post而不是get?

二、XHTML和CSS以及javascript方面
9、简述两条w3c关于XHTML1.0的规范
10、访问过的超链接样式不再具有css里定义的hover和active了,问题的原因可能是?解决方法是?
答案::visited
11、定义一个层,用css实现下列样式:高200px,宽300px,其边框宽度为1px,边框颜色为红色,背景颜色为蓝色,文字颜色为白色,文字水平和垂直居中,文字大小14px,粗体
12、设有 <ul><li>aaa</li><li>bbb</li></ul>,用css使aaa和bbb显示在同一行上。
答案:display:inline;
13、onblur事件在什么时机被触发?
答案:失去焦点
14、请指出body是什么元素的子元素?
答案:document
15、设有如下HTML代码:
<input type=”text” id=”companyName” />
<p id=”company”></p>
<input type=”button” onclick=”setCompanyName()” value=”设置公司名” />
请完成 setCompanyName() 方法,使点击按钮的时候,将<p>中的文字设置为输入框中的文字。如果点击按钮时输入框里没有文字,弹出“请输入文字”的提示。
16、使用过哪些js类库?

三、其他部分
17、使用过哪些发行版本的Linux?喜欢他们的哪些地方?
18、在linux下面你一般用什么方法安装一个软件?
19、bash下面 ls -lah 代表什么意思?
19、rm -i 代表什么意思?rm -f 呢?
20、你用什么办法登录到一台 linux 主机?21、一个文件的权限为 764,表示什么意思?用什么命令将这个文件的权限改为 700?
22、FTP传输过程中binary和ascii模式有什么区别?
23、一个ftp服务器ip为1.2.3.4,端口为123,用户名是 andy,密码是 xyz,要求下载 movie 目录下的 1.rm,请写出可以直接下载这个文件的 URL
24、HTTP返回代码中404代表什么含义?302呢?
25、<script src=”a.js?0607″></script>,请问为什要写问号及其后面的内容?
答案:防止缓存
26、假设第1题中某一个方法你不知道怎么实现,一般情况下你会通过哪些途径来解决?

vForm ver1.3 build 20071207

Friday, December 7th, 2007

为了简化烦琐的javascript前端验证代码,

为了更好的通过w3c标准认证,

Oh yeah, vForm诞生了!

下载程序请直接拉到文章最后的附件部分.

什么是vForm?

vForm是一个php和一个javascript的结合, 再具体点说,vform由一个php类和一个javascript验证函数库组成, php的作用就是控制调用和生成javascript.

为什么开发vForm?

javascript验证是我们公司每个项目必须要做的工作, 为了避免反复写大量的javascript验证代码, 所以抽出了一些时间开发vForm.

vForm有多方便?

因为本人很懒, 所以需要程序一定要完成大部分工作.不说废话,上代码,看看vform如何完成一个表单验证. 注:需要将vform.php和vform.js放到同目录下.可以直接下载程序包,里面也有这个例子.

___________________simple.php____________________

<?php
/**
*   这是一个vfrom使用的一个离子.本例中为大家演示了各种验证规则
* 的使用和同页面多表单验证的实现方法.
*/
require_once(’vform.php’);
$config  = array(
array(”,’username’,’require’,’请输入帐号’),
array(’len’,’username’,’10′,’帐号不能超过10位’,’5′,’帐号不能少于5位’),
array(”,’pass’,’require’,’请输入密码’),
array(’len’,’pass’,’16′,’密码不能超过16位’,’6′,’密码不能少于6位’),
array(’s’,’repass’,’pass’,’两次输入的密码必须相同’),
array(”,’qq’,’number’,’QQ号码必须为数字’),
array(’len’,’qq’,’9′,’QQ号码不能超过9位’,’5′,’QQ号码不能少于5位’),
array(”,’phone’,’phone’,’电话号码由-和数字组成’),
array(”,’name’,’chinese’,’姓名必须是汉字’),
array(’len’,’name’,’4′,’这里不欢迎日本人’,’2′,’名字太短了’),
array(”,’ename’,’english’,’英文名必须是英文’),
array(’len’,’name’,’25′,’你是火星人么?’,’2′,’名字太短了’),
array(”,’age’,’number’,’年龄要是数字才行’),
array(”,’postcode’,’postcode’,’这个是邮政编码’),
array(”,’p’,’percent’,’一个百分比’),
array(”,’f’,’float’,’一个有理数,正负小数整数等等’),
array(”,’nc’,’nochinese’,’不能输入汉字’),
);
$config2  = array(
array(”,’username2′,’require’,’请输入帐号2′),
array(”,’pass2′,’require’,’请输入密码2′),
array(’s’,’repass2′,’pass2′,’两次输入的密码2必须相同’)
);
$vform   = new vform($config, ‘form1′);
$xform   = new vform($config2, ‘b_2′, ‘click’);
?>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd“>
<html xmlns=”http://www.w3.org/1999/xhtml” xml:lang=”en” lang=”en”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<title>vForm示例</title>
<style type=”text/css”>
*{
margin:0;
}
body,html{
font:12px;
text-align:center;
}
h1{
font:36px;
font-weight:bold;
text-align:left;
background:#ccc;
border-bottom:2px solid #666;
margin-bottom:10px;
}
form{
margin:10px;
}
img{
border:0;
}
#main{
width:275px;
margin:0 auto;
text-align:left;
}
#main p{
text-align:right;
padding:2px;
}
.text{
width:150px;
background:#eee;
border:1px solid #666;
}
.botton{
width:75px;
color:#fff;
font-weight:bold;
background:#555;
border:1px solid #000;
padding:2px;
}
</style>
<?=$vform->p();?>
<?=$xform->p(true);?>
</head>
<body>
<h1>vForm示例</h1>
<div id=’main’>
<form action=’http://www.m4ker.net’ method=’get’ id=’form1′ >
<p><b>帐号:</b><input name=’username’ class=’text’ id=’username’ /></p>
<p><b>密码:</b><input name=’pass’ class=’text’ id=’pass’ /></p>
<p><b>重复密码:</b><input name=’repass’ class=’text’ id=’repass’ /></p>
<p><b>电话号码:</b><input name=’phone’ class=’text’ id=’phone’ /></p>
<p><b>QQ号码:</b><input name=’qq’ class=’text’ id=’qq’ /></p>
<p><b>姓名:</b><input name=’name’ class=’text’ id=’name’ /></p>
<p><b>英文名:</b><input name=’ename’ class=’text’ id=’ename’ /></p>
<p><b>年龄:</b><input name=’age’ class=’text’ id=’age’ /></p>
<p><b>邮政编码:</b><input name=’postcode’ class=’text’ id=’postcode’ /></p>
<p><b>百分比:</b><input name=’p’ class=’text’ id=’p’ /></p>
<p><b>有理数:</b><input name=’f’ class=’text’ id=’f’ /></p>
<p><b>非汉字:</b><input name=’nc’ class=’text’ id=’nc’ /></p>

<p><input type=’submit’ value=’验证’ class=’botton’ id=’b_1′ /></p>
</form>
<form action=’http://www.m4ker.net’ method=’get’ id=’form2′ >
<p><b>帐号2:</b><input name=’username’ class=’text’ id=’username2′ /></p>
<p><b>密码2:</b><input name=’pass’ class=’text’ id=’pass2′ /></p>
<p><b>重复密码2:</b><input name=’repass’ class=’text’ id=’repass2′ /></p>

<p><input type=’submit’ value=’验证’ class=’botton’ id=’b_2′ /></p>
</form>
<p><a href=”http://validator.w3.org/check?uri=referer”><img src=”http://www.w3.org/Icons/valid-xhtml10” alt=”Valid XHTML 1.0 Transitional” height=”31″ width=”88″ /></a></p>
</div>
</body>
</html>

______________________________________

Ok了, 一点javascript都不需要.更详细的使用方法就需要大家自己发掘了.

附件:vform ver1.3 bulid 20071207

不使用中间变量来交换变量的值

Monday, July 16th, 2007

今天在群里有人问了这样一个问题, 在网上搜了一下, php大概有以下几种方法.

<?php

list($a,$b) = array($b,$a);

?>

这种方法我感觉不是很好, 虽然省去了一个变量的空间,但是调用函数也是要耗费系统资源的,不知道php是如何来进行操作的,估计时间效率上要比借助第三变量要慢.

<?php

$a=10;

$b=12;

$a=$b-$a; //$a=2,$b=12

$b=$b-$a; //$a=2,$b=10

$a=$b+$a; //$a=12,$b=10

?>

这个方法挺容易理解的,方法也很巧妙,只用了简单的加减运算.

<?php

$a=10; //$a=1010

$b=12; //$b=1100

$a=$a^$b; //$a=0110,$b=1100

$b=$a^$b; //$a=0110,$b=1010

$a=$a^$b; //$a=1100=12,$b=1010

?>

个人认为这种方法应该是效率最高的了,因为位操作的效率明显要比其他操作高的.

上面这些方法只供参考学习,不建议实际应用,严重影响程序的可读性.

今天第一次成功安装PHP+Apache+MySQL+Zend Optimizer

Tuesday, June 19th, 2007

用了大半天, 真不容易,.

是按PHP&MORE第一期的文章装的.

PHP5.2.3 + Apache2.2 + MYSQL5.0.41 + Zend Optimizer3.2.8

因为文章是很久以前的了,所以有很多地方不是按照上面的来做的.

太好了,再也不用装集成开发环境了.

图片附件:
php.jpg

图片附件:
apache.jpg

图片附件:
mysql.jpg

图片附件:
zend.jpg

for循环的特殊用法

Saturday, June 9th, 2007

在手册上发现了下面的代码

for ($i = 1; $i <= 10; echo $i , $i++);

但是运行之后提示语法错误, 后来在论坛发帖得知是由于echo 并不是一个函数,换成print就可以正常运行了

for ($i = 1; $i <= 10; print $i , $i++);

但是这段代码好象除了重复执行某条命令之外并没有什么其他的特殊功能了,如果想精简代码的话的确值得用一用,但是要注意程序的可读性.