高质量PHP代码的50个实用技巧必备(下)


Posted in PHP onJanuary 22, 2016

接着上篇《高质量PHP代码的50个实用技巧必备(上)》继续研究。

26. 避免直接写SQL, 抽象之
不厌其烦的写了太多如下的语句:

<span style="color:#333333;font-family:''Helvetica, Arial, sans-serif'';">$query = "INSERT INTO users(name , email , address , phone) VALUES('$name' , '$email' , '$address' , '$phone')";
 $db->query($query); //call to mysqli_query()</span>

这不是个建壮的方案. 它有些缺点:

  • >>每次都手动转义值
  • >>验证查询是否正确
  • >>查询的错误会花很长时间识别(除非每次都用if-else检查)
  • >>很难维护复杂的查询

因此使用函数封装:

<span style="color:#333333;font-family:''Helvetica, Arial, sans-serif'';">function insert_record($table_name , $data)
 {
 foreach($data as $key => $value)
 {
 //mysqli_real_escape_string
 $data[$key] = $db->mres($value);
 }
 $fields = implode(',' , array_keys($data));
 $values = "'" . implode("','" , array_values($data)) . "'";
 //Final query
 $query = "INSERT INTO {$table}($fields) VALUES($values)";
 return $db->query($query);
}
 $data = array('name' => $name , 'email' => $email , 'address' => $address , 'phone' => $phone);
 insert_record('users' , $data);</span>

看到了吗? 这样会更易读和扩展. record_data 函数小心的处理了转义。最大的优点是数据被预处理为一个数组, 任何语法错误都会被捕获。该函数应该定义在某个database类中, 你可以像 $db->insert_record这样调用。查看本文, 看看怎样让你处理数据库更容易。类似的也可以编写update,select,delete方法. 试试吧.

27. ?⑹?菘馍?傻哪谌莼捍娴骄蔡?募?
如果所有的内容都是从数据库获取的, 它们应该被缓存. 一旦生成了, 就?⑺?潜4嬖诹偈蔽募?? 下次请求该页面时, 可直接从缓存中取, 不用再查数据库.
好处:
>>节约php处理页面的时间, 执行更快
>>更少的数据库查询意味着更少的mysql连接开销

28. 在数据库中保存session
基于文件的session策略会有很多限制. 使用基于文件的session不能扩展到集群中, 因为session保存在单个服务器中. 但数据库可被多个服务器访问, 这样就可以解决问题.
在数据库中保存session数据, 还有更多好处:
>>处理username重复登录问题. 同个username不能在两个地方同时登录.
>>能更准备的查询在线用户状态.

29. 避免使用全局变量

  • >>使用 defines/constants
  • >>使用函数获取值
  • >>使用类并通过$this访问

30. 在head中使用base标签
没听说过? 请看下面:

<head>
 <base href="http://www.domain.com/store/">
 </head>
 <body>
 <img src="happy.jpg" />
 </body>
 </html>

base 标签非常有用. 假设你的应用分成几个子目录, 它们都要包括相同的导航菜单.

  • www.domain.com/store/home.php
  • www.domain.com/store/products/ipad.php

在首页中, 可以写:

<a href="home.php">Home</a>
<a href="products/ipad.php">Ipad</a>

但在你的ipad.php不得不写成:

<span style="color:#333333;font-family:''Helvetica, Arial, sans-serif'';"><a href="../home.php">Home</a>
 <a href="ipad.php">Ipad</a></span>

因为目录不一样. 有这么多不同版本的导航菜单要维护, 很糟糕啊。因此, 请使用base标签.

<span style="color:#333333;font-family:''Helvetica, Arial, sans-serif'';"><head>
 <base href="http://www.domain.com/store/">
 </head>
 <body>
 <a href="home.php">Home</a>
 <a href="products/ipad.php">Ipad</a>
 </body>
 </html></span>

现在, 这段代码放在应用的各个目录文件中行为都一致.

31. 永远不要? error_reporting 设为 0
关闭不相的错误报告. E_FATAL 错误是很重要的.

<span style="color:#333333;font-family:'Helvetica, Arial, sans-serif';">ini_set('display_errors', 1);
 error_reporting(~E_WARNING & ~E_NOTICE & ~E_STRICT);</span>

32. 注意平台体系结构
integer在32位和64位体系结构中长度是不同的. 因此某些函数如 strtotime 的行为会不同.
在64位的机器中, 你会看到如下的输出.

<span style="color:#333333;font-family:''Helvetica, Arial, sans-serif'';">$ php -a 
 Interactive shell 
 php > echo strtotime("0000-00-00 00:00:00"); 
 -62170005200 
 php > echo strtotime('1000-01-30'); 
 -30607739600 
 php > echo strtotime('2100-01-30'); 
 4104930600</span>

但在32位机器中, 它们?⑹?ool(false). 查看这里, 了解更多.

33. 不要过分依赖 set_time_limit
如果你想限制最小时间, 可以使用下面的脚本:

<span style="color:#333333;font-family:''Helvetica, Arial, sans-serif'';">set_time_limit(30);
 //Rest of the code</span>

高枕无忧吗? 注意任何外部的执行, 如系统调用,socket操作, 数据库操作等, 就不在set_time_limits的控制之下.
因此, 就算数据库花费了很多时间查询, 脚本也不会停止执行. 视情况而定.

34. 使用扩展库
一些例子:

  • >>mPDF — 能通过html生成pdf文档
  • >>PHPExcel — 读写excel
  • >>PhpMailer — 轻松处理发送包含附近的邮件
  • >>pChart — 使用php生成报表

使用开源库完成复杂任务, 如生成pdf, ms-excel文件, 报表等.

35. 使用MVC框架
是时候使用像 codeigniter 这样的MVC框架了. MVC框架并不强迫你写面向对象的代码. 它们仅??hp代码与html分离.

  • >>明确区分php和html代码. 在团队协作中有好处, 设计师和程序员可以同时工作.
  • >>面向对象设计的函数能让你更容易维护
  • >>内建函数完成了很多工作, 你不需要重复编写
  • >>开发大的应用是必须的
  • >>很多建议, 技巧和hack已被框架实现了

36. 时常看看 phpbench
phpbench 提供了些php基本操作的基准测试结果, 它展示了一些徽小的语法变化是怎样导致巨大差异的.
查看php站点的评论, 有问题到IRC提问, 时常阅读开源代码, 使用Linux开发.

37. 如何正确的创建一个网站的Index页面
创建每一个网站时,建立网站的index页面是首要做的事情之一。如果你是一个PHP新手,在编写index页面时典型的做法是只对index页面所需的内容进行编程,其它链接创建另一个页面。不过,如果想学习一种更高效的方式来实现PHP编程,可以采用“index.php?page=home”模式,许多网站都在采用这种模式。

38. 使用Request Global Array抓取数据
实际上我们没有任何理由使用$_GET和$_POST数组来抓取数值。$_REQUEST这个全局数组能够让你获取一个get或form请求。因此,多数情况下解析数据的更高效代码大体如下:

$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : 0;

39. 利用var_dump进行PHP代码调试
如果你在寻找php调试技术,我必须说var_dump应该是你要找的目标。在显示php信息方面这个命令可以满足你的所有需要。而调试代码的多数情况与得到PHP中的数值有关。

40. PHP处理代码逻辑,Smarty处理展现层
Smarty是一个使用PHP写出来的模板PHP模板引擎,是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲,目的就是要使PHP程序员同前端人员分离,使程序员改变程序的逻辑内容不会影响到前端人员的页面设计,前端人员重新修改页面不会影响到程序的程序逻辑,这在多人合作的项目中显的尤为重要。

41. 的确需要使用全局数值时,创建一个Config文件
动辄创建全局数值是一种糟糕的做法,不过有时候实际情况的确又需要这么做。对于数据库表或数据库连接信息使用全局数值是一个不错的想法,但不要在你的PHP代码中频繁使用全局数值。另外,更好的一种做法是把你的全局变量存放在一个config.php文件中。

42. 如果未定义,禁止访问!
如果你正确的创建了页面,那么任何其他人没有理由访问index.php或home.php之外的index.php页面。一旦index.php被访问后,你可以通过获得变量的方式来打开需要的页面。你的index页面应该包含类似的以下代码:

define('yourPage',1);

然后,其它页面应该包含:

if (!defined('yourPage')) die('Access Denied');

这么做的目的是防止直接访问你的其它php页面。这样,任何试图不通过index.php访问其它网页的人,将得到“访问被拒绝”的消息。

43. 创建一个数据库类
如果你正在进行数据库编程(在PHP中非常常见的任务),一个不错的想法是创建一个数据库类来处理任何数据库管理功能。示例代码如下:

public function dbExec($query)  
    
 {  
    
   $result = $this->db->exec($query);  
    
   if (PEAR::isError($result))  
    
     errorRedirect($result->getMessage(), true);  
    
   else 
    
     return $result;  
    
 }

这个函数仅接收一个查询语句并对其执行。它还处理可能出现的任何错误。你还可以在这儿包含审核代码,不过我更喜欢使用一个类似的审核函数:

// checks if arguments given are integer values not less than 0 - has multiple arguments  
    
 function sanitizeInput()  
    
 {  
    
   $numargs = func_num_args();  
    
   $arg_list = func_get_args();  
    
   for ($i = 0; $i < $numargs; $i++) {  
    
     if (!is_numeric($arg_list[$i]) || $arg_list[$i] < 0)  
    
       errorRedirect("Unexpected variable value", true);  
    
   }  
    
 }

44. 一个php文件处理输入,一个class.php文件处理具体功能
不让代码变得混乱的一个重要方法是:获取用户输入后,将其重定向到其它函数来进行处理。原理非常简单,php文件获得我们需要的任何输入,然后将其执行重定向到类文件中的一个函数。举例来讲,假设有一个类似“index.php?page=profile&action=display”的URL。由profile.php来检索该网址并得到操作是“display”。然后使用一个简单的switch函数,我们来执行真正的显示函数:

require_once PROJECTROOT.'libs/messages.class.php';  
    
$message = new Message();  
    
switch ($action) 
    
{ 
    
  case 'display': 
    
    $message->display(); 
    
    break;  
    
...

如上所示,我使用了一个消息类,然后开始进行switch检查。$message只是被类中的调用函数使用的一个对象。

45. 了解你的SQL语句,并总是对其审查(Sanitize)
正如我以前所提到的,任何php网站中最重要的部分有99%的可能是数据库。因此,你需要非常熟悉如何正确的使用sql。学会关联表和更多高级技术。下面我将展示一个使用MySQL的函数示例,并使用本文第7条函数进行审查。

private function getSentMessages($id)  
    
 {  
    
$this->util->sanitizeInput($id);  
    
  $pm_table = $GLOBALS['config']['privateMsg'];  
    
 $users = $GLOBALS['config']['users'];  
    
   $sql = "SELECT PM.*, USR.username as name_sender FROM $pm_table PM, $users USR  
    
     WHERE id_sender = '$id' AND sender_purge = FALSE AND USR.id = PM.id_receiver AND is_read = TRUE  
    
     ORDER BY date_sent DESC";  
    
 $result = $this->dbQueryAll($sql);  
    
  return $result;  
    
 }

首先,我们对用户输入进行检查(通过一个GET变量传递消息id),然后我们执行我们的SQL命令。注意这儿SQL的用法。你需要了解如何使用别名和关联表。

46. 当你只需要一个对象时,使用单例模式
在PHP中相当常见的一种情形时,我们只需要创建一个对象一次,然后在我们的整个程序中使用它。一个很好的例子就是smarty变量,一旦被初始化后就可以在任何地方使用。这种情形的一个很好实现方案就是单例模式。示例代码如下:

function smartyObject()  
    
 {  
    
   if ($GLOBALS['config']['SmartyObj'] == 0)  
    
   {  
    
     $smarty = new SmartyGame();  
    
     $GLOBALS['config']['SmartyObj'] = $smarty;  
    
   }  
    
   else 
    
     $smarty = $GLOBALS['config']['SmartyObj'];  
    
   return $smarty;  
    
 }

注意,我们拥有一个全局smarty变量(该示例中它在config.php中被初始化),如果它的值为0,我们将创建一个新smarty对象。否则,它意味着该对象已经被创建,我们只需要返回它。

47. 关于PHP重定向
方法一:header("Location:index.php");
方法二:echo"<script>window.location=\"$PHP_SELF\";</script>";
方法三:echo"<METAHTTP-EQUIV=\"Refresh\"CONTENT=\"0;URL=index.php\">";

48. 获取访问者浏览器

functionbrowse_infor()
{
$browser="";$browserver="";
$Browsers=array("Lynx","MOSAIC","AOL","Opera","JAVA","MacWeb","WebExplorer","OmniWeb");
$Agent=$GLOBALS["HTTP_USER_AGENT"];
for($i=0;$i<=7;$i++)
{
if(strpos($Agent,$Browsers[$i]))
{
$browser=$Browsers[$i];
$browserver="";
}
}
if(ereg("Mozilla",$Agent)&&!ereg("MSIE",$Agent))
{
$temp=explode("(",$Agent);$Part=$temp[0];
$temp=explode("/",$Part);$browserver=$temp[1];
$temp=explode("",$browserver);$browserver=$temp[0];
$browserver=preg_replace("/([\d\.]+)/","\1",$browserver);
$browserver="$browserver";
$browser="NetscapeNavigator";
}
if(ereg("Mozilla",$Agent)&&ereg("Opera",$Agent))
{
$temp=explode("(",$Agent);$Part=$temp[1];
$temp=explode(")",$Part);$browserver=$temp[1];
$temp=explode("",$browserver);$browserver=$temp[2];
$browserver=preg_replace("/([\d\.]+)/","\1",$browserver);
$browserver="$browserver";
$browser="Opera";
}
if(ereg("Mozilla",$Agent)&&ereg("MSIE",$Agent))
{
$temp=explode("(",$Agent);$Part=$temp[1];
$temp=explode(";",$Part);$Part=$temp[1];
$temp=explode("",$Part);$browserver=$temp[2];
$browserver=preg_replace("/([\d\.]+)/","\1",$browserver);
$browserver="$browserver";
$browser="InternetExplorer";
}
if($browser!="")
{
$browseinfo="$browser$browserver";
}
else
{
$browseinfo="Unknown";
}
return$browseinfo;
}
//调用方法$browser=browseinfo();直接返回结果

49.获取访问者操作系统

functionosinfo(){
$os="";
$Agent=$GLOBALS["HTTP_USER_AGENT"];
if(eregi('win',$Agent)&&strpos($Agent,'95')){
$os="Windows95";
}
elseif(eregi('win9x',$Agent)&&strpos($Agent,'4.90')){
$os="WindowsME";
}
elseif(eregi('win',$Agent)&&ereg('98',$Agent)){
$os="Windows98";
}
elseif(eregi('win',$Agent)&&eregi('nt5\.0',$Agent)){
$os="Windows2000";
}
elseif(eregi('win',$Agent)&&eregi('nt',$Agent)){
$os="WindowsNT";
}
elseif(eregi('win',$Agent)&&eregi('nt5\.1',$Agent)){
$os="WindowsXP";
}
elseif(eregi('win',$Agent)&&ereg('32',$Agent)){
$os="Windows32";
}
elseif(eregi('linux',$Agent)){
$os="Linux";
}
elseif(eregi('unix',$Agent)){
$os="Unix";
}
elseif(eregi('sun',$Agent)&&eregi('os',$Agent)){
$os="SunOS";
}
elseif(eregi('ibm',$Agent)&&eregi('os',$Agent)){
$os="IBMOS/2";
}
elseif(eregi('Mac',$Agent)&&eregi('PC',$Agent)){
$os="Macintosh";
}
elseif(eregi('PowerPC',$Agent)){
$os="PowerPC";
}
elseif(eregi('AIX',$Agent)){
$os="AIX";
}
elseif(eregi('HPUX',$Agent)){
$os="HPUX";
}
elseif(eregi('NetBSD',$Agent)){
$os="NetBSD";
}
elseif(eregi('BSD',$Agent)){
$os="BSD";
}
elseif(ereg('OSF1',$Agent)){
$os="OSF1";
}
elseif(ereg('IRIX',$Agent)){
$os="IRIX";
}
elseif(eregi('FreeBSD',$Agent)){
$os="FreeBSD";
}
if($os=='')$os="Unknown";
return$os;
}
//调用方法$os=os_infor();

50. 文件格式类

$mime_types=array(
'gif'=>'image/gif',
'jpg'=>'image/jpeg',
'jpeg'=>'image/jpeg',
'jpe'=>'image/jpeg',
'bmp'=>'image/bmp',
'png'=>'image/png',
'tif'=>'image/tiff',
'tiff'=>'image/tiff',
'pict'=>'image/x-pict',
'pic'=>'image/x-pict',
'pct'=>'image/x-pict',
'tif'=>'image/tiff',
'tiff'=>'image/tiff',
'psd'=>'image/x-photoshop',
  
'swf'=>'application/x-shockwave-flash',
'js'=>'application/x-javascript',
'pdf'=>'application/pdf',
'ps'=>'application/postscript',
'eps'=>'application/postscript',
'ai'=>'application/postscript',
'wmf'=>'application/x-msmetafile',
  
'css'=>'text/css',
'htm'=>'text/html',
'html'=>'text/html',
'txt'=>'text/plain',
'xml'=>'text/xml',
'wml'=>'text/wml',
'wbmp'=>'image/vnd.wap.wbmp',
  
'mid'=>'audio/midi',
'wav'=>'audio/wav',
'mp3'=>'audio/mpeg',
'mp2'=>'audio/mpeg',
  
'avi'=>'video/x-msvideo',
'mpeg'=>'video/mpeg',
'mpg'=>'video/mpeg',
'qt'=>'video/quicktime',
'mov'=>'video/quicktime',
  
'lha'=>'application/x-lha',
'lzh'=>'application/x-lha',
'z'=>'application/x-compress',
'gtar'=>'application/x-gtar',
'gz'=>'application/x-gzip',
'gzip'=>'application/x-gzip',
'tgz'=>'application/x-gzip',
'tar'=>'application/x-tar',
'bz2'=>'application/bzip2',
'zip'=>'application/zip',
'arj'=>'application/x-arj',
'rar'=>'application/x-rar-compressed',
  
'hqx'=>'application/mac-binhex40',
'sit'=>'application/x-stuffit',
'bin'=>'application/x-macbinary',
  
'uu'=>'text/x-uuencode',
'uue'=>'text/x-uuencode',
  
'latex'=>'application/x-latex',
'ltx'=>'application/x-latex',
'tcl'=>'application/x-tcl',
  
'pgp'=>'application/pgp',
'asc'=>'application/pgp',
'exe'=>'application/x-msdownload',
'doc'=>'application/msword',
'rtf'=>'application/rtf',
'xls'=>'application/vnd.ms-excel',
'ppt'=>'application/vnd.ms-powerpoint',
'mdb'=>'application/x-msaccess',
'wri'=>'application/x-mswrite',
);
5、php生成excel文档
<?
header("Content-type:application/vnd.ms-excel");
header("Content-Disposition:filename=test.xls");
echo"test1\t";
echo"test2\t\n";
echo"test1\t";
echo"test2\t\n";
echo"test1\t";
echo"test2\t\n";
echo"test1\t";
echo"test2\t\n";
echo"test1\t";
echo"test2\t\n";
echo"test1\t";
echo"test2\t\n";
?>

//改动相应文件头就可以输出.doc.xls等文件格式了

以上就是本文的全部内容,大家结合前一篇进行深入学习,一定会有所收获。

PHP 相关文章推荐
使用php重新实现PHP脚本引擎内置函数
Mar 06 PHP
PHP中文汉字验证码
Apr 08 PHP
php获取post中的json数据的实现方法
Jun 08 PHP
php实现查看邮件是否已被阅读的方法
Dec 03 PHP
php实现获取文章内容第一张图片的方法
Nov 04 PHP
PHP中的类型约束介绍
May 11 PHP
CodeIgniter视图使用注意事项
Jan 20 PHP
PHP+jQuery实现滚屏无刷新动态加载数据功能详解
May 04 PHP
总结一些PHP中好用但又容易忽略的小知识
Jun 02 PHP
网站被恶意镜像怎么办 php一段代码轻松搞定(全面版)
Oct 23 PHP
php实现分页功能的详细实例方法
Sep 29 PHP
Thinkphp5+Redis实现商品秒杀代码实例讲解
Dec 29 PHP
php使用timthumb生成缩略图的方法
Jan 22 #PHP
php session的锁和并发
Jan 22 #PHP
php5.4传引用时报错问题分析
Jan 22 #PHP
php实现word转html的方法
Jan 22 #PHP
高质量PHP代码的50个实用技巧必备(上)
Jan 22 #PHP
php中namespace use用法实例分析
Jan 22 #PHP
PHP爬虫之百万级别知乎用户数据爬取与分析
Jan 22 #PHP
You might like
一个简单实现多条件查询的例子
2006/10/09 PHP
关于php程序报date()警告的处理(date_default_timezone_set)
2013/10/22 PHP
PHP过滤黑名单关键字的方法
2014/12/01 PHP
PHP数组与对象之间使用递归实现转换的方法
2015/06/24 PHP
PHP+jQuery实现即点即改功能示例
2019/02/21 PHP
基于jquery的滚动条滚动固定div(附演示下载)
2012/10/29 Javascript
js的Boolean对象初始值示例
2014/03/04 Javascript
js判断iframe内的网页是否滚动到底部触发事件
2014/03/18 Javascript
node.js中的fs.link方法使用说明
2014/12/15 Javascript
jQuery中unwrap()方法用法实例
2015/01/16 Javascript
js使用cookie记录用户名的方法
2015/11/26 Javascript
Javascript将数值转换为金额格式(分隔千分位和自动增加小数点)
2016/06/22 Javascript
基于BootStrap的Metronic框架实现页面链接收藏夹功能按钮移动收藏记录(使用Sortable进行拖动排序)
2016/08/29 Javascript
详解angularjs实现echart图表效果最简洁教程
2017/11/29 Javascript
使用json-server简单完成CRUD模拟后台数据的方法
2018/07/12 Javascript
Vue 通过自定义指令回顾v-内置指令(小结)
2018/09/03 Javascript
vue-cli项目修改文件热重载失效的解决方法
2018/09/19 Javascript
js使用formData实现批量上传
2020/03/27 Javascript
vue-router权限控制(简单方式)
2018/10/29 Javascript
js消除图片小游戏代码
2019/12/11 Javascript
JS面向对象编程基础篇(三) 继承操作实例详解
2020/03/03 Javascript
使用Typescript开发微信小程序的步骤详解
2021/01/12 Javascript
wxPython 入门教程
2008/10/07 Python
Python实现读取json文件到excel表
2017/11/18 Python
Python命令行解析模块详解
2018/02/01 Python
Python 获取ftp服务器文件时间的方法
2019/07/02 Python
Python3自定义http/https请求拦截mitmproxy脚本实例
2020/05/11 Python
Python获取excel内容及相关操作代码实例
2020/08/10 Python
python实现登录与注册系统
2020/11/30 Python
AmazeUI 手机版页面的顶部导航条Header与侧边导航栏offCanvas的示例代码
2020/08/19 HTML / CSS
CK巴西官方网站:Calvin Klein巴西
2019/07/19 全球购物
银行介绍信范文
2014/01/10 职场文书
2014学习全国两会精神心得体会2000字
2014/03/11 职场文书
2014年党务公开方案
2014/05/08 职场文书
渠道运营商合作协议书范本
2014/10/06 职场文书
HTML基础详解(上)
2021/10/16 HTML / CSS