首页 > PHP教程

多核编程中的负载平衡难题

多核CPU中,要很好地发挥出多个CPU的性能的话,必须保证分配到各个CPU上的任务有一个很好的负载平衡。否则一些CPU在运行,另外一些CPU处于空闲,无法发挥出多核CPU的优势来。


  要实现一个好的负载平衡通常有两种方案,一种是静态负载平衡,另外一种是动态负载平衡。


  1、静态负载平衡


  静态负载平衡中,需要人工将程序分割成多个可并行执行的部分,并且要保证分割成的各个部分能够均衡地分布到各个CPU上运行,也就是说工作量要在多个任务间进行均匀的分配,使得达到高的加速系数。


  静态负载平衡问题从数学上来说是一个NP完全性问题,Richard M. Karp, Jeffrey D. Ullman, Christos H. Papadimitriou, M. Garey, D. Johnson等人相继在1972年到1983年间证实了静态负载问题在几种不同约束条件下的NP完全性。


  虽然NP完全性问题在数学上是难题,但是这并不是标题中所说的难题,因为NP完全性问题一般都可以找到很有效的近似算法来解决。


  2、动态负载平衡


  动态负载平衡是在程序的运行过程中来进行任务的分配达到负载平衡的目的。实际情况中存在许多不能由静态负载平衡解决的问题,比如一个大的循环中,循环的次数是由外部输入的,事先并不知道循环的次数,此时采用静态负载平衡划分策略就很难实现负载平衡。


  动态负载平衡中对任务的调度一般是由系统来实现的,程序员通常只能选择动态平衡的调度策略,不能修改调度策略,由于实际任务中存在很多的不确定因素,调度算法无法做得很优,因此动态负载平衡有时可能达不到既定的负载平衡要求。


  3、负载平衡的难题在那里?


  负载平衡的难题并不在于负载平衡的程度要达到多少,因为即使在各个CPU上分配的任务执行时间存在一些差距,但是随着CPU核数的增多总能让总的执行时间下降,从而使加速系数随CPU核数的增加而增加。


  负载平衡的困难之处在于程序中的可并行执行块很多要靠程序员来划分,当然CPU核数较少时,比如双核或4核,这种划分并不是很困难。但随着核数的增加,划分的粒度将变得越来越细,到了16核以上时,估计程序员要为如何划分任务而抓狂。比如一段顺序执行的代码,放到128核的CPU上运行,要手工划分成128个任务,其划分的难度可想而知。


  负载划分的误差会随着CPU核数的增加而放大,比如一个需要16个时间单位的程序分到4个任务上执行,平均每个任务上的负载执行时间为4个时间单位,划分误差为1个时间单位的话,那么加速系数变成 16/(4 1)=3.2,是理想情况下加速系数 4的80%。但是假如放到一个16核CPU上运行的话,假如某个任务的划分误差假如为0.5个时间单位的话,那么加速系数变成16/(1 0.5) = 10.67,只有理想的加速系数16的66.7%,假如核数再增加的话,由于误差的放大,加速系数相比于理想加速系数的比例还会下降。


  负载划分的难题还体现在CPU和软件的升级上,比如在4核CPU上的负载划分是均衡的,但到了8核、16核上,负载也许又变得不均衡了。软件升级也一样,当软件增加功能后,负载平衡又会遭到破坏,又需要重新划分负载使其达到平衡,这样一来软件设计的难度和麻烦大大增加了。


  假如使用了锁的话,一些看起来是均衡的负载也可能会由于锁竞争变得不平衡起来。


  4、负载平衡的应对策略


  对于运算量较小的软件,即使放到单核CPU上运行速度也很快,负载平衡做得差一些并没有太大影响,实际中负载平衡要考虑的是大运算量和规模很大的软件,这些软件需要在多核上进行负载平衡才能较好地利用多核来提高性能。


  对于大规模的软件,负载平衡方面采取的应对策略是发展划分并行块的宏观划分方法,从整个软件系统层面来进行划分,而不是象传统的针对某些局部的程序和算法来进行并行分解,因为局部的程序通常都很难分解成几十个以上的任务来运行。


  另外一个应对策略是在工具层面的,也就是编译工具能够协助人工进行并行块的分解,并找出良好的分解方案来,这方面Intel已经作出了一些努力,但是还需要更多的努力让工具的功能更强大一些才能应对核数较多时的情况。

阅读全文

PHP程序中的特效应用实用代码珍藏

禁止屏蔽类

  1.禁止右键

<body oncontextmenu=return(false)>

  2.禁止选择

<body onselectstart="return false">

  3.禁止粘贴

<body onpaste="return false">
 
  4.禁止直接访问 [必须框架内才行]

<script>
if (top == self)top.location.href = "page.htm";
</script>

  5.禁止frame引用

<script>
if (top != self)top.location.href = "page.htm";
</script>

  6.禁止功能键Shift,Alt,Ctrl

<script>function key(){
if(event.shiftKey) alert("Shift不答应使用!");} document.onkeydown=key; </script>

  数据取得类

  1.取得分辨率

<script>document.write("宽为" screen.Width "高为" screen.Height)</script>

  2.取得地址栏

<script>document.write(self.location)</script>

  3.取得地址栏后参数

<SCRIPT>var add = top.location;
add = add.toString();
document.write (add.substring(add.indexOf("?") 1,add.length));
</SCRIPT>

阅读全文

兼容性最强的PHP生成缩略图的代码

function ImageResize($srcFile,$toW,$toH,$toFile="")
{
if($toFile==""){ $toFile = $srcFile; }
$info = "";
$data = GetImageSize($srcFile,$info);
switch ($data[2])
{
case 1:
if(!function_exists("imagecreatefromgif")){
echo "你的GD库不能使用GIF格式的图片,请使用Jpeg或PNG格式!<a href=java script:go(-1);>返回</a>";
exit();
}
$im = ImageCreateFromGIF($srcFile);
break;
case 2:
if(!function_exists("imagecreatefromjpeg")){
echo "你的GD库不能使用jpeg格式的图片,请使用其它格式的图片!<a href=java script:go(-1);>返回</a>";
exit();
}
$im = ImageCreateFromJpeg($srcFile);
break;
case 3:
$im = ImageCreateFromPNG($srcFile);
break;
}
$srcW=ImageSX($im);
$srcH=ImageSY($im);
$toWH=$toW/$toH;
$srcWH=$srcW/$srcH;
if($toWH<=$srcWH){
$ftoW=$toW;
$ftoH=$ftoW*($srcH/$srcW);
}
else{
$ftoH=$toH;
$ftoW=$ftoH*($srcW/$srcH);
}
if($srcW>$toW||$srcH>$toH)
{
if(function_exists("imagecreatetruecolor")){
@$ni = ImageCreateTrueColor($ftoW,$ftoH);
if($ni) ImageCopyResampled($ni,$im,0,0,0,0,$ftoW,$ftoH,$srcW,$srcH);
else{
$ni=ImageCreate($ftoW,$ftoH);
ImageCopyResized($ni,$im,0,0,0,0,$ftoW,$ftoH,$srcW,$srcH);
}
}else{
$ni=ImageCreate($ftoW,$ftoH);
ImageCopyResized($ni,$im,0,0,0,0,$ftoW,$ftoH,$srcW,$srcH);
}
if(function_exists(imagejpeg)) ImageJpeg($ni,$toFile);
else ImagePNG($ni,$toFile);
ImageDestroy($ni);
}
ImageDestroy($im);
}

阅读全文

动态网页制作技术PHP处理时间的实例

<?
/**
* 转换为UNIX时间戳
*/
function gettime($d) {
if(is_numeric($d))
return $d;
else {
if(! is_string($d)) return 0;
if(ereg(":",$d)) {
$buf = split(" ",$d);
$year = split("[-/]",$buf[0]);
$hour = split(":",$buf[1]);
if(eregi("pm",$buf[2]))
$hour[0] = 12;
return mktime($hour[0],$hour[1],$hour[2],$year[1],$year[2],$year[0]);
}else {
$year = split("[-/]",$d);
return mktime(0,0,0,$year[1],$year[2],$year[0]);
}
}
}

/**
*
* DateAdd(interval,number,date)
* 返回已添加指定时间间隔的日期。
* Inetrval为表示要添加的时间间隔字符串表达式,例如分或天
* number为表示要添加的时间间隔的个数的数值表达式
* Date表示日期
*
* Interval(时间间隔字符串表达式)可以是以下任意值:
* yyyy year年
* q Quarter季度
* m Month月
* y Day of year一年的数
* d Day天
* w Weekday一周的天数
* ww Week of year周
* h Hour小时
* n Minute分
* s Second秒
* w、y和d的作用是完全一样的,即在目前的日期上加一天,q加3个月,ww加7天。
*/
function DateAdd($interval, $number, $date) {
$date = gettime($date);
$date_time_array = getdate($date);
$hours = $date_time_array["hours"];
$minutes = $date_time_array["minutes"];
$seconds = $date_time_array["seconds"];
$month = $date_time_array["mon"];

阅读全文

PHP当中取得Url及物理路径的总结

在这里我想总结一下取得地址栏内URL及文件所属的我更路径的一些信息:

运用$_SERVER[ ]我们可以来完成许多事情:它是一个包含头部(headers),路径信息及脚本位置的数组,数组的实体由web服务器创建。

这是一个“superglobal”,或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中您不需要使用global $_SERVER; 访问它,就如同使用 $HTTP_SERVER_VARS 一样。 $HTTP_SERVER_VARS 包含着同样的信息,但是不是一个自动全局变量。(注重: $HTTP_SERVER_VARS 和 $_SERVER 是不同的变量,PHP 处理它们的方式不同。)假如设置了 register_globals 指令,这些变量也在所有脚本中可用;也就是,分离了 $_SERVER 和 $HTTP_SERVER_VARS 数组。

$_SERVER[HTTP_HOST] 取得当前请求的Host:头部内容
$_SERVER[PHP_SELF]这可能是我们最为经常用到的了,它返回当前调用 的页的文件名,假如是http://localhost/test/2005/test.php, 那么将会返回/test/2005/test.php

$_SERVER[SCRIPT_NAME]它将返回包含当前脚本的路径。这在页面需要指向自己时非常有用

$_SERVER[SCRIPT_FILENAME]它将返回当前文件所在的绝对路径信息

$_SERVER[REQUEST_URI]返回访问此页面所需的URI,包括"/"


当然还有许多路径函数:

dirname(),返回路径信息中的目录部分,前面是带有"/"的


basename()返回路径中的基本的文件名部分,当然也可以设置后缀来控制输出。

realpath(),返回路径信息的绝对规范化的路径

阅读全文

通过PHP来实现登录验证码功能

通过PHP来实现登录验证码功能:

<?php
session_start();
session_register("login_check_number");
//昨晚看到了chianren上的验证码效果,就考虑了一下,用PHP的GD库完成了类似功能
//先成生背景,再把生成的验证码放上去
$img_height=120; //先定义图片的长、宽
$img_width=40;
if($HTTP_GET_VARS["act"]== "init"){
//srand(microtime() * 100000);//PHP420后,srand不是必须的
for($Tmpa=0;$Tmpa<4;$Tmpa ){
$nmsg.=dechex(rand(0,15));
}//by sports98


$HTTP_SESSION_VARS[login_check_number] = $nmsg;

//$HTTP_SESSION_VARS[login_check_number] = strval(mt_rand("1111","9999")); //生成4位的随机数,放入session中
//谁能做下补充,可以同时生成字母和数字啊??----由sports98完成了

$aimg = imageCreate($img_height,$img_width); //生成图片
ImageColorAllocate($aimg, 255,255,255); //图片底色,ImageColorAllocate第1次定义颜色PHP就认为是底色了
$black = ImageColorAllocate($aimg, 0,0,0); //定义需要的黑色
ImageRectangle($aimg,0,0,$img_height-1,$img_width-1,$black);//先成一黑色的矩形把图片包围

//下面该生成雪花背景了,其实就是在图片上生成一些符号
for ($i=1; $i<=200; $i ) { //先用100个做测试
imageString($aimg,1,mt_rand(1,$img_height),mt_rand(1,$img_width),"*",imageColorAllocate($aimg,mt_rand(200,255),mt_rand(200,255),mt_rand(200,255)));
//哈,看到了吧,其实也不是雪花,就是生成*号而已。为了使它们看起来"杂乱无章、5颜6色",就得在1个1个生成它们的时候,让它们的位置、颜色,甚至大小都用随机数,rand()或mt_rand都可以完成。
}

//上面生成了背景,现在就该把已经生成的随机数放上来了。道理和上面差不多,随机数1个1个地放,同时让他们的位置、大小、颜色都用成随机数~~
//为了区别于背景,这里的颜色不超过200,上面的不小于200
for ($i=0;$i<strlen($HTTP_SESSION_VARS[login_check_number]);$i ){
imageString($aimg, mt_rand(4,8),$i*$img_height/4 mt_rand(1,10),mt_rand(1,$img_width/2), $HTTP_SESSION_VARS[login_check_number][$i],imageColorAllocate($aimg,mt_rand(0,100),mt_rand(0,150),mt_rand(0,200)));
}
Header("Content-type: image/png"); //告诉浏览器,下面的数据是图片,而不要按文字显示
ImagePng($aimg); //生成png格式。。。嘿嘿效果蛮像回事的嘛。。。
ImageDestroy($aimg);
}

?>

阅读全文

把静态变量作为Cache使用

我猜你们肯定都碰到过以下的情况
我有两个表,magazine(杂志信息)和subscibe(订阅信息),在subscibe表内我有一个magazine_id来和magazine表内的编号关联
现在我要做一个浏览订阅信息的列表,这个列表内有一列是显示杂志名称的(magazine表的name字段),有一种办法是使用join在这两个表之间做一个关联,把magazine_id都替换成为name,但是这个列表是一个搜索结果,sql查询语句是拼接而成的,假如再加上join,拼接sql的逻辑会变得有点复杂,所以还是简单的弄一个select * from subscibe where ....,然后把结果集内的magazine_id拿来查询会比较简单一点,这又出现另外的问题就是我不想在我的程序里出现过多的重复查询,比如结果集内有10条数据都是关于同一个magazine_id,我就会多出9条重复的查询,于是我决定这样干

function MagazineInfoById($magazine_id){
global $db;
static $magazine_info;

if (!isset($magazine_info[$magazine_id])){
$magazine_info[$magazine_id] = $db->getRow(select * from magazine where id = . $magazine_id);
}

return $magazine_info[$magazine_id];
}

while (....){
$magazine_info = MagazineInfoById($magazine_id);
.....
}


MagazineInfoById()内的静态变量$magazine_info就成为了一个缓存形式的东西,在某些情况下,可以大大的降低查询的次数,避免重复的查询

阅读全文

获取客户端IP的方法代码

//
//获取客户端IP
//
function GetIP()
{
if(!empty($_SERVER["HTTP_CLIENT_IP"]))
$cip = $_SERVER["HTTP_CLIENT_IP"];
else if(!empty($_SERVER["HTTP_X_FORWARDED_FOR"]))
$cip = $_SERVER["HTTP_X_FORWARDED_FOR"];
else if(!empty($_SERVER["REMOTE_ADDR"]))
$cip = $_SERVER["REMOTE_ADDR"];
else
$cip = "无法获取!";
return $cip;
}

阅读全文

PHP读取汉字点阵数据

鑳屾櫙鐭ヨ瘑锛欬br />
銆€銆€銆€绠€浣撲腑鏂囧浗鏍囧瓧搴擄紙1981骞磋锛屼腑鍥藉ぇ闄嗭級銆?445涓瓧绗︼紝鍏朵腑姹夊瓧6773涓紝鍖呮嫭涓€绾ф眽瀛?755涓紝浜岀骇姹夊瓧3008涓€傞噰鐢?瀛楄妭锛?6浣嶄簩杩涘埗锛夌紪鐮併€侟br />
銆€銆€鍖轰綅鐮侊細鍥芥爣GB2312瑙勫畾,鎵€鏈夌殑鍥芥爣姹夊瓧涓庣鍙风粍鎴愪竴涓?4×94鐨勭煩闃点€傚湪姝ゆ柟闃典腑,姣忎竴琛岀О涓轰竴涓?rdquo;鍖?rdquo;,姣忎竴鍒楃О涓轰竴涓?rdquo;浣?rdquo;,鍥犳,杩欎釜鏂归樀瀹為檯涓婄粍鎴愪簡涓€涓湁94涓尯(鍖哄彿鍒嗗埆涓? 1鍒?4)銆佹瘡涓尯鍐呮湁94涓綅(浣嶅彿鍒嗗埆涓?1鍒?4)鐨勬眽瀛楀瓧绗﹂泦銆備竴涓眽瀛楁墍鍦ㄧ殑鍖哄彿鍜屼綅鍙风畝鍗曞湴缁勫悎鍦ㄤ竴璧峰氨鏋勬垚浜嗚姹夊瓧鐨?rdquo;鍖轰綅鐮?rdquo;銆傚湪姹夊瓧鐨勫尯浣嶇爜涓?楂樹袱浣嶄负鍖哄彿,浣庝袱浣嶄负浣嶅彿銆傜敱姝ゅ彲瑙?鍖轰綅鐮佷笌姹夊瓧鎴栫鍙蜂箣闂存槸涓€涓€瀵瑰簲鐨勩€侟br />
銆€銆€鍐呯爜锛氭眽瀛楃殑鍐呯爜鏄寚鍦ㄨ绠楁満涓〃绀烘眽瀛楃殑缂栫爜銆傛満鍐呯爜涓庡尯浣嶇爜绋嶆湁鍖哄埆銆備负浠€涔堜笉鐩存帴鐢ㄥ尯浣嶇爜浣滀负璁$畻鏈哄唴鐨勭紪鐮佸憿? 杩欐槸鍥犱负姹夊瓧鐨勫尯鐮佸拰浣嶇爜鐨勮寖鍥撮兘鍦?鍒?4鍐? 鍋囧鐩存帴鐢ㄥ尯浣嶇爜浣滄満鍐呯爜, 灏变細涓庡熀鏈珹SCII鐮佸啿绐併€ 姹夊瓧鐨勫唴鐮侀€氬父涓庢墍浣跨敤鐨勮绠楁満绯荤粺鏈夊叧銆傜洰鍓?瀵逛簬鍥藉唴澶у鏁扮殑璁$畻鏈虹郴缁?涓€涓眽瀛楃殑鍐呯爜鍗犱袱涓瓧鑺?鍒嗗埆绉颁负楂樹綅瀛楄妭涓庝綆浣嶅瓧鑺?涓旇繖涓や綅瀛楄妭涓庡尯浣嶇爜鐨勫叧绯诲涓婜 鍐呯爜楂樹綅=鍖虹爜 A0H(H琛ㄧず鍗佸叚杩涘埗) 鍐呯爜浣庝綅=浣嶇爜 A0H 渚嬪,姹夊瓧”鍟?rdquo;鐨勫尯浣嶇爜涓?rdquo;1601″,鍖虹爜鍜屼綅鐮佸垎鍒敤鍗佸叚杩涘埗琛ㄧず鍗充负”1001H”,鍒欏畠鐨勫唴鐮佷负”B0A1H”銆傚叾涓瑽0H涓哄唴鐮佺殑楂樹綅瀛楄妭,A1H涓哄唴鐮佺殑浣庝綅瀛楄妭銆侟br />
銆€銆€PHP浠g爜锛氳繑鍥炵敱0鍜?缁勬垚鐨勫瓧绗︿覆銆侟br /><?php
/**
* 璇诲彇姹夊瓧鐐归樀鏁版嵁
*/

$str = "涓崕浜烘皯鍏卞拰鍥?quot;;

$font_file_name = "simsun12.fon"; // 鐐归樀瀛楀簱鏂囦欢鍚岦br />$font_width = 12; // 鍗曞瓧瀹藉害
$font_height = 12; // 鍗曞瓧楂樺害
$start_offset = 0; // 鍋忕Щ

$fp = fopen($font_file_name, "rb");

$offset_size = $font_width * $font_height / 8;
$string_size = $font_width * $font_height;
$dot_string = "";

for ($i = 0; $i < strlen($str); $i )
{
if (ord($str{$i}) >160)
{
// 鍏堟眰鍖轰綅鐮侊紝鐒跺悗鍐嶈绠楀叾鍦ㄥ尯浣嶇爜浜岀淮琛ㄤ腑鐨勪綅缃紝杩涜€屽緱鍑烘瀛楃鍦ㄦ枃浠朵腑鐨勫亸绉狐br />$offset = ((ord($str{$i}) - 0xa1) * 94 ord($str{$i 1}) - 0xa1) * $offset_size;
$i ;
}
else
{
$offset = (ord($str{$i}) 156 - 1) * $offset_size;
}

// 璇诲彇鍏剁偣闃垫暟鎹?br />fseek($fp, $start_offset $offset, SEEK_SET);
$bindot = fread($fp, $offset_size);

for ($j = 0; $j < $offset_size; $j )
{
// 灏嗕簩杩涘埗鐐归樀鏁版嵁杞寲涓哄瓧绗︿覆
$dot_string .= sprintf("b", ord($bindot{$j}));
}
}

fclose($fp);

echo $dot_string;
?>

阅读全文

自定义PHP分页函数

<?
//为了避免重复包含文件而造成错误,加了判定函数是否存在的条件:
if(!function_exists(pageft)){
//定义函数pageft(),三个参数的含义为:
//$totle:信息总数;
//$displaypg:每页显示信息数,这里设置为默认是20;
/http://pic4.phprm.com/2013/09/05/$url.jpg:分页导航中的链接,除了加入不同的查询信息“page”外的部分都与这个URL相同。
//   默认值本该设为本页URL(即$_SERVER["REQUEST_URI"]),但设置默认值的右边只能为常量,所以该默认值设为空字符串,在函数内部再设置为本页URL。
function pageft($totle,$displaypg=20,$url=){

//定义几个全局变量:
//$page:当前页码;
//$firstcount:(数据库)查询的起始项;
//$pagenav:页面导航条代码,函数内部并没有将它输出;
//$_SERVER:读取本页URL“$_SERVER["REQUEST_URI"]”所必须。
global $page,$firstcount,$pagenav,$_SERVER;

//为使函数外部可以访问这里的“$displaypg”,将它也设为全局变量。注重一个变量重新定义为全局变量后,原值被覆盖,所以这里给它重新赋值。
$GLOBALS["displaypg"]=$displaypg;

if(!$page) $page=1;

//假如$url使用默认,即空值,则赋值为本页URL:
if(!$url){ $url=$_SERVER["REQUEST_URI"];}

//URL分析:
$parse_url=parse_url(/$url);
$url_query=$parse_url["query"]; //单独取出URL的查询字串
if($url_query){
//因为URL中可能包含了页码信息,我们要把它去掉,以便加入新的页码信息。
//这里用到了正则表达式,请参考“PHP中的正规表达式”(http://www.pconline.com.cn/pcedu/empolder/wz/php/10111/15058.html)
$url_query=ereg_replace("(^|&)page=$page","",$url_query);

//将处理后的URL的查询字串替换原来的URL的查询字串:
$url=str_replace($parse_url["query"],$url_query,$url);

//在URL后加page查询信息,但待赋值:
if($url_query) $url.="&page"; else $url.="page";
}else {
$url.="?page";
}

页码计算:
$lastpg=ceil($totle/$displaypg); //最后页,也是总页数
$page=min($lastpg,$page);
$prepg=$page-1; //上一页
$nextpg=($page==$lastpg ? 0 : $page 1); //下一页
$firstcount=($page-1)*$displaypg;

阅读全文

PHP中对数据库操作的封装

现在我们把其封装在dbfz.inc中,其设计如下:
<?
class dbInterface{ var $dbID=1; //用于确定当前操作的数据库,当dbID为1代表MySql,当为 2代表 SQL Server,为3时为ODBC或其它。
var $dbHost; //数据库所在主机域名
var $dbUsername; //数据库用户名
var $dbPassword; //用户密码
//设置主机、用户名及密码函数
function setParameter($host,$username,$password){
$this->dbUsername=$username;
$this->dbHost=$host;
$this->dbPassword=$password;
}
//联接数库函数
function dbConnect(){
switch($this->dbID)
{
case 1;
return @mysql_connect($this->dbHost,$this->dbUsername,$this->dbPassword);
case 2;
//用支持SQL Server的函数
case 3;
//用支持ODBC的函数
}
}
//关闭数库函数
function dbClose($dataHandle){
switch($this->dbID)
{
case 1;
mysql_close($dataHandle);
case 2;
//用支持SQL Server的函数
case 3;
//用支持ODBC的函数
}
}

//执行SQL语句函数
function dbQuery($dbName,$sql,$dbHandle){
switch($this->dbID)
{
case 1;
return @mysql_db_query($dbName,$sql,$dbHandle);
case 2;
//用支持SQL Server的函数
case 3;
//用支持ODBC的函数
}
}

//检索SQL返回值的当前记录函数
function dbFetchrow($dataHandle,$offset=-1){
switch($this->dbID)
{
case 1;
@mysql_data_seek($dataHandle,$offset);
return @mysql_fetch_row($dataHandle);
case 2;
//用支持SQL Server的函数
case 3;
//用支持ODBC的函数
}
}
//返回检索记录数函数
function dbNumrows($dataHandle){
switch($this->dbID)
{
return @mysql_num_rows($dataHandle);
case 2;
//用支持SQL Server的函数
case 3;
//用支持ODBC的函数
}
}


//返回检索列数函数
function dbNumcols($dataHandle){

阅读全文

PHP面向对象编程快速入门

面向对象编程(OOP)是我们编程的一项基本技能,PHP4对OOP提供了良好的支持。如何使用OOP的思想来进行PHP的高级编程,对于提高PHP编程能力和规划好Web开发构架都是非常有意义的。下面我们就通过实例来说明使用PHP的OOP进行编程的实际意义和应用方法。

我们通常在做一个有数据库后台的网站的时候,都会考虑到程序需要适用于不同的应用环境。和其他编程语言有所不同的是,在PHP中,操作数据库的是一系列的具体功能函数(假如你不使用ODBC接口的话)。这样做虽然效率很高,但是封装却不够。假如有一个统一的数据库接口,那么我们就可以不对程序做任何修改而适用于多种数据库,从而使程序的移植性和跨平台能力都大大提高。

在PHP中要完成OOP,需要进行对象封装,也就是编写类。我们可以通过生成一个新的SQL类实现对数据库的简单封装。例如:

<?
class SQL
{
var $Driver; //实际操作的数据库驱动子类
var $connection; //共用的数据库连接变量
function DriverRegister($d)
{
if($d!="")
{
$include_path = ini_get("include_path");
$DriverFile = $include_path."/".$d.".php";
//驱动的存放路径必须在PHP.ini文件中设定的INCLUDE_PATH下
if( file_exists( $DriverFile)) //查找驱动是否存在
{
include($DriverFile);
$this->Driver = new $d();
// 根据驱动名称生成相应的数据库驱动类
return true;
}
}
return false; //注册驱动失败
}
function Connect($host,$user,$passwd,$database)//连接数据库的函数
{
$this->Driver->host=$host;
$this->Driver->user=$user;
$this->Driver->passwd=$pas
swd;
$this->Driver->database=$d
atabase;
$this->connection = $this->Driver->Connect();
}
function Close()//关闭数据库函数
{
$this->Driver->close($this->connection);
}
function Query($queryStr)//数据库字符串查询函数
{
return $this->Driver->query($queryStr,$this->connection);
}
function getRows($res)//查找行
{
return $this->Driver->getRows($res);
}
function getRowsNum($res)//取得行号
{
return $this->Driver-> getRowsNum ($res);
}
}
?>

阅读全文