存档

文章标签 ‘php编程’

php pdo中bindParam() 和 bindValue()方法的区别

2011年7月27日 没有评论

方法 bindParam() 和 bindValue() 非常相似。
唯一的区别就是前者使用一个PHP变量绑定参数,而后者使用一个值。

所以使用bindParam是第二个参数只能用变量名,而不能用变量值,而bindValue至可以使用具体值。

$stm = $pdo->prepare("select * from users where user = :user");
$user = "jack";
//正确
$stm->bindParam(":user",$user);
//错误
//$stm->bindParam(":user","jack");
//正确
$stm->bindValue(":user",$user);
//正确
$stm->bindValue(":user","jack");

另外在存储过程中,bindParam可以绑定为input/output变量,如下面:

$stm = $pdo->prepare("call func(:param1)");
$param1 = "abcd";
$stm->bindParam(":param1",$param1); //正确
$stm->execute();

存储过程执行过后的结果可以直接反应到变量上。

对于那些内存中的大数据块参数,处于性能的考虑,应优先使用前者。

php截取html字符串,并自动补全html代码

2011年6月18日 没有评论

实际开发中会经常碰到,很多人直接先strip_tags过滤掉html标签,但是就只剩下纯文本了,可读性非常差,下面是一个函数

/**
 * 截取HTML,并自动补全闭合
 * @param $html
 * @param $length
 * @param $end
 */
function subHtml($html,$length) {
 $result = '';
 $tagStack = array();
 $len = 0;

 $contents = preg_split("~(<[^>]+?>)~si",$html, -1,PREG_SPLIT_NO_EMPTY| PREG_SPLIT_DELIM_CAPTURE);
 foreach($contents as $tag)
 {
 if (trim($tag)=="")  continue;
 if(preg_match("~<([a-z0-9]+)[^/>]*?/>~si",$tag)){
 $result .= $tag;
 }else if(preg_match("~</([a-z0-9]+)[^/>]*?>~si",$tag,$match)){
 if($tagStack[count($tagStack)-1] == $match[1]){
 array_pop($tagStack);
 $result .= $tag;
 }
 }else if(preg_match("~<([a-z0-9]+)[^/>]*?>~si",$tag,$match)){
 array_push($tagStack,$match[1]);
 $result .= $tag;
 }else if(preg_match("~<!--.*?-->~si",$tag)){
 $result .= $tag;
 }else{
 if($len + mstrlen($tag) < $length){
 $result .= $tag;
 $len += mstrlen($tag);
 }else {
 $str = msubstr($tag,0,$length-$len+1);
 $result .= $str;
 break;
 }

 }
 }
 while(!empty($tagStack)){
 $result .= '</'.array_pop($tagStack).'>';
 }
 return  $result;
}

/**
 * 截取中文字符串
 * @param $string 字符串
 * @param $start 起始位
 * @param $length 长度
 * @param $charset  编码
 * @param $dot 附加字串
 */
function msubstr($string, $start, $length,$dot='',$charset = 'UTF-8') {
 $string = str_replace(array('&amp;', '&quot;', '&lt;', '&gt;','&nbsp;'), array('&', '"', '<', '>',' '), $string);
 if(strlen($string) <= $length) {
 return $string;
 }

 if(strtolower($charset) == 'utf-8') {
 $n = $tn = $noc = 0;
 while($n < strlen($string)) {
 $t = ord($string[$n]);
 if($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
 $tn = 1; $n++;
 } elseif(194 <= $t && $t <= 223) {
 $tn = 2; $n += 2;
 } elseif(224 <= $t && $t <= 239) {
 $tn = 3; $n += 3;
 } elseif(240 <= $t && $t <= 247) {
 $tn = 4; $n += 4;
 } elseif(248 <= $t && $t <= 251) {
 $tn = 5; $n += 5;
 } elseif($t == 252 || $t == 253) {
 $tn = 6; $n += 6;
 } else {
 $n++;
 }
 $noc++;
 if($noc >= $length) {
 break;
 }
 }
 if($noc > $length) {
 $n -= $tn;
 }
 $strcut = substr($string, 0, $n);
 } else {
 for($i = 0; $i < $length; $i++) {
 $strcut .= ord($string[$i]) > 127 ? $string[$i].$string[++$i] : $string[$i];
 }
 }

 return $strcut.$dot;
}

/**
 * 取得字符串的长度,包括中英文。
 */
function mstrlen($str,$charset = 'UTF-8'){
 if (function_exists('mb_substr')) {
 $length=mb_strlen($str,$charset);
 } elseif (function_exists('iconv_substr')) {
 $length=iconv_strlen($str,$charset);
 } else {
 preg_match_all("/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/", $text, $ar); 
 $length=count($ar[0]);
 }
 return $length;
}

巧用金山快盘搭建多地可用的SVN”服务器”

2011年5月5日 没有评论

这里说的SVN服务器,并不是一个真正的服务器,却具有svn服务器的功能。因为有些代码在家里和公司都需要维护,代码的同步变得有些麻烦,一开始用了google code,孰料google被狙,gogole account都登陆不上了,经过研究,发现了一个利用金山快盘搭建svn服务器的功能。

客户端用TortoiseSVN,其实TortoiseSVN不仅仅是个SVN客户端,还集成了一些svn服务器进行版本库管理的功能。在金山快盘里建立一个文件夹svn,在svn目录再建立一个空文件夹 project,在此文件夹上点右键,在弹出菜单中的TortoiseSvn下执行”在此创建版本库”命令。这样版本库就创建在了快盘上,以后版本库任意的改动,金山网盘都会帮我们自动同步到各台电脑上,当然前提是这些电脑都是开启了使用同一个账户的快盘。

版本库建好了,就相当于我们在每台有快盘的机器上都有个SVN服务器端,只是这里的版本库URL设置成版本库的位置 file:///X:/svn/project,这时就可以从TortoiseSVN里检出(checkout),提交(commit),和更新(update)了,这样我在公司修改了代码,提交以后,金山快盘会帮我把版本库文件同步到家里的电脑上,回到家里我只需要update一下,就可以看到在公司修改后的代码了。

顺便帮金山坐下广告,申请金山快盘的地址是:http://k.wps.cn/register/

php压缩/解压zip的利器-PclZip

2011年3月31日 没有评论

PclZip简介与使用

PclZip介绍
PclZip library能够压缩与解压缩Zip格式的压缩档(WinZip、PKZIP);且能对此类类档案进行处理,包括产生压缩档、列出压缩档的内容以及解压缩档案等等。由于能够在伺服器端进行压缩与解压缩的动作,所以相当方便使用。
PclZip定义一个PclZip类别,其类别物件可视为一个ZIP档案,亦提供method来进行处理。

如何使用PclZip
1.基础
所有的功能都由pclzip.lib.php这个档案提供,PclZip library可于其首页(www.phpconcept.net/pclzip/index.en.php)下载。所有的PKZIP档案其实就是一个PclZip的类别物件。当产生一个PclZip档案(ie, PclZip类别物件),就会先产生一个压缩档,且档名已经指定,但此压缩档的内容尚未存在:

< ?PHP
require_once('pclzip.lib.php');
$archive = new PclZip("archive.zip");
?>

此物件提供了一些public method可用来处理此档案。

2.参数
每一个method有其各自可使用的参数,包括有必须与非必须的参数:

< ?PHP
require_once('pclzip.lib.php');
$archive = new PclZip('archive.zip');

$v_list = $archive->add('dev/file.txt',
PCLZIP_OPT_REMOVE_PATH, 'dev');
?>

上例中的’dev/file.txt’就是必须参数;’PCLZIP_OPT_REMOVE_PATH’则为非必须参数。当然有些method也可以只包含非必须的参数:

< ?PHP
$list = $archive->extract(PCLZIP_OPT_PATH, "folder",
PCLZIP_OPT_REMOVE_PATH, "data",
PCLZIP_CB_PRE_EXTRACT, "callback_pre_extract",);
?>

上例中原本压缩档内档案存放的路径为/data,不过你可以指定解压缩至/folder中。此外,在解压缩之前,会呼叫callback function(’callback_pre_extract()’),此function可让使用者在解压缩的过程中变更档案存放路径与档名,或是选择某些档案不解压缩。
所有可用的非必要参数可参考网址(www.phpconcept.net/pclzip/man/en/index.php)。

3.回传值
每个method所回传的值可能会不同,将会在每个method中说明。不过大部分的method回传0、error或是阵列。

4.错误处理
从版本1.3之后,错误处理已经整合至PclZip类别中,当一个method回传错误码,可以得知一些额外的讯息以方便错误处理:
* errorName():回传错误名称
* errorCode():回传错误码
* errorInfo():回传错误的描述

接下来会举几个例子来说明如何使用PclZip。

PclZip实例1、产生ZIP压缩档
PclZip($zipname):为PclZip constructor,$zipname为PKZIP压缩档的档名。
主要是产生一个PclZip物件,即一个PKZIP压缩档;但此时,只有压缩档产生出来,并做一些检查(例如是否有开启zlib extension…等),除此之外,并没有做其他动作。
create($filelist, [optional arguments list]):将参数$filelist指定的档案或目录(包含当中所有档案与子目录)加入上述所产生的压缩档中。
而非必要的参数则能够修改压缩档内的档案存放路径。
此method可用的参数可以参考网志(www.phpconcept.net/pclzip/man/en/index.php)。

下面的示例说明如何产生PKZIP压缩档(档名为archive.zip),并将file.txt、data/text.txt以及目录folder(包含当中的档案与子目录)加入刚刚产生的archive.zip中:

< ?PHP
include_once('pclzip.lib.php');
$archive = new PclZip('archive.zip');
$v_list = $archive->create('file.txt,data/text.txt,folder');
if ($v_list == 0) {
die("Error : ".$archive->errorInfo(true));
}
?>

下面的示例说明基本上与上例一样产生archive.zip,但在将file.txt与text.txt压缩于其中时,将路径由data/改为install/ ;因此,在archive.zip中这两个档案的路径会是install/file.txt与install/text.txt

< ?PHP
include_once('pclzip.lib.php');
$archive = new PclZip('archive.zip');
$v_list = $archive->create('data/file.txt,data/text.txt',
PCLZIP_OPT_REMOVE_PATH, 'data',
PCLZIP_OPT_ADD_PATH, 'install');
if ($v_list == 0) {
die("Error : ".$archive->errorInfo(true));
}
?>

PclZip实例2、列出压缩档内容
listContent( ) :列出压缩档中的内容,包括档案的属性与目录:

< ?PHP
include_once('pclzip.lib.php');
$zip = new PclZip("test.zip");

if (($list = $zip->listContent()) == 0) {
die("Error : ".$zip->errorInfo(true));
}

for ($i=0; $i<sizeof ($list); $i++) {
for(reset($list[$i]); $key = key($list[$i]); next($list[$i])) {
echo "File $i / [$key] = ".$list[$i][$key]."<br>";
}
echo "<br />";
}
?></sizeof>

上例将会回传结果:
File 0 / [filename] = data/file1.txt
File 0 / [stored_filename] = data/file1.txt
File 0 / [size] = 53
File 0 / [compressed_size] = 36
File 0 / [mtime] = 1010440428
File 0 / [comment] =
File 0 / [folder] = 0
File 0 / [index] = 0
File 0 / [status] = ok

File 1 / [filename] = data/file2.txt
File 1 / [stored_filename] = data/file2.txt
File 1 / [size] = 54
File 1 / [compressed_size] = 53
File 1 / [mtime] = 1011197724
File 1 / [comment] =
File 1 / [folder] = 0
File 1 / [index] = 1
File 1 / [status] = ok

PclZip实例3、解压缩档案
extract([options list]) :解压缩PKZIP中的档案或目录。
[options list]可用的参数可参考网址(www.phpconcept.net/pclzip/man/en/index.php)。这些参数能让使用者在解压缩的时候有更多的选项,譬如指定变更解压缩档案的路径、指定只解压缩某些档案或不解压缩某些档案或者是将档案解压缩成字串输出(可用于readme档)。

下例是一个简单的解压缩档案示例,将压缩档archive.zip内的档案解压缩至目前的目录:

< ?PHP
require_once('pclzip.lib.php');
$archive = new PclZip('archive.zip');

if ($archive->extract() == 0) {
die("Error : ".$archive->errorInfo(true));
}
?>

下例是进阶的解压缩档案使用,archive.zip中所有档案都解压缩于data/中,而特别指明在install/release中的所有档案也直接丢于data/中,而非data/install/ release:

< ?PHP
include('pclzip.lib.php');
$archive = new PclZip('archive.zip');
if ($archive->extract(PCLZIP_OPT_PATH, 'data',
PCLZIP_OPT_REMOVE_PATH, 'install/release') == 0) {
die("Error : ".$archive->errorInfo(true));
}
?>

本文转自 http://www.ccvita.com/59.html

javascript 表单 submit()错误

2010年10月18日 没有评论

做个简单的表单验证,调用表单对象的submit对象竟然出现submit is not a function这样的错误,花了半个晚上的时间,终于找出了原因

原来 js对submit关键字敏感,而我的表单中有按钮name=”submit”…

把所有的name=”submit”去掉一切正常

吐血。。。

有关IIS下zencart的伪静态设置

2010年1月16日 没有评论

公司的zencart 项目放在了window2003的服务器上,为了seo的考虑,开启了搜索引擎优化模块,可是碰到了一个问题,url的伪静态是通过网站根目录下的.htaccess文件来实现的,这需要apache的rewrite模块,可是iis中怎么实现?其实可以通过iis的ISAPI_Rewrite扩展来实现,下载一个ISAPI Rewrite的安装包,Lite免费版本ISAPI_Rewrite Lite (freeware)即可。安装运行后,打开IIS,在网站单击右键选属性,就可以看到ISAPI_Rewrite已经被加入到了ISAPI筛选器中。在ISAPI_Rewrite的安装目录下,找到 httpd.ini 在此文件中输入Rewrite的规则即可,这里的规则基本跟apache的rewrite差不多,不过在我的测试过程中,发现了一些问题,例如http.ini中不能使用%{QUERY_STRING}这样的服务器变量,也不知道是不是我服务器配置的原因,这里我对 zencart 里的.htaccess文件需要经过一些修改解决了这个问题

RewriteRule ^(.*)-p-(.*).html$ index\.php?main_page=product_info&products_id=$2&%{QUERY_STRING} [L]

修改为,无非是一个简单的正则替换

RewriteRule ^(.*)-p-(.*).html(\?(.*))?$ index\.php?main_page=product_info&products_id=$2&$4 [L]

强大的php魔术,类方法的overload,cakephp中findby的实现

2009年11月19日 1 条评论

今天又摸了下cakephp,突然想研究一下cakephp中modle所提供的findbyfieldname..这样的方法,深入研究了一下,又发现了php的一个新技能!这确实是一个很有魔力的东西,简单代码如下

class OverLoadable{
//这个方法,当调用类中不存在的的方法时会调用这个方法,php自动把这个不存在的方法名和这个方法里的变量数组填充进这个方法并自动调用,于是我要findbyUsername时, 我就可以简单的通过正则提取出方法名中的Username这个字符串,然后传递给类中真正存在的方法findbyfield($field),这样就间接的实现了findbyUsername方法
于是这里,我就可以通过正则提出出方法名
function __call($method, $params){
if(preg_match(“/findby(?P.*)/i”,$method,$preg))
return $this->findbyfield($preg['field']);
}

function findbyfield($field)
{
echo $field;
}
//当读取类的成员变量不存在时,触发这个方法,以你要读取的变量名作为参数
function __get($name){
echo “Your val is $name,and is not exsit in this class!”;
}
//当写入类的成员变量不存在时,触发这个方法,以你要写入的变量名和值作为参数
function __set($name,$value){
echo ‘Your val is ‘.$name.’=>’.$value;
}
}

$oo = new OverLoadable();
$oo->findbyusername();
$oo->i = 5;
?>

我的wordpress图形验证码插件Wp-validcode

2009年10月25日 8 条评论

今天一天收到了65个垃圾评论,于是在前一个php验证码的基础上做出了自己的第一个wordpress插件,case见本站,下载地址在下面

wp-validcode

解压上传到wp-content/plugins目录,从后台安装即可!

已经调整为不区分大小写,验证码背景也进行了更换,更简单,但更具干扰性

php mkdir 递归创建多级目录

2009年9月14日 2 条评论

php默认的mkdir一次只能创建一层目录,如果在当前目录下创建一个div/css/layout 的目录就需要逐层逐层的先创建div,再创建div/css 再创建 div/css/layout,然而我们希望能让程序自动帮我们完成这个过程。

其实思路也很简单,1.先判断 div目录是否存在,不存在则创建;2.判断子目录 div/css 是否存在,不能存在则创建,3.在第二步中以子目录作为参数递归调用函数本身。也可以按相反顺序来,1.先判断最底层目录div/css/layout是否存在;2.判断div/css/layout的上层目录div/css是否存在,不存在则以div/css作为参数递归进行。。

下面是程序代码:

function mkdirs($dir)
{
if(!is_dir($dir))
{
if(!mkdirs(dirname($dir))){
return false;
}
if(!mkdir($dir,0777)){
return false;
}
}
return true;
}
mkdirs('div/css/layout');

同样的思路,php用rmdir和unlink递归删除多级目录的代码:

function rmdirs($dir)
{
$d = dir($dir);
while (false !== ($child = $d->read())){
if($child != '.' && $child != '..'){
if(is_dir($dir.'/'.$child))
rmdirs($dir.'/'.$child);
else unlink($dir.'/'.$child);
}
}
$d->close();
rmdir($dir);
}

zen cart 中使用自定义 session

2009年9月5日 1 条评论

    上次给zen cart添加图片验证码功能的时候同时碰到了一个问题,自己定义的session在zen cart程序中读取不到值,后来分析了一下得出如下结论。

    zen cart自定义了session的处理函数,session_save_path设在了/cache/文件夹,在include/configure.php里有个选项 define(‘STORE_SESSIONS’, ‘db’); // use ‘db’ for best support, or ” for file-based storage 设置session的保存方式。

    不同的程序间要想共享session数据,至少要遵循以下几个条件:session_save_path 相同,session_id相同,当然session的保存方式肯定要一样,php默认的session保存方式就是文件存储,而保存目录就在系统的临时目录。

    这里我们要想zen cart 读取到我们自己定义的 session变量,就需要我们在自己的程序里把session的存储目录放到zc目录下的cache文件夹,例如 session_save_path(‘e:/zc/cache’),然后修改zc/include/configure.php文件中 define(‘STORE_SESSIONS’, ‘db’); 修改为 define(‘STORE_SESSIONS’, ”);这样就让zen cart的session也以文件形式存储,就可以实现自定义session的共享了!

    以上的原理适用于其他类似的不同程序间session共享的问题,其实 zen cart中使用自定义 session的最简单的方法是 直接在自己的程序最顶部 require进来zen cart 的application_top.php即可,简单固然简单,但了解原理更重要!