存档

‘PHP’ 分类的存档

BLOG重新开放.

2010年2月27日

SORRY, 最近太忙太忙, 心思也比较倦怠, 最大的喜事是我儿子于2010.1.10顺利诞生了, 一切平安.

博客评论功能已经重新开放了, 欢迎大家评论.

另外我的服务器挺快的, 但是运行wordpress我自己很明显的感觉到打开wordpress的速度太慢了, 受不了. 准备近期换BLOG系统, 我目前正在开发的PHP版本的SmallMVC框架即将完工, 稍后将会使用本框架重新开发一个BLOG系统代替目前的.

感谢大家支持.

admin PHP

PHP截取等长中英文混合UTF8编码字符串

2009年8月12日
/*utf8编码时截取等长中英文字串*/ //英文标点[.,\"\\?!:_']   
<?   
function substr_utf8($string,$start,$length)   
{       //by aiou   
     $chars = $string;   
     //echo $string[0].$string[1].$string[2];   
     $i=0;   
     do{   
        if (preg_match ("/[0-9a-zA-Z]/", $chars[$i])){//纯英文   
            $m++;   
        }   
    else {$n++;     }//非英文字节,   
        $k = $n/3+$m/2;   
        $l = $n/3+$m;//最终截取长度;$l = $n/3+$m*2?   
        $i++;   
    } while($k < $length);   
     $str1 = mb_substr($string,$start,$l,'utf-8');//保证不会出现乱码   
     return $str1;   
}

原文:http://aiou.javaeye.com/blog/371094

admin PHP

PHP拾遗捡漏(一)

2009年5月6日

PHP拾遗捡漏(一)

最近在看<PHP和MySQL WEB开发>第四版, 把一些基础知识又复习了一遍, 还是很有收获的.
边看边记录一些文字吧.

1. echo 输出字符串
双引号和单引号的区别

$foo = 'hello';
echo $foo.' world!<br />';
echo "$foo world!<br />";
echo '$foo world!<br />';

运行后, 可以看出第一第二两个语句是等价的, 而第三个语句则原样输出.

结论: 对于任何简单类型的变量, 都可以将变量写入到一个由双引号引起来的字符串中, 在双引号中, 变量名称将被变量值所代替.而在单引号中, 变量名称,或者任何其他文本都会不经修改而直接发送到浏览器端.

Heredoc字符串也是插补的, 就像双引号字符串.

2.正确理解标识符
PHP中, 标识符是区分大小写的, $foo和$Foo是不同的, 而函数名称则不区分大小写.

$foo = 'foo';
$Foo = 'Foo';
echo "$foo<br />";
echo "$Foo<br />";
echo bar()."<br />";
echo Bar()."<br />";
 
function bar() {
	echo 'bar';
}

3.引用
PHP中引用操作符&可以在关联赋值时使用. 通常, 在将一个变量的值赋给另外一个变量的时候, 将先产生原变量的一个副本, 然后再将它保存在内存的其它的一个地方.
例如

$a = 5;
$b = $a;
$a = 7; // 此时$a=7, 而$b仍然等于5

这两行代码首先将产生一个$a的副本, 然后再将它保存到$b中, 如果随后改变$a的值, $b的值不会有任何变化.

可以通过引用操作符&来避免产生$a的副本, 此时$a和$b都指向了内存中的相同地址.

$a = 5;
$b = &$a;
$a = 7; // 此时$a和$b都等于7

可以通过unset($a)来重置它们来改变所指向的地址, 重置并不会改变$b(7)的值.

4. “执行操作符, 它是一对反向单引号, PHP将试着将其间的命令当做服务器端的命令行来执行. 表达式的值就是命令的执行结果.

$out = `dir c:` // windows, Linux为 `ls -la`
echo $out;

5. isset()和empty()
bool isset(mixed var)
该函数需要一个变量名称作为参数, 如果这个变量存在返回true,否则返回false. 也可以传递一个由逗号间隔的变量列表, 如果所有变量都被设置了. 返回true.
可以使用unset()来销毁一个变量.

函数empty()可以用来检测一个变量是否存在,以及它的值是否为空和非0, 相应的返回true和false.

简单的来说empty()比isset()多检测值的非空和非0状态.

6. range()可以使用range()函数自动创建一个按升序排列的数字数组.

// 例如以下的代码将创建一个1~10的数字数组
$numbers = range(1, 10);
//range()函数具有一个可选的第三个参数, 这个参数允许设定值之间的步幅. 例如创建一个1~10之间的奇数数组
$odds = range(1, 10, 2);
//range()函数也可以对字符进行操作, 如下
$letters = range('a', 'z');

7. 数组排序
使用sort()函数, sort()函数可以将数组按字母或数字升序进行排序

 $products = array('Tires', 'Oil', 'Spark Plugs');
 sort($products);
 $prices = array(100, 10, 4);
 sort($prices);

sort()函数的第二个参数是可选的, 这个可选参数可以传递SORT_REGULAR(默认值), SORT_NUMERIC或SORT_STRING, sort()函数是区分大小写的.

使用asort()和ksort()函数对关联数组排序
函数asort()根据数组的每个元素值进行排序.
函数ksort()根据数组的每个元素进行排序.

以上三个函数都使数组按升序排序, 它们每个都对应有一个反向排序的函数, 分别是rsort(), arsort(), krsort().

用户自定义排序usort()
usort()函数的参数分别是希望排序的数组和用户比较的函数的名称

 // 这是一个普通的二维数组, 存储了3种产品的代码,说明和价格.
 $products = array(array('TLR', 'Tires', 100),
		array('OIL', 'Oil', 10),
		array('SPK', 'Spark Plugs', 4));
 
 // 以下代码对订单数组中的第二列(说明)按字母进行排序
 function compare($x, $y) {
	if ($x[1] == $y[1])
		return 0;
	else if ($x[1] < $y[1])
		return -1;
	else
		return 1;
 }
 
 usort($products, 'compare')
 
 // 同时实现反向排序
 function reverse_compare($x, $y) {
	if ($x[1] == $y[1])
		returnn 0;
	else if ($x[1] < $y[1])
		return 1;
	else
		return -1;
 }
 
 usort($products, 'reverse_compare');

转载请注明出处: http://www.suiyuan.org

admin PHP

正确的使用PHP5中的异常处理

2009年4月16日

本来想自己写个具体的例子的, 但是太忙了, 又怕转头就忘了, 用的网上的代码.
应该明白的是PHP5中的异常处理和类是紧密结合在一起的, 在进行异常捕捉前对代码中可能出现的异常情况进行判断, 然后抛出异常.

<?php 
// PHP 5 
require_once('cmd_php5/Command.php'); 
class CommandManagerException extends Exception{} 
class IllegalCommandException extends Exception{} 
 
class CommandManager { 
    private $cmdDir = "cmd_php5"; 
 
    function __construct() { 
        if (!is_dir($this->cmdDir)) { 
            throw new CommandManagerException("directory error: $this->cmdDir"); 
        } 
    } 
 
    function getCommandObject($cmd) { 
        $path = "{$this->cmdDir}/{$cmd}.php"; 
        if (!file_exists($path)) { 
            throw new IllegalCommandException("Cannot find $path"); 
        } 
        require_once $path; 
        if (!class_exists($cmd)) { 
            throw new IllegalCommandException("class $cmd does not exist"); 
        } 
 
        $class = new ReflectionClass($cmd); 
        if (!$class->isSubclassOf(new ReflectionClass('Command'))) { 
            throw new IllegalCommandException("$cmd is not a Command"); 
        } 
        return $class->newInstance(); 
    } 
} 
?>

当我们的类不能找到正确的command目录时,将抛出一个CommandManagerException异常;当在生成Command对象时产生错误,则getCommandObject()方法将抛出一个IllegalCommandException异常。注意存在多个可能导致抛出IllegalCommandException异常的原因(如未找到文件,或在文件中未找到正确的类)。我们将前两个例子结合起来并为IllegalCommandException提供整型的错误标识常量来代表不同类型的出错原因。
现在CommandManager类已经具备了处理这多种出错情况的能力,我们可以增加新的catch语句来匹配不同的错误类型。
代码后半段

<?php 
// PHP 5 
try { 
    $mgr = new CommandManager(); 
    $cmd = $mgr->getCommandObject('realcommand'); 
    $cmd->execute(); 
} catch (CommandManagerException $e) { 
    die($e->getMessage()); 
} catch (IllegalCommandException $e) { 
    error_log($e->getMessage()); 
    print "attempting recovery\n"; 
    // perhaps attempt to invoke a default command? 
} catch (Exception $e) { 
    print "Unexpected exception\n"; 
    die($e->getMessage()); 
} 
?>

看了代码, 应该明白这里和c#直接try…catch不同的是多了个判断的过程. 为什么在C#中不需要, 很简单, C#底层中已经对这些代码进行封装过了.
来个c#打开串口的例子

            try
            {
                if (comPort.IsOpen) comPort.Close();
 
                comPort.BaudRate = int.Parse(_baudRate);
                comPort.DataBits = int.Parse(_dataBits);
                comPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), _stopBits);
                comPort.Parity = (Parity)Enum.Parse(typeof(Parity), _parity);
                comPort.PortName = _portName;
                comPort.Open();
                if (this.IsBatch)
                    DisplayData(MsgType.Normal, "当前模式:批量传输,正在接收数据..\n");
                else
                    DisplayData(MsgType.Normal, "当前模式:实时传输,正在接受数据..\n");
                return true;
            }
            catch (Exception ex)
            {
                //DisplayData(MsgType.Error, ex.Message);
                FormUtility.Alert(ex.Message);
                return false;
            }

以前对PHP5的异常处理机制了解的不够透彻, 按照C#的方法直接去了才发现还是有不同的. 呵呵, 学习了.

admin PHP

PHP中自定错误和异常处理函数

2009年4月16日

PHP 函数set_error_handler()的用法

<?PHP
function ErrorHandler($errno, $errmsg, $errfile, $errline) {
	if ($errno == E_USER_ERROR) {
		$msg = "<strong>Custom Error:</strong>$errmsg<br />\n";
		$msg .= "File:$errfile<br />\n";
		$msg .= "Line Number:$errline<br />\n";
	}
	echo $msg;
	// 记录错误信息
	error_log(date("[Y-m-d H:i:s]")." -[".$_SERVER['REQUEST_URI']."] :".$msg."\n", 3, 'log.txt');
//	exit(); // 必要时必须终止脚本执行.
}
 
// set_error_handler()函数用于让用户自定义错误处理函数
// set_error_handler(error_function, error_type)
// error_function 必须, 制定发生错误时运行的函数
// error_type 可选, 规定不同的错误级别提示的不同信息, 默认是"E_ALL"
set_error_handler('ErrorHandler');
 
$foo = 2;
if ($foo > 1) {
	// trigger_error()接收一个错误信息和一个常量作为参数, 
	// 常量为E_USER_ERROR -> a fatal error
	//		 E_USER_WARNING -> a non-fatal error
	//		 E_USER_NOTICE -> a report that may not represent an error 
	trigger_error("A custom error has been trigglered", E_USER_ERROR);
}
?>

PHP 函数set_exception_handler()的用法

<?php
function ExceptionHandler($e) {
	echo "<strong>Exception:</strong>".$e->getMessage();
	echo "Stack Trace String:".$e->getTraceAsString();
}
 
// set_exception_handler()函数用于让用户自定义异常处理函数
// set_exception_handler(exception_function)
// 该函数需要抛出的exception对象最为参数
// 在这个异常处理程序被执行后, 脚本会停止执行
set_exception_handler('ExceptionHandler');
 
throw new Exception('Uncaught Exception occurred');
?>

admin PHP

Smarty一些小技巧

2009年4月13日

Smarty, PHP的一个非常出名的模板引擎, 很少用, 最近用了一点, 记录一些心得以备日后查阅.
1. 使用Smarty进行循环嵌套

// 在这里定义$sec1为一个二维数组
$sec1 = $db->fetchAll("select * from category");
for($i=0; $i<count($sec1); $i++) {
	$sec1[$i]['news'] = $db->fetchAll("select * from news where cid = ".$sec1[$i]['id']." order by id desc limit 0, 5");
}
 
$smarty->assign('sec1', $sec1); 
$smarty->left_delimiter = "<{";
$smarty->right_delimiter = "}>";
$smarty->display('news.html');

// 模版文件

<{section name=sec1 loop=$sec1}>
<div class="inner">
<h1><a href="/category/<{$sec1[sec1].id}>.html"><{$sec1[sec1].name}></a></h1>
	<ul>
	<{section name=sec2 loop=$sec1[sec1].news}>
		<li>
		<a href="/news/<{$sec1[sec1].news[sec2].id}>.html" target="_blank">
		<{$sec1[sec1].news[sec2].title}>
		</a>
		</li>
	<{/section}>
	</ul>				
</div>
<{/section}>

2. Smarty对于类似分页情况时的多参数缓存
我们都知道可以通过$smarty->display(’NewsList.tpl’, $page)这样来实现类似与NewsList.php?page=1这样URL结构相同的情况缓存. 但是如果情况是NewsList.php?cid=1&Page=1这样呢? 或许大家也知道, 但是我今天在网上查阅了一下才知道原来这么简单,$smarty->display(’NewsList.tpl’, “cid:{$cid}-page:{$page}”)就可以了. 呵呵

admin PHP