php的handler
1. php自定义门面以后显示错误
如果您是PHP老手,当然知道当PHP脚本出错时发生了什么事情。此时PHP解析器将在屏幕上给出错误信息,如 Fatal error: Call to undefined function on line 19 --,因此程序在此处终止。这个信息会吓到客户,他可能立即打电话和你进行咨询。
幸运的是,这里有解决办法。PHP拥有内置工具,可以让开发人员捕捉脚本错误然后将它们转到自定义的错误处理器。此时则可以对处理器进行编程显示更多关于错误的详细信息。还可以将错误写入文件或数据库以采取补救措施。有时候还可以对处理器编写程序忽略错误消息。
本文中,我将阐述如何使用PHP的错误处理API构建用户自定义的错误处理器,并且说明如何以简单而友好的方式显示和管理脚本的错误信息。
错误类型和报告级别
我们从最基本的开始。PHP有三种最基本的错误类型,从低级到高级分别为:注意、警告和错误(或致命错误)。通常情况下,注意和警告不会终止程序;但是致命错误则是危险故障(例如,调用一个没有定义的函数或参考一个不存在的对象),将导致程序中断。这些错误有可能在启动、解析、编译或运行时发生。
关键字如E_NOTICE, E_ERROR等用于表明错误的不同类型和等级。在PHP手册上可以获得它们的详细信息列表。
脚本阶段错误显示由error_reporting()函数进行控制。这一函数针对不同的错误等级设置不同的参数。表A给出了使用此函数报告警告和致命错误的脚本程序。
表A
<?php
// display warnings and errors
error_reporting(E_WARNING | E_ERROR);
// this will generate a notice, which will never be displayed
echo $undefinedVar;
// this will generate a fatal error, which will be displayed
callUndefFunc();
?>
将表B中的代码与上面的进行比较发现,Listing B中隐藏错误信息甚至隐藏致命信息,使得错误信息不会被显示出来。
表B
<?php
// turn off error display
// no errors will be displayed
error_reporting(0);
// this will generate a notice
echo $undefinedVar;
// this will generate a fatal error
callUndefFunc();
?>
表C中的代码将所有错误信息甚至简单的注意事项都显示出来:
表C
<?php
// all errors will be displayed
error_reporting(E_ALL);
// this will generate a notice
echo $undefinedVar;
// this will generate a fatal error
callUndefFunc();
?>
如以上3个例子所示,error_reporting()函数在控制错误发生时,在屏幕上显示内容非常重要。这里的关键字是displayed,其表达的意思是错误不被显示而不是错误没有发生。因此,发生致命错误时(例如不正确的函数调用),程序将被终止;但是,此时没有任何消息显示给用户。
下面的例子(表 D)说明了这种情况:
表D
<?php
// no errors will be displayed
error_reporting(0);
// start a task
echo "Starting task...";
// call an undefined function
// a fatal error occurs ring task processing
callMe();
// end the task
echo "Successfully completed task...";
?>
在表D中,在调用echo()函数时发生了致命错误,程序执行时到这点被终止,但是却没有任何错误消息给出,用户不知道这种情况还以为程序在正确运行。下面的结论是非常明显的:不给出错误报告非常危险,因为不论过程是否完成它常导致不正确的结论。
注意:调用不带任何参数的error_reporting()将返回当前的错误报告等级。
自定义错误处理器
很明显,隐藏错误报告是不正确的,你肯定想知道有什么其他办法加以改进。自定义错误处理器就是一个很好的能取代PHP默认错误处理系统的解决方法。自定义错误处理器可以以任何方式设置处理错误信息,包括信息如何显示。
PHP函数中,完成这一功能的是set_error_handler()函数。错误发生时,此函数被自动调用,然后给出4个参数:错误代码、错误消息、发生错误的脚本名称和错误出现的行,此函数对错误管理负责。
表E给出一个简单例子:
表E
<?php
// define custom handler
set_error_handler('myHandler');
// custom handler code
function myHandler($code, $msg, $file, $line) {
echo "Just so you know, something went wrong at line $line of your script $file. The system says that the error code was $code, and the reason for the error was: $msg. Sorry about this!";
}
// generate a notice
echo $undefVar;
?>
当运行此脚本的时候,会出现下面的信息:
Just so you know, something went wrong at line 11 of your /dev/error1.php. The system says that the error code was 8, and the reason for the error was: Undefined variable: undefVar. Sorry about this!
此时,PHP的默认错误处理器被用户定义的myHandler()函数所取代,$undefVar变量被激活,PHP通知未定义变量的信息,此信息在运行时引擎产生,然后传递给myHandler()函数,同时错误发生的地址也传递给此函数。然后myHandler()函数输出友好信息解释错误。
注意:错误和致命错误很重要,它们会绕过自定义错误处理器,然后以PHP默认的错误处理机制进行显示。显示这些信息可使用前面讨论的标准error_reporting()函数进行控制。
例1:动态错误页面和e-mail警报
表F给出了另一个范例,当发生错误时,将动态产生HTML错误页面,并且通过e-mail向Web管理员进行报告。
表F
<?php
// define custom handler
set_error_handler('myHandler');
// custom handler code
function myHandler($code, $msg, $file, $line, $context) {
// print error page
echo "<html><head></head><body>";
echo "<h2 align=center>Error!</h2>";
echo "<font color=red size=+1>";
echo "An error occurred while processing your request. Please visit our <a href=http://www.domain.dom>home page</a> and try again.";
echo "</font>";
echo "</body></html>";
// email error to admin
$body = "$msg at $file ($line), timed at " . date ("d-M-Y h:i:s", mktime());
$body .= "nn" . print_r($context, TRUE);
mail ("[email protected]", "Web site error", $body);
// halt execution of script
die();
}
// generate a notice
echo $undefVar;
?>
这里,自定义的错误处理器在遇到错误时动态产生HTML错误页面。此错误信息也能被e-mail信息捕获,然后通过PHP内置的mail()函数发送给管理员。
这里出现了myHandler()函数的一个新参数$context。这是myHandler()函数的第五个参数,是可选项。它包含了当前变量状态的快照。包括对管理员有用的上下文信息,有利于减少调试时间。
2. php引用函数的使用方法
php引用函数的使用方法
在技术学习的道路上,能掌握一些有用的技巧,对于初学者是非常有帮助的,下面是php引用函数的使用方法,希望大家会喜欢。
1.不要在你的应用程序中gzip输出,让apache来做
考虑使用ob_gzhandler?不,别这样做。它没有任何意义。PHP应该是来写应用程序的。不要担心PHP中有关如何优化在服务器和浏览器之间传输的数据。
使用apache mod_gzip/mod_deflate通过.htaccess文件压缩内容。
2.从php echo javascript代码时使用json_encode
有些时候一些JavaScript代码是从php动态生成的。
$images = array( 'myself.png' , 'friends.png' , 'colleagues.png');
$js_code = '';foreach($images as $image)
{
$js_code .= "'$image' ,";
}
$js_code = 'var images = [' . $js_code . ']; ';echo $js_code;//Output is var images = ['myself.png' ,'friends.png' ,'colleagues.png' ,];
放聪明点。使用json_encode:
$images = array( 'myself.png' , 'friends.png' , 'colleagues.png');
$js_code = 'var images = ' . json_encode($images);
echo $js_code;//Output is : var images = ["myself.png","friends.png","colleagues.png"]
这不是很整洁?
3.在写入任何文件之前检查目录是否可写
在写入或保存任何文件之前,请务必要检查该目录是否是可写的,如果不可写的话,会闪烁错误消息。这将节省你大量的“调试”时间。当你工作于Linux时,权限是必须要处理的,并且会有很多很多的权限问题时,当目录不可写,文件无法读取等的时候。
请确保你的应用程序尽可能智能化,并在最短的时间内报告最重要的信息。
$contents = "All the content";
$file_path = "/var/www/project/content.txt";
file_put_contents($file_path , $contents);
这完全正确。但有一些间接的问题。file_put_contents可能会因为一些原因而失败:
父目录不存在
目录存在,但不可写
锁定文件用于写入?
因此,在写入文件之前最好能够一切都弄明确。
$contents = "All the content";
$dir = '/var/www/project';
$file_path = $dir . "/content.txt";if(is_writable($dir))
{
file_put_contents($file_path , $contents);
}else{ die("Directory $dir is not writable, or does not exist. Please check");
}
通过这样做,你就能得到哪里文件写入失败以及为什么失败的准确信息。
4.改变应用程序创建的文件的权限
当在Linux环境下工作时,权限处理会浪费你很多时间。因此,只要你的php应用程序创建了一些文件,那就应该修改它们的权限以确保它们在外面“平易近人”。否则,例如,文件是由“php”用户创建的,而你作为一个不同的用户,系统就不会让你访问或打开文件,然后你必须努力获得root权限,更改文件权限等等。
// Read and write for owner, read for everybody elsechmod("/somedir/somefile", 0644);// Everything for owner, read and execute for otherschmod("/somedir/somefile", 0755);
5.不要检查提交按钮值来检查表单提交
if($_POST['submit'] == 'Save')
{ //Save the things}
以上代码在大多数时候是正确的,除了应用程序使用多语言的情况。然后“Save”可以是很多不同的东西。那么你该如何再做比较?所以不能依靠提交按钮的值。相反,使用这个:
if( $_SERVER['REQUEST_METHOD'] == 'POST' and isset($_POST['submit']) )
{ //Save the things}
现在你就可以摆脱提交按钮的值了。
6.在函数中总是有相同值的地方使用静态变量
//Delay for some timefunction delay(){
$sync_delay = get_option('sync_delay'); echo "
Delaying for $sync_delay seconds...";
sleep($sync_delay); echo "Done
";
}
相反,使用静态变量:
//Delay for some timefunction delay(){ static $sync_delay = null; if($sync_delay == null)
{
$sync_delay = get_option('sync_delay');
} echo "
Delaying for $sync_delay seconds...";
sleep($sync_delay); echo "Done
";
}
7.不要直接使用$ _SESSION变量
一些简单的例子是:
$_SESSION['username'] = $username;
$username = $_SESSION['username'];
但是这有一个问题。如果你正在相同域中运行多个应用程序,会话变量会发生冲突。2个不同的应用程序在会话变量中可能会设置相同的键名。举个例子,一个相同域的前端门户和后台管理应用程序。
因此,用包装函数使用应用程序特定键:
define('APP_ID' , 'abc_corp_ecommerce');//Function to get a session variablefunction session_get($key){
$k = APP_ID . '.' . $key; if(isset($_SESSION[$k]))
{ return $_SESSION[$k];
} return false;
}//Function set the session variablefunction session_set($key , $value){
$k = APP_ID . '.' . $key;
$_SESSION[$k] = $value; return true;
}
8.封装实用辅助函数到一个类中
所以,你必须在一个文件中有很多实用函数:
function utility_a(){ //This function does a utility thing like string processing}function utility_b(){ //This function does nother utility thing like database processing}function utility_c(){ //This function is ...}
自由地在应用程序中使用函数。那么你或许想要将它们包装成一个类作为静态函数:
class Utility{ public static function utility_a()
{
} public static function utility_b()
{
} public static function utility_c()
{
}
}//and call them as $a = Utility::utility_a();
$b = Utility::utility_b();
这里你可以得到的一个明显好处是,如果php有相似名称的内置函数,那么名称不会发生冲突。
从另一个角度看,你可以在相同的应用程序中保持多个版本的相同类,而不会发生任何冲突。因为它被封装了,就是这样。
9.一些傻瓜式技巧
使用echo代替print
使用str_replace代替preg_replace,除非你确定需要它
不要使用short tags
对于简单的'字符串使用单引号代替双引号
在header重定向之后要记得做一个exit
千万不要把函数调用放到for循环控制行中。
isset比strlen快
正确和一致地格式化你的代码
不要丢失循环或if-else块的括号。
不要写这样的代码:
if($a == true) $a_count++;
这绝对是一种浪费。
这样写
if($a == true)
{
$a_count++;
}
不要通过吃掉语法缩短你的代码。而是要让你的逻辑更简短。使用具有代码高亮功能的文本编辑器。代码高亮有助于减少错误。
10. 使用array_map快速处理数组
比方说,你要trim一个数组的所有元素。新手会这样做:
foreach($arr as $c => $v)
{
$arr[$c] = trim($v);
}
但它可以使用array_map变得更整洁:
$arr = array_map('trim' , $arr);
这适用于trim数组$arr的所有元素。另一个类似的函数是array_walk。
11.使用php过滤器验证数据
你是不是使用正则表达式来验证如电子邮件,IP地址等值?是的,每个人都是这样做的。现在,让我们试试一个不同的东西,那就是过滤器。
php过滤器扩展程序将提供简单的方法来有效验证或校验值。
12.强制类型检查
$amount = intval( $_GET['amount'] );
$rate = (int) $_GET['rate'];
这是一种好习惯。
13.使用set_error_handler()将Php错误写入到文件
set_error_handler()可以用来设置自定义的错误处理程序。在文件中编写一些重要的错误用于日志是个好主意。
14.小心处理大型数组
大型的数组或字符串,如果一个变量保存了一些规模非常大的东西,那么要小心处理。常见错误是创建副本,然后耗尽内存,并得到内存溢出的致命错误:
$db_records_in_array_format; //This is a big array holding 1000 rows from a table each having 20 columns , every row is atleast 100 bytes , so total 1000 * 20 * 100 = 2MB$cc = $db_records_in_array_format; //2MB moresome_function($cc); //Another 2MB ?
当导入csv文件或导出表到csv文件时,上面这样的代码很常见。
像上面这样做可能经常会由于内存限制而让脚本崩溃。对于小规模的变量它不会出现问题,但当处理大型数组时一定要对此加以避免。
考虑通过引用传递它们,或者将它们存储在一个类变量中:
$a = get_large_array();
pass_to_function(&$a);
这样一来,相同的变量(并非其副本)将用于该函数。
class A{ function first()
{ $this->a = get_large_array(); $this->pass_to_function();
} function pass_to_function()
{ //process $this->a
}
}
尽快复原它们,这样内存就能被释放,并且脚本的其余部分就能放松。
下面是关于如何通过引用来赋值从而节省内存的一个简单示例。
<?phpini_set('display_errors' , true);
error_reporting(E_ALL);
$a = array();for($i = 0; $i < 100000 ; $i++)
{
$a[$i] = 'A'.$i;
}echo 'Memory usage in MB : '. memory_get_usage() / 1000000 . '
';
$b = $a;
$b[0] = 'B';echo 'Memory usage in MB after 1st : '. memory_get_usage() / 1000000 . '
';
$c = $a;
$c[0] = 'B';echo 'Memory usage in MB after 2st : '. memory_get_usage() / 1000000 . '
';
$d =& $a;
$d[0] = 'B';echo 'Memory usage in MB after 3st (reference) : '. memory_get_usage() / 1000000 . '
';
一个典型php 5.4机器上的输出是:
Memory usage in MB : 18.08208Memory usage in MB after 1st : 27.930944Memory usage in MB after 2st : 37.779808Memory usage in MB after 3st (reference) : 37.779864
因此可以看出,内存被保存在第3份通过引用的副本中。否则,在所有普通副本中内存将被越来越多地使用。
15.在整个脚本中使用单一的数据库连接
请确保你在整个脚本使用单一的数据库连接。从一开始就打开连接,使用至结束,并在结束时关闭它。不要像这样在函数内打开连接:
function add_to_cart(){
$db = new Database();
$db->query("INSERT INTO cart .....");
}function empty_cart(){
$db = new Database();
$db->query("DELETE FROM cart .....");
}
有多个连接也不好,会因为每个连接都需要时间来创建和使用更多的内存,而导致执行减缓。
在特殊情况下。例如数据库连接,可以使用单例模式。
;3. 如何php 环境 apache2handler 变成cli
PHP作为一项普通的脚本语言,有如今的部署规模,很大程度上归结于apache2handler的功劳。
众所周知,通常情况在UNIX下,php在编译时通过--with-apxs2=apxs2_path的方式向apache moles中生成libphp5.so,然后在httpd.conf文件中添加LoadMoudle语句,并设置MIME以提供对php请求文件的支持。
4. 哪位高手能详解下 PHP session_set_save_handler() 。 往往会写这样一个类,搜索了写答案,但不详细
我有代码。但是我的报错。好像是配置文件哪儿没弄对:
Warning: Unknown: Unknown session.serialize_handler. Failed to encode session object. in Unknown on line 0
类的代码:
class session{
private static $handler=null;
private static $ip=null;
private static $lifetime=null;
private static $time=null;
private static function init($pdo){
self::$handler=$handler;
self::$ip = !empty($_SERVER["REMOTE_ADDR"])?$_SERVER["REMOTE_ADDR"]:unknown;
self::$lifetime=ini_get("session.gc_maxlifetime");
self::$time=time();
}
static function start(PDO $pdo){
self::init($pdo);
session_set_save_handler(
array(__CLASS__,"open"),
array(__CLASS__,"close"),
array(__CLASS__,"read"),
array(__CLASS__,"write"),
array(__CLASS__,"destroy"),
array(__CLASS__,"gc")
);
session_start();
}
public static function open($path,$name){
return true;
}
public static function close(){
return true;
}
public static function read($PHPSESSID){
$sql="select PHPSESSID,update_time,client_ip,data from session where PHPSESSID= ?";
$stmt=self::$handler->prepare($sql);
$stmt->execute(array($PHPSESSID));
if(!$result=$stmt->fetch(PDO::FETCH_ASSOC)){
return "";
}
if(self::$ip != $result['client_ip']){
self::destroy($PHPSESSID);
return "";
}
if(($result['update_time'] + self::$lifetime) < self::$time){
self::destroy($PHPSESSID);
return "";
}
return $result["data"];
}
public static function write($PHPSESSID,$data){
$sql="select PHPSESSID,update_time,client_ip,data from session where PHPSESSID= ?";
$stmt=self::$handler->prepare($sql);
$stmt->execute(array($PHPSESSID));
if($result=$stmt->fetch(PDO::FETCH_ASSOC)){
if($result["data"] != $data || self::$time > ($result['update_time']+30)){
$sql="update session set update_time=?,data=? where PHPSESSID=?";
$stmt=self::$handler->prepare($sql);
$stmt->execute(array(self::$time,$data,$PHPSESSID));
}
}else{
if(!empty($data)){
$sql="insert into session(PHPSESSID,update_time,client_ip,data values(?,?,?,?))";
$sth=self::$handler->prepare($sql);
$sth->execute(array($PHPSESSID,self::$time,self::$ip,$data));
}
}
return true;
}
public static function destroy($PHPSESSID){
$sql="delete from session where PHPSESSID=?";
$stmt=self::$handler->prepare($sql);
$stmt->execute(array($PHPSESSID));
return true;
}
public static function gc($lifetime){
$sql="delete from session where update_time < ?";
$stmt=self::$handler->prepare($sql);
$stmt->execute(array(self::$time-$lifetime));
return true;
}
}
try{
$pdo=new PDO("mysql:host=localhost;dbname=shoping","root","123456");
}catch(PDDException $e){
echo $e->getMessage();
}
session::start($pdo);
5. php $handler( $path )是什么意思
全部的代码是怎么样的?
$func='base64_decode';
$str='';
eval($func($str));
就等于:
base64_decode($str);
6. PHP set_error_handler 怎么设置
看下这篇文章吧
比较详细关于解决你这个问题
http://php.net/manual/zh/function.set-error-handler.php
7. PHP与PHP数据传输
这需要用ajax来实现
index.php
<html>
<title>php+jquery+ajax+json简单小例子</title>
<?php
header("Content-Type:text/html;charset=utf-8");
?>
<head>
<scripttype="text/javascript"src="
<scripttype="text/javascript">
$(function(){
$("#subbtn").click(function(){
varparams=$("input").serialize();
varurl="1.php";
$.ajax({
type:"post",
url:url,
dataType:"json",
data:params,
success:function(msg){
varbackdata="您提交的姓名为:"+msg.name+
"<br/>您提交的密码为:"+msg.password;
$("#backdata").html(backdata);
$("#backdata").css({color:"green"});
}
});
});
});
</script>
</head>
<body>
<p><labelfor="name">姓名:</label>
<inputid="name"name="name"type="text"/>
</p>
<p><labelfor="password">密码:</label>
<inputid="password"name="password"type="password"/>
</p>
<spanid="backdata"></span>
<p><inputid="subbtn"type="button"value="提交数据"/></p>
</body>
</html>
1.php代码:
<?php
//接收数据->处理数据->返回数据
echojson_encode($_POST);
?>
8. set_exception_handler函数在ThinkPHP中的用法
本文实例讲述了set_exception_handler函数在ThinkPHP中的用法。分享给大家供大家参考。具体方法如下:
函数:
复制代码
代码如下:string
set_exception_handler
(
callback
$exception_handler
)
定义和用法:
set_exception_handler()
函数设置用户自定义的异常处理函数。
该函数用于创建运行时期间的用户自己的异常处理方法。
该函数会返回旧的异常处理程序,若失败,则返回
null。
语法:
set_exception_handler(exception_function)
参数
描述
error_function
必需。规定未捕获的异常发生时调用的函数。
该函数必须在调用
set_exception_handler()
函数之前定义。
这个异常处理函数需要需要一个参数,即抛出的
exception
对象。
提示和注释:
提示:在这个异常处理程序被调用后,脚本会停止执行。
同样是在看TP代码的时候发现的这个函数,就想不明白了,自己以前咋就没关心过这些东西呢?(捶胸顿足ing。。。)
继续来看一下TP是怎么实现的,呃,为啥一定要用TP呢,嗯。那好吧,一会儿我把手册的例子也搬过来。
复制代码
代码如下:public
function
appException($e)
{
halt($e->__toString());
}
set_exception_handler(array(&$this,"appException"));
呵呵,这个简单吧?因为我没有给出halt这个方法的实现,这样就足够了。
再看手册中的例子,
复制代码
代码如下:function
exception_handler($exception)
{
echo
"Uncaught
exception:
"
,
$exception->getMessage(),
"n";
}
set_exception_handler('exception_handler');
throw
new
Exception('Uncaught
Exception');
echo
"Not
Executedn";
其实呢,set_exception_handler就是设置了一下,当你的程序需要抛出一个异常的时候调用哪个自定义的函数。
就这么简单
注意事项:
set_exception_handler(“myException”)
不仅可以接受函数,还可以接受
类的方法(公开的静态方法
及
公开的非静态方法
都可以),但需要以
数组形式
传递,数组的第一值为“类名”,第二个参数为“方法名”
希望本文所述对大家的ThinkPHP框架程序设计有所帮助。
9. PHP的apache2handler和PHP-FPM 运行模式的区别是什么
nginx和php是通过fastcgi通讯的,是有两个独立的进程
apache则把php嵌入进来
你下次可以去后盾人学习视频非常多质量好视频都是一线讲师亲自录制的,含金量高
10. PHP(或其他语言) 的Session 运行机制是
session实现与工作原理
浏览器和服务器采用http无状态的通讯,为了保持客户端的状态,使用session来达到这个目的。然而服务端是怎么样标示不同的客户端或用户呢?
假如你参加一个晚会,认识了很多人,你会采取什么方式来区分不同的人呢!你可能根据脸型,也有可能根据用户的名字,或者人的身份证,即采用一个独一无二的标示。在session机制中,也采用了这样的一个唯一的session_id来标示不同的用户,不同的是:浏览器每次请求都会带上由服务器为它生成的session_id.
简单介绍一下流程:当客户端访问服务器时,服务器根据需求设置session,将会话信息保存在服务器上,同时将标示session的session_id传递给客户端浏览器,
浏览器将这个session_id保存在内存中(还有其他的存储方式,例如写在url中),我们称之为无过期时间的cookie。浏览器关闭后,这个cookie就清掉了,它不会存在用户的cookie临时文件。
以后浏览器每次请求都会额外加上这个参数值,再服务器根据这个session_id,就能取得客户端的数据状态。
如果客户端浏览器意外关闭,服务器保存的session数据不是立即释放,此时数据还会存在,只要我们知道那个session_id,就可以继续通过请求获得此session的信息;但是这个时候后台的session还存在,但是session的保存有一个过期
时间,一旦超过规定时间没有客户端请求时,他就会清除这个session。
下面介绍一下session的存储机制,默认的session是保存在files中,即以文件的方式保存session数据。在php中主要根据php.ini的配置session.save_handler来选择保存session的方式。如果要做服务器的lvs,即多台server的话,我们一般使用memcached的方式session,否则会导致一些请求找不到session。
一个简单的memcache配置:
session.save_handler = memcache
session.save_path = "tcp://12.8.1.8:1000"
当然如果一定要使用files文件缓存,我们可以将文件作nfs,将所有的保存session文件定位到一个地方。返回给用户的session-id最终保存在内存中,这里我们也可以设置参数将其保存在用户的url中。