王新阳

wangxinyang

isset、array_key_exists判断数组键名是否存在的区别

由于 isset 属于 php 中的语言结构,而 array_key_exists 是函数,所以isset相对速度更快。

isset不只判断键名是否存在,还与键值有关,当键值为null时也返回 false,而array_key_exists则返回true。

MySQL old_passwords 问题(16位和41位加密模式)

mysqlnd cannot connect to MySQL 4.1+ using the old insecure authentication. Please use an administration tool to reset your password with the command SET PASSWORD = PASSWORD('your_existing_password'). This will store a new, and more secure, hash value in mysql.user. If this user is used in other scripts executed by PHP 5.2 or earlier you might need to remove the old-passwords flag from your my.cnf file

解决方法如下:

SET old_passwords = 0;
UPDATE mysql.user SET PASSWORD = PASSWORD( 'root' ) WHERE User = 'root' LIMIT 1 ;
SELECT LENGTH( PASSWORD ) FROM mysql.user WHERE User = 'root';
FLUSH PRIVILEGES ;

PHP运算符优先级

结合方向运算符附加信息
clone newclone 和 new
[array()
++ -- ~ (int) (float) (string) (array) (object) (bool) @类型递增/递减
instanceof类型
!逻辑运算符
* / %算术运算符
+ - .算术运算符字符串运算符
<< >>位运算符
== != === !== <>比较运算符
&位运算符引用
^位运算符
|位运算符
&&逻辑运算符
||逻辑运算符
? :三元运算符
= += -= *= /= .= %= &= |= ^= <<= >>= =>赋值运算符
and逻辑运算符
xor逻辑运算符
or逻辑运算符
,多处用到

对具有相同优先级的运算符,左结合方向意味着将从左向右求值,右结合方向则反之。对于无结合方向具有相同优先级的运算符,该运算符有可能无法与其自身结合。举例说,在 PHP 中 1 < 2 > 1 是一个非法语句,而 1 <= 1 == 1 则不是。因为 T_IS_EQUAL 运算符的优先级比 T_IS_SMALLER_OR_EQUAL 的运算符要低。

UTF-8、UNICODE互转

<?php
//UTF-8转UNICODE
function utf8_unicode($s)
{
	if (is_string($s)) {
		$s = mb_str_split($s);
	}
	$arr = array();
	$n = 0;
	for ($i = 0; $i < count($s); $i++) {
		switch (strlen($s[$i])) {
			case 1:
				$n = ord($s[$i]);
				break;
			case 2:
				$n = (ord($s[$i][0]) & 63) << 6;
				$n += ord($s[$i][1]) & 63;
				break;
			case 3:
				$n = (ord($s[$i][0]) & 31) << 12;
				$n += (ord($s[$i][1]) & 63) << 6;
				$n += ord($s[$i][2]) & 63;
				break;
			case 4:
				$n = (ord($s[$i][0]) & 15) << 18;
				$n += (ord($s[$i][1]) & 63) << 12;
				$n += (ord($s[$i][2]) & 63) << 6;
				$n += ord($s[$i][3]) & 63;
				break;
		}
		$arr[] = $n;
	}
	return $arr;
}
function mb_str_split($str, $charset = 'utf-8', $length = 1)
{
	if ($length < 1) {
		return FALSE;
	}
	$result = array();
	for ($i = 0; $i < mb_strlen($str, $charset); $i += $length) {
		$result[] = mb_substr($str, $i, $length, $charset);
	}
	return $result;
}
//UNICODE转UTF-8
function unicode_utf8($u)
{
	if (is_int($u)) {
		$u = array($u);
	}
	$arr = array();
	$tmp = '';
	for ($i = 0; $i < count($u); $i++) {
		if ($u[$i] < 128) {
			$tmp = $u[$i];
		} else {
			if ($u[$i] < 2048) {
				$tmp = chr(192 | $u[$i] >> 6);
				$tmp .= chr(128 | $u[$i] & 63);
			} else {
				if ($u[$i] < 65536) {
					$tmp = chr(224 | $u[$i] >> 12);
					$tmp .= chr(128 | $u[$i] >> 6 & 63);
					$tmp .= chr(128 | $u[$i] & 63);
				} else {
					if ($u[$i] < 2097152) {
						$tmp = chr(240 | $u[$i] >> 18);
						$tmp .= chr(128 | $u[$i] >> 12 & 63);
						$tmp .= chr(128 | $u[$i] >> 6 & 63);
						$tmp .= chr(128 | $u[$i] & 63);
					}
				}
			}
		}
		$arr[] = $tmp;
	}
	return $arr;
}

PHP生成静态页面

用PHP输出静态页面有2种方法
一种是利用模板技术,另一种是用ob系列函数。两种方法,看起来都差不多,但是实际上,却是不同的。


第一种:利用模板
目前PHP的模板可以说是很多了,有功能强大的smarty,还有简单易用的smarttemplate等。
它们每一种模板,都有一个获取输出内容的函数。我们生成静态页面的方法,就是利用了这个函数。用这个方法的优点是,代码比较清晰,可读性好。
这里我用smarty做例子,说明如何生成静态页


<?php
require('smarty/Smarty.class.php');
$t = new Smarty;
$t->assign("title","Hello World!");
$content = $t->fetch("templates/index.htm");
//这里的 fetch() 就是获取输出内容的函数,现在$content变量里面,就是要显示的内容了
$fp = fopen("archives/2005/05/19/0001.html", "wb");
fwrite($fp, $content);
fclose($fp);
?>


第二种方法:利用ob系列的函数
这里用到的函数主要是 ob_start(), ob_end_flush(), ob_get_content(),
其中ob_start()是打开浏览器缓冲区的意思,打开缓冲后,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区,直到你使用了ob_end_flush()。而这里最重要的一个函数,就是ob_get_contents(),这个函数的作用是获取缓冲区的内容,相当于上面的那个fetch(),道理一样的。代码:


<?php
ob_start();
$fp = fopen("ip.html", "wb");
fwrite($fp, ob_get_contents());//取得php页面输出的全部内容
fclose($fp);
ob_end_clean();
?>

PHP遍历文件件

<?php
$dir = '.';
//当前目录
list_file($dir);
function list_file($dir)
{
    $list = scandir($dir);
    // 得到该文件下的所有文件和文件夹
    foreach ($list as $file) {
        //遍历
        $file_location = $dir . '/' . $file;
        //生成路径
        if (is_dir($file_location) && $file != '.' && $file != '..') {
            //判断是不是文件夹
            echo "------------------------sign in {$file_location}------------------";
            echo '<br>';
            list_file($file_location);
        } else {
            echo is_file($dir . '/' . $file) ? $dir . '/' . $file . '<br>' : '';
        }
    }
}

如遇文件名显示乱码,可用mb_convert_encoding 或 iconv 转换

文本内容return array()的使用

方法一:
a.txt或a.php内容:
return array(
    0 => 'hello',
    1 => 'world',
);

调用:
<?php
$arr = eval(file_get_contents('a.txt'));
?>


方法二:
a.php内容:

<?php
return array(
    0 => 'hello',
    1 => 'world',
);
?>

调用:
<?php
$arr = @include $path.'a.php';
?>

PHP保存远程文件到本地

echo httpcopy("http://www.baidu.com/img/baidu_sylogo1.gif");

function httpcopy($url, $file="", $timeout=60) {
	$file = empty($file) ? pathinfo($url,PATHINFO_BASENAME) : $file;
	$dir = pathinfo($file,PATHINFO_DIRNAME);
	!is_dir($dir) && @mkdir($dir,0755,true);
	$url = str_replace(" ","%20",$url);

	if(function_exists('curl_init')) {
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
		$temp = curl_exec($ch);
		if(!curl_error($ch)){
			$dest = fopen($file, 'wb');
			fwrite($dest, $temp);
			fclose($dest);
			return $file;
		}else{
			return false;
		}
	}elseif(function_exists('copy')) {
		$opts = array(
			"http"=>array(
			"method"=>"GET",
			"header"=>"",
			"timeout"=>$timeout)
		);
		$context = stream_context_create($opts);
		if(@copy($url, $file, $context)) {
			//$http_response_header
			return $file;
		} else {
			return false;
		}
	}else{
		$temp=fopen($url,'rb');
		if($temp){
			$newf=fopen($file,'wb');
			if($newf){
				while(!feof($temp)){
					fwrite($newf,fread($temp,1024*8),1024*8);
				}
			}
			if($temp){
				fclose($temp);
			}
			if($newf){
				fclose($newf);
			}
			return $file;
		}
	}
}

简单的PHP采集示例

<?php
header('Content-type: text/html; charset=utf-8');
set_time_limit(900);
$a=<<<EOD
复制html内容到这里
EOD;
//获取需要的链接
preg_match_all('/\\/chapter\\/110701\\/\\d+\\.html/i', $a, $arr);
//得到完整链接地址
$arr = explode(',', 'http://vip.book.sina.com.cn' . implode(',http://vip.book.sina.com.cn', $arr[0]));
$b = '文章正文内容开始前面的html';
$c = '/正则匹配章节标题和章节内容之间的html,如果此部门内容没有时间等不同的字符,可以直接用str_replace而不是preg_replace';
$e = '文章正文内容结束后面的html';
$result = '';
//要获取的文章内容
$txt = fopen('e:/web/abc.txt', 'wb');
ob_start();
for ($i = 0; $i < count($arr); $i++) {
	$result = '';
	$str = file_get_contents($arr[$i]);
	//也可以用curl
	$str = explode($b, $str);
	$str = explode($e, count($str) > 1 ? $str[1] : $str[0]);
	$str = explode('</h1>', $str[0], 2);
	$result = $str[0] . "\r\n";
	$str = preg_replace($c, '', $str[1]);
	$str = str_replace('<p>', '', $str);
	$str = str_replace('</p>', "\r\n", $str);
	$result .= $str;
	fwrite($txt, $result);
	echo str_replace("\r\n", '<br />', $result);
	flush();
}
fclose($txt);


file_get_contents()抓取 https 地址时出错:
SSL operation failed with code 1. OpenSSL Error message

原因是证书校验不通过,可以设置忽略证书校验:

$option=array(
	'ssl'=>array('verify_peer' => false, 'verify_peer_name' => false)
);
$stream=stream_context_create($option);
file_get_contents($url, false, $stream);

PHP curl示例

cur进行https请求时,如果出现 curl: (35) SSL connect error
一般是发起请求的服务器ssl_version为 NSS 需要改为 openSSL

/**
 * 通过curl请求远程数据
 * @param string $url
 * @param string $request_method 默认GET
 * @param array $post_data 默认null
 * @param string $do_what http_build_query/json_encode
 * @param array $opt_array 批量设置特殊选项
 * @return FALSE | string
 */
function my_curl($url, $request_method='GET', $post_data=NULL, $do_what='', $opt_array=NULL){
	$arr_header = array();
	if($post_data){
		switch($do_what){
			case 'json_encode': //需要发送json数据时,对数组或对象进行json编码(微信开发此处不能包含中文,否则会有:不合法的请求字符,不能包含\uxxxx格式的字符)
				$post_data = json_encode($post_data);
				$arr_header[] = 'Content-length: '.strlen($post_data);
				break;
			case 'http_build_query':
				$post_data = http_build_query($post_data); //对数组或对象使用http_build_query()以提高兼容性
				$arr_header[] = 'Content-length: '.strlen($post_data);
				break;
			default:
		}
	}
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $url);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //curl_exec执行成功则返回结果(默认返回true),失败返回false
	curl_setopt($ch, CURLOPT_HEADER, false); //启用时会将头文件的信息作为数据流输出
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); //连接超时时间
	if(count($arr_header))curl_setopt($ch, CURLOPT_HTTPHEADER, $arr_header);
	if(strtolower($request_method)=='post')curl_setopt($ch, CURLOPT_POST, true); //POST方式时添加
	if(strpos(strtolower($url), 'https://')===0){
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //https请求时跳过cURL验证对等证书
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //https请求时跳过cURL验证域名
	}
	if($post_data)curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
	if(is_array($opt_array) && count($opt_array))curl_setopt_array($ch, $opt_array);
	$output = curl_exec($ch);
//	$outinfo = curl_getinfo($ch);
	$err_no = curl_errno($ch);
	$curl_error = $err_no ?  'curl: '.curl_error($ch)." $err_no" : ''; //失败时返回当前会话最后一次错误的字符串
	curl_close($ch);
	if($err_no){
		log_message('error', $curl_error);
		return FALSE;
	}else{
		return $output;
	}
}
2024-05-11 星期六 农历四月初四