PHP关于获取二进制数据流转换为文件的方法$content = $_POST['data'];
$fp = fopen('/tmp/newfile.bin','w');
fwrite($fp,$content);
以上例子是在data参数上传二进制,并保存到/tmp/newfile.bin中 , 解析json用json_decode,然后把二进制的那个值赋给content就可以
如何使用PHP编程说明 PHP是一门高效的网络编程语言 由于它具有编写灵活 运行快速等优点 迅速成为Web程序员的首选语言 前不久的一份权威调查表明 现在已经有 %的网站使用PHP作为主要的服务器端编程语言
但是 要成为一名PHP编程高手却并不容易 并不像很多人想象的那样 只要能够飞快地编写几条简单的代码去解决一个复杂的问题就是PHP编程高手了 真正的PHP高手还需要考虑更多的其它问题 以下三条准则是一名成熟的PHP程序员在编程中应该首先遵循的准则
懒惰是金
编写漂亮的代码
追求程序的速度 而不是编程的速度
一 懒惰是金
做一个懒惰的程序员吗?这个想法太奇怪了!因为这个世界上最忙碌的人可能就是计算机程序员了 但正是因为程序员太忙了 所以才应该在编程时学会偷懒
对于一个程序员来说 懒惰的方法有两种 其一 大胆使用现成的别人的程序代码 把这些代码融入到你自己的程序或者项目中去 其二是编写一些有用的代码建立一个函数库 在将来编写程序时可以顺手拈来 省去了许多重复的劳动 自然就可以懒惰一点了
这两种偷懒的方法都非常适合PHP程序员了
首先 PHP是在自由开放的环境中诞生和成长的一门语言 在世界各地 有成千上万的程序员 他们一直在为PHP的完美而不断奋斗 他们也愿意和别人分享自己的聪明才智和自己编写的代码 你每天都可以从一些PHP网站 邮件列表 新闻组发现大量的优秀的程序代码 这样说 我并不是鼓励你整天等著让别人为你编写代码 但是你可以 站在伟人的肩膀上 充分发扬 拿来主义 聪明地应用别人的程序代码可以节省你大量时间 其次 在PHP中 你可以方便地建立自己的函数库 这样可以在你以后编写程序时省去很多麻烦
下面笔者为大家介绍几个通用的函数 这些函数有的来自网上的一些开放源代码的项目 有的精选自邮件列表 如果你能把它们加入到你自己的函数库中 迟早你将会发现自己受益无穷
通用数据库处理函数
和其它的CGI函数相比 PHP的优点之一是具有很强大的数据库处理能力 但是 在PHP中 对于不同的数据库都使用一些特定的函数来专门处理 缺少通用的数据库处理函数 这大大降低了程序代码的可移植性 这也为初学编程的朋友带来了很多不便
在网上 许多程序员都通过封装类解决了这个问题 他们编写了统一的函数用来处理任何流行的数据库——不管是在Linux世界深受欢迎的mysql_query($Query_String $this-Link_ID);ss_timing_stop();ss_log(INFO ss_timing_current() Secs - $Query_String);$this-Row = ;$this-Errno = mysql_errno();$this-Error = mysql_error();if ($halt_on_error && !$this-Query_ID) {$this-halt( Invalid SQL: $Query_String);}return $this-Query_ID; }
二 编写漂亮的代码
将后台程序与前端程序分开
在编写PHP程序时 有些代码是用来处理一些事务 例如操作数据库 进行数学运算等 而另外的一些代码则只是事务处理的结果显示出来 例如一些使用echo 语句将结果以HTML的格式显示在Web浏览器上的PHP代码以及那些直接嵌入PHP程序的HTML代码 首先我们应该清晰地区分这两种代码 把前者称为后台程序 把后者称为前端程序
因为PHP是一种嵌入式编程语言 也就是说 所有的PHP代码都可以嵌入到HTML代码之中 这为程序的编写带来了许多便利之处 但是 物极必反 如果在一段较长的程序中将PHP代码和HTML代码混合编写 这将使程序杂乱无章 不利于程序的维护和阅读 所以我们需要尽可能地将这些程序中混杂于HTML代码中的PHP代码移植出来 在专门的文件中将这些代码封装成函数 然后在HTML代码中使用 include语句来包含这些文件 在适当的位置调用这些函数即可
这种做法一方面使HTML代码和PHP代码都简单易读 另一方面因为HTML代码需要不断更新 而这种分离的方法可以确保后台程序不会被破坏 同前端程序不同 后台程序更多追求的是稳定 结构化 极少更改 所以应该认真地设计和管理 其实 在设计台程序时 投入大量时间是值得的 现在栽树 以后乘凉 在以后的设计工作中将可以轻松地使用现在编写的后台程序
灵活使用包含文件
正如前面所说的那样 后台程序应当安排在一系列的包含文件中 包含文件可以通过include语句在需要时动态装入 也可以在php ini文件中通过使用auto_prepend_file指令预先自动装入 如果使用后一种方法的话 虽然取得了一劳永逸的好处 但是也有一些缺点值得我们注意 下面的一段代码向我们展示了解析一个庞大的包含文件需要一定的时间
require(timing inc); ss_timing_start(); include(test inc); ss_timing_stop(); echo ss_timing_current() ?
在上面的代码中 test inc是一个 行的包含文件 运行的结果显示 解析这个包含文件花费了 秒钟 对于一个大型网站来说 这个速度并不是可以忽略不记的
使用包含文件的另外一个缺点是 如果一个文件中的一个语句发生错误 将会使整个网站的PHP程序都无法运行 所以使用起来也及其小心
其实 对包含文件稍做处理 即可以使包含文件只在需要时进行解析 下面的代码使abc inc文件只在程序需要时才作解析
if ( defined( __LIBA_INC) ) return; define( __LIBA_INC ); /* * 代码 */ ?
使用面向对象的编程方法
PHP 也是一种面向对象的语言 面向对象的编程方法是优秀的程序员们非常推崇的一种软件设计方法 在PHP编程中可以充分发挥面向对象语言的优势 对编程中的对象进行封装 在前面的代码中 我们使用了面向对象的方法 例如在管理数据库时 我们将query()函数封装进数据库类中 这极大地方便了代码的管理 增加了程序的可读性
三 追求程序速度 而不是编程的速度
在网站建设中 程序运行速度和网页下载速度都是关系成败的重要因素 作为一名Web程序员 应该更加注意代码的运行速度 下面介绍的几种方法都在不同程度上提高了代码的运行速度
使用内嵌的HTML代码 而不是PHP的echo语句
因为PHP是一门嵌入式Web编程语言 可以将HTML代码和PHP代码相互嵌入 但是很多程序员担心在HTML代码中过多的使用 嵌入PHP代码会多次调用PHP解释器 从而降低了PHP代码的运行速度 所以宁愿使用PHP的echo语句来输出HTML代码 而不直接使用HTML代码 但事实却恰恰相反 每一个PHP页面只调用一次PHP解释器来解释所有的PHP代码 所以 只在需要时才嵌入PHP代码 而大多数的时候直接使用HTML代码输入结果 不但不会降低程序的运行速度 而且因为减少了对echo语句的解析 往往可以提高代码的运行速度
下面的一段代码证明了我们的结论 在这段代码中 我们使用了前面介绍的时间测试函数
使用str-replace而不是ereg-replace 习惯使用Perl进行编程的程序员更加愿意使用ereg_replace完成字符串替换工作 因为在PHP中ereg_replace的用法和Perl中模式匹配的用法相近 但是 下面的这段代码证明 使用str_replace 代替 ereg_replace将可以大大提高代码的运行速度
测试str_replace和ereg_replace的运行速度
//这段代码测试str_replace的运行速度 emphasis; ? for ($i= ; $i ; $i++) {str_replace(i b $string) } ?
//这段代码测试ereg_replace的运行速度 for ($i= ; $i ; $i++) {ereg_replace(([/]*)i \ b $string) } ? //打印结果
结论
使用str_replace的时间 - 使用ereg_pattern的时间 -
运行上面的代码 得到的结果是
使用str_replace的时间 - 使用ereg_pattern的时间 -
从运行的结果我们可以看出使用str_replace替代ereg_replace作为字符串替换函数 极大地提高了代码的运行速度
注意字符串的引用
PHP 和其它很多编程语言一样 可以使用双引号( )来引用字符串 也可以使用单引号() 但是在PHP中 如果使用双引号来引用字符串 那么PHP解析器将首先分析字符串中有没有对变量的引用 有变量的话 将对变量进行替换 如果是单引号 则没有如此复杂——直接将单引号包含起来的所有字符串直接显示出来 显然 在PHP编程中 如果使用单引号引用字符串变量要比使用双引号快速一些
在数据库中避免使用联合操作
比起其它的Web编程语言来说 PHP的数据库功能十分强大 但是在PHP中数据库的运行仍然是一件十分费时费力的事情 所以 作为一个Web程序员 要尽量减少数据库的查询操作 同时应该为数据库建立适当的索引 另一件值得注意的事情是在用PHP操作数据库时 尽可能不使用多个数据表的联合操作 尽管联合操作可以增强数据库的查询功能 但是却大大增加了服务器的负担
为了说明这个问题 我们可以看看下面的这个简单的例子
我们在数据库中创建了两个数据表foo和big_foo 在数据表foo中 只有一个字段 包含了从 - 之间的所有自然数 数据表big_foo同样只有一个字段 但包含了从 - 之间的全部自然数 所以 从大小上说 big_foo等于foo与它自身进行了联合操作
$db-query( select * from foo ); secs $db-next_record(); secs $db-query( insert into foo values (NULL) ); secs $db-query( select * from foo as a foo as b ); secs $db-query( select * from foo as a foo as b where a idb id ); secs $db-query( select * from foo as a foo as b where a id = b id ); secs $db-query( select * from big_foo ); secs
从上面操作结果我们可以发现 对于两个有 条记录的数据表进行联合 其速度并不比对一个 条纪录的大型数据表单独进行操作快多少
注意include与require的区别
在PHP变成中 include()与require()的功能相同 但在用法上却有一些不同 include()是有条件包含函数 而require()则是无条件包含函数 例如在下面的一个例子中 如果变量$somgthing为真 则将包含文件somefile
if($something){include( somefile ); }
但不管$something取何值 下面的代码将把文件somefile包含进文件里
if($something){require( somefile ); }
下面的这个有趣的例子充分说明了这两个函数之间的不同
$i = ; while ($i) {require( somefile $i );$i++; }
在这段代码中 每一次循环的时候 程序都将把同一个文件包含进去 很显然这不是程序员的初衷 从代码中我们可以看出这段代码希望在每次循环时 将不同的文件包含进来 如果要完成这个功能 必须求助函数include()
$i = ; while ($i) { include( somefile $i ); $i++; }
注意echo和print的区别
PHP中echo和print的功能也基本相同 但是两者之间也有细微差别 在PHP代码中可以把print作为一个普通函数来使用 例如执行下面的代码后变量$res的值将为 $ret = print Hello World ;
lishixinzhi/Article/program/PHP/201405/30767
PHP curl 模拟表单数据流multipart/form-data上传文件在调用公众号接口".$token."type=".$type;
上传永久素材文件总是返回 "{\"errcode\":41005,\"errmsg\":\"media data missing\"}"
经过多次测试使用下面的方式,可以正常上传
//调用测试
protected static $url;
protected static $delimiter;
protected static $instance;
public function index()
{
static::$delimiter = uniqid();
$basename = Request::instance()-root();
if (pathinfo($basename, PATHINFO_EXTENSION) == 'php') {
$basename = dirname($basename);
}
$result=$this-wxAddMaterial($token,$basename.'/upload/images/gnlog.jpg','image');
}
// 新增其他类型永久素材
public function wxAddMaterial($token,$filename='',$type='') {
// 设置请求参数
static::$url = "".$token."type=".$type;
$filePath = str_replace('\\', '/', $filename);
// 发送请求
$imginfo=pathinfo($filePath);
$fields = array(
'media'=file_get_contents(".".$filePath),
'filename'=$imginfo["basename"],
);
$res = $this-putPart( $fields);
// 发送请求
return $res;
}
//推送文件流
public function putPart($param) {
$post_data = https://www.04ip.com/post/static::buildData($param);
$curl = curl_init(static::$url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
【php数据流编程 php 数据处理】curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($curl, CURLOPT_HTTPHEADER, [
"Content-Type: multipart/form-data; boundary=" . static::$delimiter,
"Content-Length: " . strlen($post_data)
]);
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
//编译请求头格式和数据流
private static function buildData($param){
$datahttps://www.04ip.com/post/= '';
$eol = "\r\n";
$upload = $param['media'];
unset($param['media']);
foreach ($param as $name = $content) {
$data .= "--" . static::$delimiter . "\r\n"
. 'Content-Disposition: form-data; name="' . $name . "\"\r\n\r\n"
. $content . "\r\n";
}
$data .= "--" . static::$delimiter . $eol
. 'Content-Disposition: form-data; name="media"; filename="' . $param['filename'] . '"' . "\r\n"
. 'Content-Type:application/octet-stream'."\r\n\r\n";
$data .= $upload . "\r\n";
$data .= "--" . static::$delimiter . "--\r\n";
return $data;
}
根据自己的实际情况稍作修改
如何使用PHP编程PHP是一门高效的网络编程语言,由于它具有编写灵活、运行快速等优点,迅速成为Web程序员的首选语言 。前不久的一份权威调查表明,现在已经有31.6%的网站使用PHP作为主要的服务器端编程语言 。
但是 , 要成为一名PHP编程高手却并不容易 。并不像很多人想象的那样,只要能够飞快地编写几条简单的代码去解决一个复杂的问题就是PHP编程高手了 , 真正的PHP高手还需要考虑更多的其它问题 。以下三条准则是一名成熟的PHP程序员在编程中应该首先遵循的准则 。
1.懒惰是金
2.编写漂亮的代码
3.追求程序的速度,而不是编程的速度
一、懒惰是金
做一个懒惰的程序员吗?这个想法太奇怪了!因为这个世界上最忙碌的人可能就是计算机程序员了 。但正是因为程序员太忙了,所以才应该在编程时学会偷懒 。
对于一个程序员来说,懒惰的方法有两种:其一,大胆使用现成的别人的程序代码 , 把这些代码融入到你自己的程序或者项目中去 。其二是编写一些有用的代码建立一个函数库,在将来编写程序时可以顺手拈来,省去了许多重复的劳动,自然就可以懒惰一点了 。
这两种偷懒的方法都非常适合PHP程序员了 。
首先,PHP是在自由开放的环境中诞生和成长的一门语言 。在世界各地,有成千上万的程序员,他们一直在为PHP的完美而不断奋斗,他们也愿意和别人分享自己的聪明才智和自己编写的代码 。你每天都可以从一些PHP网站、邮件列表、新闻组发现大量的优秀的程序代码 。这样说 , 我并不是鼓励你整天等着让别人为你编写代码 , 但是你可以“站在伟人的肩膀上” , 充分发扬“拿来主义”,聪明地应用别人的程序代码可以节省你大量时间 。其次,在PHP中,你可以方便地建立自己的函数库,这样可以在你以后编写程序时省去很多麻烦 。
下面笔者为大家介绍几个通用的函数 , 这些函数有的来自网上的一些开放源代码的项目 , 有的精选自邮件列表 。如果你能把它们加入到你自己的函数库中,迟早你将会发现自己受益无穷 。
1.通用数据库处理函数
和其它的CGI函数相比,PHP的优点之一是具有很强大的数据库处理能力 。但是,在PHP中 , 对于不同的数据库都使用一些特定的函数来专门处理,缺少通用的数据库处理函数 。这大大降低了程序代码的可移植性,这也为初学编程的朋友带来了很多不便 。
在网上,许多程序员都通过封装类解决了这个问题 。他们编写了统一的函数用来处理任何流行的数据库——不管是在Linux世界深受欢迎的Mysql还是在Windows平台上广泛流行的SqlServer 。就笔者个人来说 , 非常喜欢使用这些函数,因为可以直接使用一些简单的诸如"query"、"next_record"之类的函数,而不需要考虑数据库的连接、数据库句柄这些复杂的东西,更不需要考虑使用的是何种数据库 。
如果你需要这些函数,你可以通过访问以下的几个网址而得到:
2.变量调试函数
PHP程序的调试一直是一件让人头疼的事,它既不像VB等高级语言那样有集成的编译调试环境,也不想Perl那样可以在Linux或者DOS环境下直接运行 。其实,我们完全可以通过灵活地使用echo语句来完成对PHP的调试工作 。
下面的几个函数可以让你随时查看程序中任何变量的类型及其值 。
function ss_array_as_string (&$array, $column = 0) {
$str = "Array(
n";
while(list($var, $val) = each($array)){
for ($i = 0; $i$column+1; $i++){
$str .= "    ";
}
$str .= $var. == ;
$str .= ss_as_string($val, $column+1)."
n";
}
for ($i = 0; $i$column; $i++){
$str .= "    ";
}
return $str.);
}
function ss_object_as_string (&$object, $column = 0) {
if (empty($object-classname)) {
return "$object";
}
else {
$str = $object-classname."(
n";
while (list(,$var) = each($object-persistent_slots)) {
for ($i = 0; $i$column; $i++){
$str .= "    ";
}
global $$var;
$str .= $var. == ;
$str .= ss_as_string($$var, column+1)."
n";
}
for ($i = 0; $i$column; $i++){
$str .= "    ";
}
return $str.);
}
}
function ss_as_string (&$thing, $column = 0) {
if (is_object($thing)) {
return ss_object_as_string($thing, $column);
}
elseif (is_array($thing)) {
return ss_array_as_string($thing, $column);
}
elseif (is_double($thing)) {
return "Double(".$thing.")";
}
elseif (is_long($thing)) {
return "Long(".$thing.")";
}
elseif (is_string($thing)) {
return "String(".$thing.")";
}
else {
return "Unknown(".$thing.")";
}
}
需要的时候,在程序中简单地加入下面的一条代码即可查看程序中的所使用的变量(包括数组和对象)的类型和值:
echo ss_as_string($my_variable);
使用下面的语句,我们可以直接查看程序中所有的变量的值:
echo ss_as_string($GLOBALS);
3. 控制Log信息的函数
调试PHP程序的另外一种重要的方法就是查看Log信息 。如果能够方便地控制Log信息的级别以及Log信息的显示内容,将会给程序调试带来更多的便利 。下面的几个函数可以方便地实现这个功能 。
$ss_log_level = 0;
$ss_log_filename = /tmp/ss-log;
$ss_log_levels = array(
NONE = 0,
ERROR = 1,
INFO = 2,
DEBUG = 3);
function ss_log_set_level ($level = ERROR) {
global $ss_log_level;
$ss_log_level = $level;
}
function ss_log ($level, $message) {
global $ss_log_level, $ss-log-filename;
if ($ss_log_levels[$ss_log_level]$ss_log_levels[$level]) {
// 不显示Log信息
return false;
}
$fd = fopen($ss_log_filename, "a+");
fputs($fd, $level. - [.ss_timestamp_pretty().] - .$message."n");
fclose($fd);
return true;
}
function ss_log_reset () {
global $ss_log_filename;
@unlink($ss_log_filename);
}
在上面的函数中 , 有四个Log级别变量 。运行PHP程序时 , 只有当Log的级别低于预设的级别值时,Log信息才可以被记录和显示出来 。例如 , 在程序中加入如下的一条语句:
ss_log_set_level(INFO);
那么,运行PHP程序时,只有ERROR和INFO级别的LOG信息才能被记录和显示出来,DEBUG级的信息则被忽略了 。除此之外 , 我们还可以设定显示的信息内容 , 其语句如下:
ss_log(ERROR, "testing level ERROR");
ss_log(INFO, "testing level INFO");
ss_log(DEBUG, "testing level DEBUG");
你也可以随时使用下面的语句清空LOG信息:
ss_log_reset();
4.速度测试函数
为了优化代码,我们需要一种可以测试代码运行时间的方法,从而来选择最优的代码 。下面的函数可以测试运行代码所需的时间:
function ss_timing_start ($name = default) {
global $ss_timing_start_times;
$ss_timing_start_times[$name] = explode( , microtime());
}
function ss_timing_stop ($name = default) {
global $ss_timing_stop_times;
$ss_timing_stop_times[$name] = explode(, microtime());
}
function ss_timing_current ($name = default) {
global $ss_timing_start_times, $ss_timing_stop_times;
if (!isset($ss_timing_start_times[$name])) {
return 0;
}
if (!isset($ss_timing_stop_times[$name])) {
$stop_time = explode(, microtime());
}
else {
$stop_time = $ss_timing_stop_times[$name];
}
$current = $stop_time[1] - $ss_timing_start_times[$name][1];
$current += $stop_time[0] - $ss_timing_start_times[$name][0];
return $current;
}
现在可以轻松地检查任何一段代码的执行时间了,甚至我们可以同时使用多个计时器,只需在使用上述的几个函数时设定不同的参数作为计时器的名称就可以了 。
5.调试和优化数据库的操作
对于数据库来说 , 运行速度是至关重要的 。尽管很多书籍和文章都讲授了一些快速运行数据库的方法,但是所有的方法都必须经过实践的检验 。下面我们将把PHPLib函数库中的query()函数和上面介绍的几个函数综合起来编写成新的query()函数,和原先的函数相比,这个函数增加了运行时间的监测功能 。
function query($Query_String, $halt_on_error = 1) {
$this-connect();
ss_timing_start();
$this-Query_ID = @mysql_query($Query_String,$this-Link_ID);
ss_timing_stop();
ss_log(INFO, ss_timing_current(). Secs - .$Query_String);
$this-Row = 0;
$this-Errno = mysql_errno();
$this-Error = mysql_error();
if ($halt_on_error && !$this-Query_ID) {
$this-halt("Invalid SQL: ".$Query_String);
}
return $this-Query_ID;
}
二、编写漂亮的代码
1.将后台程序与前端程序分开
在编写PHP程序时 , 有些代码是用来处理一些事务,例如操作数据库、进行数学运算等,而另外的一些代码则只是事务处理的结果显示出来,例如一些使用echo语句将结果以HTML的格式显示在Web浏览器上的PHP代码以及那些直接嵌入PHP程序的HTML代码 。首先我们应该清晰地区分这两种代码 , 把前者称为后台程序,把后者称为前端程序 。
因为PHP是一种嵌入式编程语言 , 也就是说,所有的PHP代码都可以嵌入到HTML代码之中 , 这为程序的编写带来了许多便利之处 。但是,“物极必反”,如果在一段较长的程序中将PHP代码和HTML代码混合编写,这将使程序杂乱无章 , 不利于程序的维护和阅读 。所以我们需要尽可能地将这些程序中混杂于HTML代码中的PHP代码移植出来,在专门的文件中将这些代码封装成函数,然后在HTML代码中使用include语句来包含这些文件,在适当的位置调用这些函数即可 。
这种做法一方面使HTML代码和PHP代码都简单易读,另一方面因为HTML代码需要不断更新 , 而这种分离的方法可以确保后台程序不会被破坏 。
同前端程序不同,后台程序更多追求的是稳定、结构化,极少更改,所以应该认真地设计和管理 。其实,在设计台程序时 , 投入大量时间是值得的,“现在栽树,以后乘凉”,在以后的设计工作中将可以轻松地使用现在编写的后台程序 。
2.灵活使用包含文件
正如前面所说的那样,后台程序应当安排在一系列的包含文件中 。包含文件可以通过include语句在需要时动态装入 , 也可以在php.ini文件中通过使用auto_prepend_file指令预先自动装入 。
如果使用后一种方法的话,虽然取得了一劳永逸的好处,但是也有一些缺点值得我们注意 。下面的一段代码向我们展示了解析一个庞大的包含文件需要一定的时间:
require(timing.inc);
ss_timing_start();
include(test.inc);
ss_timing_stop();
echo
.ss_timing_current().
;
?
在上面的代码中 , test.inc是一个1000行的包含文件,运行的结果显示,解析这个包含文件花费了0.6秒钟 , 对于一个大型网站来说,这个速度并不是可以忽略不记的 。
使用包含文件的另外一个缺点是:如果一个文件中的一个语句发生错误 , 将会使整个网站的PHP程序都无法运行 。所以使用起来也及其小心 。
其实 , 对包含文件稍做处理,即可以使包含文件只在需要时进行解析 。下面的代码使abc.inc文件只在程序需要时才作解析:
if ( defined( __LIBA_INC) ) return;
define( __LIBA_INC, 1 );
/*
* 代码...
*/
?
3.使用面向对象的编程方法
PHP也是一种面向对象的语言 , 面向对象的编程方法是优秀的程序员们非常推崇的一种软件设计方法,在PHP编程中可以充分发挥面向对象语言的优势,对编程中的对象进行封装 。在前面的代码中 , 我们使用了面向对象的方法,例如在管理数据库时,我们将query()函数封装进数据库类中 , 这极大地方便了代码的管理,增加了程序的可读性 。
三、追求程序速度 , 而不是编程的速度
在网站建设中 , 程序运行速度和网页下载速度都是关系成败的重要因素 。作为一名Web程序员,应该更加注意代码的运行速度 。下面介绍的几种方法都在不同程度上提高了代码的运行速度 。
1.使用内嵌的HTML代码,而不是PHP的echo语句 。
因为PHP是一门嵌入式Web编程语言,可以将HTML代码和PHP代码相互嵌入 。但是很多程序员担心在HTML代码中过多的使用""嵌入PHP代码会多次调用PHP解释器 , 从而降低了PHP代码的运行速度,所以宁愿使用PHP的echo语句来输出HTML代码,而不直接使用HTML代码 。但事实却恰恰相反 。每一个PHP页面只调用一次PHP解释器来解释所有的PHP代码,所以,只在需要时才嵌入PHP代码,而大多数的时候直接使用HTML代码输入结果,不但不会降低程序的运行速度 , 而且因为减少了对echo语句的解析,往往可以提高代码的运行速度 。
下面的一段代码证明了我们的结论 。在这段代码中,我们使用了前面介绍的时间测试函数 。
使用str-replace而不是ereg-replace
习惯使用Perl进行编程的程序员更加愿意使用ereg_replace完成字符串替换工作,因为在PHP中ereg_replace的用法和Perl中模式匹配的用法相近 。但是 , 下面的这段代码证明,使用str_replace 代替 ereg_replace将可以大大提高代码的运行速度 。
测试str_replace和ereg_replace的运行速度
//这段代码测试str_replace的运行速度
emphasis; ?
for ($i=0; $i1000; $i++) {
str_replace(i, b, $string).
;
}
?
//这段代码测试ereg_replace的运行速度
for ($i=0; $i1000; $i++) {
ereg_replace(([/]*)i, \1b, $string).
;
}
?
//打印结果
结论
使用str_replace的时间 -
使用ereg_pattern的时间 -
运行上面的代码,得到的结果是:
使用str_replace的时间 - 0.089757
使用ereg_pattern的时间 - 0.248881
从运行的结果我们可以看出使用str_replace替代ereg_replace作为字符串替换函数,极大地提高了代码的运行速度 。
3.注意字符串的引用
PHP和其它很多编程语言一样,可以使用双引号("")来引用字符串,也可以使用单引号() 。但是在PHP中,如果使用双引号来引用字符串,那么PHP解析器将首先分析字符串中有没有对变量的引用,有变量的话,将对变量进行替换 。如果是单引号,则没有如此复杂——直接将单引号包含起来的所有字符串直接显示出来 。显然,在PHP编程中,如果使用单引号引用字符串变量要比使用双引号快速一些 。
4.在数据库中避免使用联合操作
比起其它的Web编程语言来说,PHP的数据库功能十分强大 。但是在PHP中数据库的运行仍然是一件十分费时费力的事情 , 所以,作为一个Web程序员,要尽量减少数据库的查询操作,同时应该为数据库建立适当的索引 。另一件值得注意的事情是在用PHP操作数据库时,尽可能不使用多个数据表的联合操作,尽管联合操作可以增强数据库的查询功能,但是却大大增加了服务器的负担 。
为了说明这个问题,我们可以看看下面的这个简单的例子 。
我们在数据库中创建了两个数据表foo和big_foo 。在数据表foo中,只有一个字段,包含了从1-1000之间的所有自然数 。数据表big_foo同样只有一个字段,但包含了从1-1,000,000之间的全部自然数 。所以,从大小上说,big_foo等于foo与它自身进行了联合操作 。
$db-query("select * from foo");
0.032273 secs
$db-next_record();
0.00048999999999999 secs
$db-query("insert into foo values (NULL)");
0.019506 secs
$db-query("select * from foo as a, foo as b");
17.280596 secs
$db-query("select * from foo as a, foo as b where a.idb.id");
14.645251 secs
$db-query("select * from foo as a, foo as b where a.id = b.id");
0.041269 secs
$db-query("select * from big_foo");
25.393672 secs
从上面操作结果我们可以发现,对于两个有1000条记录的数据表进行联合,其速度并不比对一个1000000条纪录的大型数据表单独进行操作快多少 。
5.注意include与require的区别
在PHP变成中,include()与require()的功能相同,但在用法上却有一些不同,include()是有条件包含函数 , 而require()则是无条件包含函数 。例如在下面的一个例子中,如果变量$somgthing为真 , 则将包含文件somefile:
if($something){
include("somefile");
}
但不管$something取何值,下面的代码将把文件somefile包含进文件里:
if($something){
require("somefile");
}
下面的这个有趣的例子充分说明了这两个函数之间的不同 。
$i = 1;
while ($i3) {
require("somefile.$i");
$i++;
}
在这段代码中,每一次循环的时候,程序都将把同一个文件包含进去 。很显然这不是程序员的初衷,从代码中我们可以看出这段代码希望在每次循环时 , 将不同的文件包含进来 。如果要完成这个功能,必须求助函数include():
$i = 1;
while ($i3) {
include("somefile.$i");
$i++;
}
6.注意echo和print的区别
PHP中echo和print的功能也基本相同,但是两者之间也有细微差别 。在PHP代码中可以把print作为一个普通函数来使用,例如执行下面的代码后变量$res的值将为1 。
$ret = print "Hello World";
这意味着print可用在一些复杂的表达式中,而echo则不行 。同样,在代码中echo语句的运行速度要略微快于print语句,因为echo语句不要求返回任何数值.
PHP流(Stream)的概述与使用详解 在现代 PHP 特性中,流或许是最出色但使用率最低的 。虽然 PHP 4.3 就引入了流,但是很多开发者并不知道流的存在,因为人们很少提及流,而且流的文档也很匮乏 。PHP 官方文档对流的解释如下:
可能看完这段解释后还是云里雾里,我们简化一下,流的作用是在出发地和目的地之间传输数据 。出发地和目的地可以是文件、命令行进程、网络连接、ZIP 或 TAR 压缩文件、临时内存、标准输入或输出,或者是通过 PHP 流封装协议实现的任何其他资源 。
如果你读写过文件,就用过流;如果你从php://stdin读取过数据,或者把输入写入php://stdout,也用过流 。流为 PHP 的很多 IO 函数提供了底层实现,如 file_get_contents、fopn、fread 和 fwrite 等 。PHP 的流函数提供了不同资源的统一接口 。
我们可以把流比作管道 , 把水(资源数据)从一个地方引到另一个地方 。在水从出发地到目的地的过程中,我们可以过滤水,可以改变水质,可以添加水 , 也可以排出水 。
流式数据的种类各异 , 每种类型需要独特的协议,以便读写数据 , 我们称这些协议为 流封装协议。例如,我们可以读写文件系统,可以通过 HTTP、HTTPS 或 SSH 与远程 Web 服务器通信,还可以打开并读写 ZIP、RAR 或 PHAR 压缩文件 。这些通信方式都包含下述相同的过程:
1.开始通信
2.读取数据
3.写入数据
4.结束通信
虽然过程是一样的 , 但是读写文件系统中文件的方式与收发 HTTP 消息的方式有所不同,流封装协议的作用是使用通用的接口封装这种差异 。
每个流都有一个协议和一个目标 。指定协议和目标的方法是使用流标识符:scheme://target,其中 scheme 是流的封装协议,target 是流的数据源 。
http://流封装协议
下面使用 HTTP 流封装协议创建了一个与 Flicker API 通信的 PHP 流:
不要以为这是普通的网页 URL,file_get_contents() 函数的字符串参数其实是一个流标识符 。http 协议会让 PHP 使用 HTTP 流封装协议 , 在这个参数中,http 之后是流的目标 。
我们通常使用 file_get_contents()、fopen()、fwrite() 和 fclose() 等函数读写文件系统,因为 PHP 默认使用的流封装协议是 file://,所以我们很少认为这些函数使用的是 PHP 流 。下面的示例演示了使用 file:// 流封装协议创建一个读写 /etc/hosts 文件的流:
我们通常会省略掉 file:// 协议,因为这是 PHP 使用的默认值 。
php://流封装协议
编写命令行脚本的 PHP 开发者会感激 php:// 流封装协议,这个流封装协议的作用是与 PHP 脚本的标准输入、标准输出和标准错误文件描述符通信 。我们可以使用 PHP 提供的文件系统函数打开、读取或写入下面四个流:
1. php://stdin :这是个只读 PHP 流,其中的数据来自标准输入 。PHP 脚本可以使用这个流接收命令行传入脚本的信息;
2. php://stdout :把数据写入当前的输出缓冲区 , 这个流只能写,无法读或寻址;
3. php://memory :从系统内存中读取数据,或者把数据写入系统内存 。缺点是系统内存有限 , 所有使用php://temp更安全;
4. php://temp :和php://memory类似,不过,没有可用内存时,PHP 会把数据写入这个临时文件 。
其他流封装协议
PHP 和 PHP 扩展还提供了很多其他流封装协议 , 例如,与 ZIP 和 TAR 压缩文件、FTP 服务器、数据压缩库、Amazon API、Dropbox API 等通信的流封装协议 。需要注意的是,PHP 中的 fopen()、fgets()、fputs()、feof() 以及 fclose() 等函数不仅可以用来处理文件系统中的文件,还可以在所有支持这些函数的流封装协议中使用 。
自定义流封装协议
我们还可以自己编写 PHP 流封装协议 。PHP 提供了一个示例 StreamWrapper 类,演示如何编写自定义的流封装协议,支持部分或全部 PHP 文件系统函数 。关于如何编写,具体请参考以下文档:
有些 PHP 流能够接受一系列可选的参数,这些参数叫流上下文 , 用于定制流的行为 。不同的流封装协议使用的流上下文有所不同,流上下文使用 stream_context_create() 函数创建 , 这个函数返回的上下文对象可以传入大多数文件系统函数 。
例如 , 你知道可以使用 file_get_contents() 发送 HTTP POST 请求吗?使用一个流上下文对象即可实现:
流过滤器
目前为止我们讨论了如何打开流 , 读取流中的数据 , 以及把数据写入流 。不过 , PHP 流真正强大的地方在于过滤、转换、添加或删除流中传输的数据,例如,我们可以打开一个流处理 Markdown 文件,在把文件内容读入内存的过程中自动将其转化为 HTML 。
运行该脚本,输出的都是大写字母:
我们还可以使用php://filter流封装协议把过滤器附加到流上,不过,使用这种方式之前必须先打开 PHP 流:
这个方式实现效果和 stream_filter_append() 函数一样,但是相比之下更为繁琐 。不过,PHP 的某些文件系统函数在调用后无法附加过滤器,例如 file() 和 fpassthru(),使用这些函数时只能使用php://filter流封装协议附加流过滤器 。
自定义流过滤器
我们还可以编写自定义的流过滤器 。其实 , 大多数情况下都要使用自定义的流过滤器,自定义的流过滤器是个 PHP 类,继承内置的 php_user_filter 类(),且必须实现 filter()、onCreate() 和 onClose() 方法,最后,必须使用 stream_filter_register() 函数注册自定义的流过滤器 。
然后,我们必须使用 stream_filter_register() 函数注册这个自定义的 DirtyWordsFilter 流过滤器:
第一个参数用于标识这个自定义过滤器的过滤器名,第二个参数是这个自定义过滤器的类名 。接下来就可以使用这个自定义的流过滤器了:
修改 test.txt 内容如下:
运行上面的自定义过滤器脚本,结果如下:
stream_bucket_append函数:为队列添加数据
stream_bucket_make_writeable函数:从操作的队列中返回一个数据对象
stream_bucket_new函数:为当前队列创建一个新的数据
stream_bucket_prepend函数:预备数据到队列
stream_context_create函数:创建数据流上下文
stream_context_get_default函数:获取默认的数据流上下文
stream_context_get_options函数:获取数据流的设置
stream_context_set_option函数:对数据流、数据包或者上下文进行设置
stream_context_set_params函数:为数据流、数据包或者上下文设置参数
stream_copy_to_stream函数:在数据流之间进行复制操作
stream_filter_append函数:为数据流添加过滤器
stream_filter_prepend函数:为数据流预备添加过滤器
stream_filter_register函数:注册一个数据流的过滤器并作为PHP类执行
stream_filter_remove函数:从一个数据流中移除过滤器
stream_get_contents函数:读取数据流中的剩余数据到字符串
stream_get_filters函数:返回已经注册的数据流过滤器列表
stream_get_line函数:按照给定的定界符从数据流资源中获取行
stream_get_meta_data函数:从封装协议文件指针中获取报头/元数据
stream_get_transports函数:返回注册的Socket传输列表
stream_get_wrappers函数:返回注册的数据流列表
stream_register_wrapper函数:注册一个用PHP类实现的URL封装协议
stream_select函数:接收数据流数组并等待它们状态的改变
stream_set_blocking函数:将一个数据流设置为堵塞或者非堵塞状态
stream_set_timeout函数:对数据流进行超时设置
stream_set_write_buffer函数:为数据流设置缓冲区
stream_socket_accept函数:接受由函数stream_ socket_server()创建的Socket连接
stream_socket_client函数:打开网络或者UNIX主机的Socket连接
stream_socket_enable_crypto函数:为一个已经连接的Socket打开或者关闭数据加密
stream_socket_get_name函数:获取本地或者网络Socket的名称
stream_socket_pair函数:创建两个无区别的Socket数据流连接
stream_socket_recvfrom函数:从Socket获取数据,不管其连接与否
stream_socket_sendto函数:向Socket发送数据,不管其连接与否
stream_socket_server函数:创建一个网络或者UNIX Socket服务端
stream_wrapper_restore函数:恢复一个事先注销的数据包
stream_wrapper_unregister函数:注销一个URL地址包
整合资料
本文整合于以下两篇文章
关于php数据流编程和php 数据处理的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息 , 记得收藏关注本站 。
推荐阅读
- 拼多多直播用的什么音乐,拼多多直播背景音乐
- thinkphp分割数组,分割数组js
- sqlserver2008没有右下角,sql server菜单栏没有
- 数显卡尺尺寸不准怎么维修,数显卡尺坏了怎么修理
- 公众号支付成功跳转,公众号支付成功跳转页面
- flutter是原生开发吗,flutter会取代原生吗
- 奇游未来之役亚服韩国服务器选择,奇游未来之役亚服韩国服务器选择什么
- 视频号直播怎么推流到直播间,视频号直播如何上推荐
- c语言vc图形库函数 vc++ 图形库