PHP 对象的一个优势是可以使用魔术方法,这些方法可以不需要修改外部代码而重写一个类的默认行为,这使得PHP 语法有更少的冗余性和更具有扩展性。这些方法很好识别,他们都是以双下划线(__)开始的。比如: __construct(),__destruct(),__call(),__callStatic(),__get(),__set(),__isset(),__unset(),__sleep(),__wakeup(),__toString(),__invoke(),__set_state() 和 __clone() 等方法在 PHP 中被称为"魔术方法"(Magic methods)。在命名自己的类方法时不能使用这些方法名,除非是想使用其魔术功能。注意:PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除了上述魔术方法,建议不要以 __ 为前缀。1、__get、__set这两个方法是为在类和他们的父类中没有声明的属性而设计的。复制代码 代码如下:__get(string $name)  //当调用一个未定义的属性时访问此方法;__set(string $name, mixed $value)  //给一个未定义的属性赋值时调用;这里的没有声明包括当使用对象调用时,访问控制为proteced,private的属性(即没有权限访问的属性)。2、__isset、__unset复制代码 代码如下:__isset( $property ) //当在一个未定义的属性上调用isset()函数时调用此方法;__unset( $property ) //当在一个未定义的属性上调用unset()函数时调用此方法;3、__call、__callStatic复制代码 代码如下: __call(string $name, array $arguments) //当调用一个未定义的方法是调用此方法。 这里的未定义的方法包括没有权限访问的方法。复制代码 代码如下: __callStatic(string $name, array $arguments) 当在静态方法中调用一个不可访问方法(如未定义,或者不可见)时,__callStatic() 会被调用。__callStatic 它的工作方式类似于 __call() 魔术方法,__callStatic() 是为了处理静态方法调用,PHP5.3.0以上版本有效。PHP 确实加强了对 __callStatic() 方法的定义;它必须是公共的,并且必须被声明为静态的。同样,__call() 魔术方法必须被定义为公共的,所有其他魔术方法都必须如此。4、__autoload__autoload 函数,它会在试图使用尚未被定义的类时自动调用。通过调用此函数,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类。注意:在 __autoload 函数中抛出的异常不能被 catch 语句块捕获并导致致命错误。5、__construct、__destruct__construct 构造方法,当一个对象创建时调用此方法。使用此方法的好处是:可以使构造方法有一个独一无二的名称,无论它所在的类的名称是什么。这样你在改变类的名称时,就不需要改变构造方法的名称。__destruct 析构方法,PHP将在对象被销毁前(即从内存中清除前)调用这个方法。默认情况下,PHP仅仅释放对象属性所占用的内存并销毁对象相关的资源。析构函数允许你在使用一个对象之后执行任意代码来清除内存。当PHP决定你的脚本不再与对象相关时,析构函数将被调用。在一个函数的命名空间内,这会发生在函数return的时候。对于全局变量,这发生于脚本结束的时候。如果你想明确地销毁一个对象,你可以给指向该对象的变量分配任何其它值,通常将变量赋值勤为NULL或者调用unset。6、__clonePHP5中的对象赋值是使用的引用赋值,如果想复制一个对象则需要使用clone方法,在调用此方法是对象会自动调用__clone魔术方法。如果在对象复制需要执行某些初始化操作,可以在__clone方法实现。7、__toString 复制代码 代码如下:public string __toString ( void )__toString方法在将一个对象转化成字符串时自动调用,比如使用echo打印对象时。 应该显示些什么。此方法必须返回一个字符串,否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。复制代码 代码如下:$myObject = new myClass();echo $myObject;// Will look for a magic method echo$myObject->__toString();注意:不能在 __toString() 方法中抛出异常。这么做会导致致命错误。需要指出的是在 PHP 5.2.0 之前,__toString() 方法只有在直接使用于 echo 或 print 时才能生效。PHP 5.2.0 之后,则可以在任何字符串环境生效(例如通过 printf(),使用 %s 修饰符),但不能用于非字符串环境(如使用 %d 修饰符)。自 PHP 5.2.0 起,如果将一个未定义 __toString() 方法的对象转换为字符串,会产生 E_RECOVERABLE_ERROR 级别的错误。8、__sleep() 和 __wakeup()复制代码 代码如下:public array __sleep ( void )void __wakeup ( void )serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。如果该方法未返回任何内容,则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误。注意:__sleep() 不能返回父类的私有成员的名字,这样做会产生一个 E_NOTICE 级别的错误。可以用 Serializable 接口来替代。__sleep() 方法常用于提交未提交的数据,或类似的清理操作。同时,如果有一些很大的对象,但不需要全部保存,这个功能就很好用。与之相反, unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。__wakeup() 经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。9、__invoke()复制代码 代码如下:mixed __invoke ([ $... ] ) 当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。10、__set_state()复制代码 代码如下:static object __set_state ( array $properties ) 自 PHP 5.1.0 起当调用 var_export() 导出类时,此静态方法会被调用。本方法的唯一参数是一个数组,其中包含按 array('property' => value, ...) 格式排列的类属性。

使用PHP的人都知道,Zend Encode是一个脚本编程工具,用它写的程序,必须以源码的形式放置在Web服务器上,所以我们无法保护自己的源代码。大家都知道任何一个脚本程序的执行效率同具有相同功能的编译好的二进制代码相比较,它的执行效率都是比较低的。那么要是有一个工具能够帮我们把用PHP写的程序编译成二进制代码就好了,这样不但执行效率提高了,运行速度也加快了。真要是有这么一个工具,那就是一举两得了。 现在这不是梦想了,Zend Encode就是为此而开发的,它可以直接将脚本编译成二进制码。有了Zend Encode,你就可以将自己写好的PHP程序,编译后分发给很多用户,而用不着公开自己的源程序代码。编译好的二进制代码可以被Zend Optimizer透明读取,也就是说,客户只要在他的服务器上安装Zend Optimizer就可以执行由Zend Encode编译好的PHP程序。编译程序中包含有Zend Optimizer的部分代码,所以编译过程中对程序代码进一步作了优化处理,这即意味着脚本的执行效率提高了。 从一定意义上讲,Zend Encode是一个“PHP编译器”。但是,它又不是一个真正意义上的编译器,因为真正编译完成的程序可以脱离原来的编译环境运行,而Zend Encode编译过的程序,需要有Zend Optimizer的支持。就像编译好的Java二进制代码,需要JVM的支持。所以,Zend Optimizer可以看作是PHP编译好代码的虚拟机。不管怎么说,它们要通过相互配合使用。 目前Zend Encode支持的操作系统有:Solaris、Linux、FreeBSD及Windows。Zend Encode可以直接运行,电脑系统中不一定非要安装PHP。 Zend Encode的安装 先去下载一个软件包吧!Zend Encode不是自由软件,使用它要付费,而且价格相当高。幸好zend.com提供了一个可供试用的软件包,用户可以免费试用30天。这个软件包可以直接从http://www.zend.com上获得。所以,首先要到www.zend.com上下载Zend Encode、Zend Optimizer软件包。其次,要下载一个授权文件license。由于Zend Encode是一个授权使用的产品,所以需要用户从zend.com上申请一个license。申请步骤如下: 要申请一个试用的license,需要向zend.com提供你正在使用的计算机的ID,也即在申请页中填写host ID(实际上就是你计算机上的网卡的MAC地址)。查看计算机ID的方法如下:从zend.com下载一个lmutil.z的程序,解压后得到程序lmutil,运行它,它会根据系统的硬件特征产生一个序列串。将这个序列号填入到申请license页的host ID中,zend.com会在48小时内为用户生成一个license,下载此license文件,文件名为zendEncode.dat,它只能在这台电脑上使用。 1.将Zend Encode软件包也解压缩到/usr/local/Zend目录下。解压缩完成后,目录下多了一个zendenc的文件,它就是那个“编译器”啦。 2.将那个license文件复制到/usr/local/Zend目录下安装完成。 Zend Optimizer的安装 完成了Zend Encode的安装,才完成了一半任务,要使用编译后的PHP二进制代码,还要安装一个解释器——Zend Optimizer,有了它的支持,编译后的PHP二进制文件才能被正确地执行。 与Zend Encode不同,Zend Optimizer是一个免费软件,它的主要功能是加速PHP脚本文件的运行。据Zend.com称,有了Zend Optimizer的优化,程序的执行效率可以提高600%,经过笔者的简单测试,执行效率的确是提高了不少。 安装Zend Optimizer步骤如下: 1.解压缩Zend Optimizer软件包,将zendoptimizer.so文件复制到/usr/local/Zend/lib目录中。 2.打开/usr/local/lib/PHP.ini文件,在文件中加入以下两行: zend_optimizer.optimization_level=15zend_extension="/usr/local/Zend/lib/ zendoptimizer.so"3.重启动Apache 服务器,使以上更新生效。 Zend Encode的使用 现在准备工作全部完成了,我们写一个简单的PHP脚本,使用Zend Encode编译一下,看看效果如何。先写一个最简单的脚本,看看编译后的代码能不能执行: #vi test.PHP<? Phpinfo(); ?>编译它: #[[email protected] Zend]# ./zendenc test.PHP testencode.PHPZend Encoder Unlimited (TEST DRIVE) v1.1.0 (c) Zend Technologies, 1999-2000Licensed to: xqkred.Compiling test.PHP...Done encoding test.PHP.Optimizing... Done.Saving... Done.好,成功编译。不过,编译好的程序大小较之以前要大很多。 将testencode.PHP复制到Web服务器的发布目录下,在浏览器上键入http://localhost/testencode.PHP,哇!编译后的代码可以成功运行了!由于我们使用是试用版的Zend Encode,所以,在页面的最上面会出现一个图片,说明这是一个由Zend Encode试用软件包所产生的二进制文件。正式版的软件中,图片将不会再现。 下面再看看它的执行效率吧!首先写一个小的计算程序粗略估计一下: [compute.PHP]<?$t=time();for( $i=0;$i<1000000;$i++) {if(($i%20)!=0) {echo $i; echo ",";}else { echo "<br>";}}$t1=time();echo "<br>"; echo "It used:"; echo $t1-$t; echo " seconds";?>这个程序在执行时,取系统的时间,完成后再取系统时间,两个值的差即为整个程序运行所需时间,先在没有编译的情况下执行一遍,然后用Zend Encode编译后再执行一遍。比较结果:没有编译的情况下,运行所需时间平均为19秒,编译后的代码平均执行时间为 9秒,看来执行效率是提高了不少。(出处:

复制代码 代码如下:<?php/** * HOST: www.icbase.com *///set_time_limit(0);// base functionfunction curl_get($url, $data = array(), $header = array(), $timeout = 15, $port = 80, $reffer = '', $proxy = ''){ $ch = curl_init(); if (!empty($data)) { $data = is_array($data)?http_build_query($data): $data; $url .= (strpos($url,'?')? '&': "?") . $data; } curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); curl_setopt($ch, CURLOPT_POST, 0); curl_setopt($ch, CURLOPT_PORT, $port); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); //是否抓取跳转后的页面 $reffer && curl_setopt($ch, CURLOPT_REFERER, $reffer); if($proxy) { curl_setopt($ch, CURLOPT_PROXY, $proxy); curl_setopt($ch, CURLOPT_PROXYPORT, 1723); curl_setopt($ch, CURLOPT_PROXYUSERPWD,"andhm001:andhm123"); }$result = array(); $result['result'] = curl_exec($ch); if (0 != curl_errno($ch)) { $result['error'] = "Error:\n" . curl_error($ch);} curl_close($ch); return $result;}复制代码 代码如下:function curl_post($url, $data = array(), $header = array(), $timeout = 5, $port = 80){ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); //curl_setopt($ch, CURLOPT_PORT, $port); !empty ($header) && curl_setopt($ch, CURLOPT_HTTPHEADER, $header); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data);$result = array(); $result['result'] = curl_exec($ch); if (0 != curl_errno($ch)) { $result['error'] = "Error:\n" . curl_error($ch);} curl_close($ch);return $result;}/** * 获取列表页的html源码 * @param string $keywords 搜索关键字 * @param int $page 页数 * @return boolean|array */function getListHtml($keywords, $page=1){ if ($page < 0) { return false; } $page = $page == 0 ? 1 : intval($page); if ($page == 1) { $result = curl_get('http://www.icbase.com/ProResult.aspx', array('ProKey' => $keywords)); if ( isset($result['error']) ) { return false; //exit($result['error']); } $result = $result['result']; // asp.net post提交数据 if(! defined('__VIEWSTATE') && preg_match('/<input\s+type="hidden"\s+name="__VIEWSTATE"\s+id="__VIEWSTATE"\s+value="(.[^"]+)"/isU', $result, $matches)) { define('__VIEWSTATE', $matches[1]); } else { return false; } if(! defined('__PREVIOUSPAGE') && preg_match('/<input\s+type="hidden"\s+name="__PREVIOUSPAGE"\s+id="__PREVIOUSPAGE"\s+value="(.[^"]+)"/isU', $result, $matches)) { define('__PREVIOUSPAGE', $matches[1]); } else { return false; } if(! defined('__EVENTVALIDATION') && preg_match('/<input\s+type="hidden"\s+name="__EVENTVALIDATION"\s+id="__EVENTVALIDATION"\s+value="(.[^"]+)"/isU', $result, $matches)) { define('__EVENTVALIDATION', $matches[1]); } else { return false; } return $result; } $data = array( '__EVENTTARGET' => 'pager', '__EVENTARGUMENT' => $page, '__VIEWSTATE' => __VIEWSTATE, '__PREVIOUSPAGE' => __PREVIOUSPAGE, '__EVENTVALIDATION' => __EVENTVALIDATION, ); $result = curl_post('http://www.icbase.com/ProResult.aspx?ProKey=' . $keywords, $data); if ( isset($result['error']) ) { return false; //exit($result['error']); } $result = $result['result']; return $result;}/** * 获取列表页 a链接的url * @param string $html html源码 * @return array */function getListHref($html){ $pattern = '/<a\s+href=\'(.[^\']+)\'\s+target="_blank"\s*>[\s\n]*<img.+[^>]\/>/isU'; if (preg_match_all($pattern, $html, $matches)) { return $matches[1]; } else { // 没有匹配项 return array(); }}/** * 获取下一页数字 * @param string $html html源码 * @return number */function getListNextPage($html){ $pattern = '/<div\s+id="Pager".+[^>]>.+<a\s+href="javascript\:__doPostBack\(\'Pager\',\'(\d+)\'\)">><\/a>/isU'; if (preg_match($pattern, $html, $matches)) { return intval($matches[1]); } else { return -1; }}/** * 获取列表也所有的href * @param string $keywords 搜索关键字 * @return boolean|array */function getListHrefAll($keywords){ if (empty($keywords)) { return false; } $html = getListHtml($keywords); $hrefList = getListHref($html); if (empty($hrefList)) { // 没有结果 return array(); } $nextPage = getListNextPage($html); while ($nextPage > 0) { $html = getListHtml($keywords, $nextPage); $tmpHrefList = getListHref($html); $hrefList = array_merge($hrefList, $tmpHrefList); $nextPage = getListNextPage($html); } return $hrefList;}/** * 获取详情页信息 * @param string $url url地址或者是抓取到的html源代码 根据@see $is_url 区分 * @param int $is_url 1使用的是url地址 0直接处理html源代码 * @return boolean|multitype:|multitype:string */function getDetail($url, $is_url = 1){ if ( empty($url) ) { return false; } $host = 'www.icbase.com'; $html = $url; if ($is_url) { $url = '/' . ltrim($url, '/'); $result = curl_get($host . $url); if ( isset($result['error']) ) { exit($result['error']); } $html = $result['result']; } $result = array( 'sup_part' => '', // 供应商型号 'sup_id' => '', // 供应商ID 'mfg_part' => '', // 制造商型号 'mfg_name' => '', // 制造商名称 'cat_name' => '', // 分类名称 'para' => '', // 属性 'desc' => '', // 描述 'pdf_url' => '', // PDF地址 'sup_stock' => '', // 库存 'min_purch' => '', // 最小订购量 'price' => '', // 价格 'img_url' => '', // 图片地址 'createtime' => '', // 创建时间 'datacode' => '', // 批号 'package' => '', // 封装 'page_url' => '', // 页面地址 );// mfg_part $pattern = '/<td>产品型号<\/td><td>(.[^<]+)</isU'; if (preg_match($pattern, $html, $matches)) { $result['mfg_part'] = trim($matches[1]); } else { // 此项木有,说明也没处处了 return array(); } // mfg_name $pattern = '/<td>厂商<\/td>[\s\n]*<td>(.+)<\/td>/isU'; if (preg_match($pattern, $html, $matches)) { $result['mfg_name'] = trim($matches[1]); } // para $pattern = '/<tr\s+style="background-color:#E9E9E9;color:black; font-weight:bold;">(.+)<\/tr><\/table>/isU'; if (preg_match($pattern, $html, $matches)) { if (preg_match_all('/<td>(.+)<\/td>/isU', $matches[1], $matches)) { $count = count($matches[1]); $count = intval($count / 2 ); foreach ($matches[1] as $k=>$v) { if ($k >= $count) { break; } if (trim($v) == '描述') { // desc $result['desc'] = trim($matches[1][$count + $k]); continue; } $v = trim($v); $result['para'][$v] = trim($matches[1][$count + $k]); } } } // pdf_url $pattern = '/<td>详细资料<\/td><td><a\s+href="(.[^"]+)"/isU'; if (preg_match($pattern, $html, $matches)) { $result['pdf_url'] = trim($matches[1]); } // sup_stock $pattern = '/<td>库存数量<\/td>[\s\n]*<td>(\d+)<\/td>/isU'; if (preg_match($pattern, $html, $matches)) { $result['sup_stock'] = trim($matches[1]); } // price $pattern = '/<tr><td.[^>]+>(\d+)\+<\/td><td.[^>]+>.[^\d]*([\d.]+)<\/td><\/tr>/isU'; if (preg_match_all($pattern, $html, $matches)) { foreach ($matches[1] as $k=>$v) { $result['price'][$v] = '¥' . $matches[2][$k]; } } //img_url $pattern = '/<td>图片<\/td><td><img\s+src="(.[^"]+)"/isU'; if (preg_match($pattern, $html,

这个分页函数非常高只能的 看看就知道了 function ppage($total, $page, $e_page = 15, $e_block = 10, $url = '', $color = '') { if(!strpos($url,'?'))    $url.='?'; else    $url.='&'; if($color<>'') {    $color   ='<font color='.$color.'>';    $colore  = '</font>'; } $totalpage = ceil($total/$e_page);  //页面数目 $p_block   = ceil($totalpage/$e_block);  //块数目 $n_block   = ceil($page/$e_block); //现在块 $start     = ($n_block-1)*$e_block+1; $ended     = $n_block*$e_block; if($ended>$total)    $ended   = $totalpage; if($n_block>1) {    $link    = $start-1;    $head    ='<a href='.$url.'page='.$link.'>'.$color.'[<=]'.$colore.'</a> '; } if($n_block<$p_block) {    $link    = $ended+1;    $foot    = '<a href='.$url.'page='.$link.'>'.$color.'[=>]'.$colore.'</a>'; } for($i=$start;$i<=$ended;$i++) {    $middle .='<a href='.$url.'page='.$i.'>'.$color.'['.$i.']'.$colore.'</a> '; } return $head.$middle.$foot; } 下面是取得当前url的方法 function geturl() { $headers = getallheaders(); $url     = 'http:

网上的解决办法说抓取后用iconv()转码。看后我就觉 得不对劲:一个是不一定编译了iconv库,更大的问题是编码都跟流转换的时候有关(如果用了iconv实际上php转了两次码:流 -> UTF-8 -> GB2312):这不是白忙乎了吗? 仔细看了下php的文档(不知道大家都是怎么写代码的,其实文档上很清楚啊),上面关于fopen()及file_get_contents()都 提到了“默认是UTF-8,但是用户可以用stream_default_encoding()或者用户自定义上下文属性改变编码”(If unicode semantics are enabled, the default encoding of the read data is UTF-8. You can specify a different encoding by creating a custom context or by changing the default using stream_default_encoding().)。于是用stream_default_encoding('gb2312′);测试:但是 faint的是,这个函数不存在?!似乎php 6才支持。不过天无绝人之路,还有“用户自定义上下文属性”可以用。 经过更仔细的看文档,最后解决了这个问题: 复制代码 代码如下: //设置流的编码格式,这是文件流(file),如果是网络访问,file改成http $opts = array('file' => array('encoding' => 'gb2312')); $ctxt = stream_context_create($opts); file_get_contents(文件名, FILE_TEXT,

分类:腾博会官方网

时间:2016-08-01 04:03:14