1. 程式人生 > 其它 >PHP良好編碼方式與技巧注意事項

PHP良好編碼方式與技巧注意事項

技術標籤:# PHP實用技術總結

PHP編碼習慣

PHP的命名

function extName($fileName){
$dotPos = strrpos($fileName, '.');
$extName = substr($fileName, $dotPos + 1 );
return $extName;
}

命名的注意事項:

  • 命名要有實際含義
  • 命名風格保持一致
  • 不用拼音命名
  • 不用語言關鍵字

適當的使用註釋

終極要求:程式碼就是註釋

  • 好的程式碼應該是自描述的
  • 難以理解的地方加上註釋
  • 函式的功能加上註釋說明
  • 類的功能和使用方法加註釋

多備份重要的程式碼

  • 程式碼不能只有一份
  • 啟用編輯器的自動備份
  • 用程式碼管理工具備份

堅持字元編碼統一

PHP檔案編碼 == 模版編碼 == 資料庫編碼

使用之前,變數要初始化

function getInfo($arrId){
$ids = implode(',', $arrId);
$query = mysql_query("select * from test where id in ($ids)");
while($info = mysql_fetch_array($query)){
$info['name'] = trim($info['name']);
$info['addr'] = trim($info['addr']);
$list[] = $info; } return $list; }
function getInfo($arrId){
$list = array();
$ids = implode(',', $arrId);
$query = mysql_query("select * from test where id in ($ids)");
while($info = mysql_fetch_array($query)){
$info['name'] = trim($info['name']);
$info['addr'] = trim($info['addr']);
$list
[] = $info; } return $list; }

使用一個未定義的變數, 比使用一個定義好的變數要慢8倍以上!
可以相像, PHP引擎會首先按照正常的邏輯來獲取這個變數, 然而這個變數不存在, 所以
PHP引擎需要丟擲一個NOTICE, 並且進入一段使用未定義變數時應該走的邏輯, 然後返回
一個新的變數.
另外, 閱讀程式碼的角度講, 當你使用一個未定義的變數時, 會讓閱讀你程式碼的人困惑:”這
個變數在那裡初始化的, 和之前的程式碼有關係麼? 和include進來的檔案有關係麼?”

使用 NULL === 來代替 is_null

is_null和 NULL === 完全是一樣的效果, 但是卻節省了一次函式呼叫.

儘量使用 === 儘量不用 ==

PHP有倆組相等比較運算子 === /!==== /!= , == /!= 會有隱式型別轉換,=== /!== 會嚴格比較倆個操作時是否型別相同並且值相等.

避免在for迴圈中計算

for($i=0; $i<strlen($str); $i++) {
}

會導致每次迴圈都呼叫strlen, 改為

$j=strlen($str);
for ($i=0; $i<$j; $i++) {
}

strtr替代str_replace

$subject = 'hello, world';
echo strtr($subject, array('hello'=>'world', 'world'=>'hello'));
echo str_replace(['hello'=>'world'], ['world'=>'hello'],$subject);

strtr函式的效率是str_replace的四倍

優先使用單引號

$row[‘id’] 的效率是 $row[id]7

header頭的編碼

header("Content-type: text/html;charset=utf-8");

php結束標記不要寫

純 PHP 程式碼,最好在檔案末尾刪除 PHP 結束標記

測試環境開啟所有錯誤

error_reporting(7)
  • 1:E_ERROR
  • 2:E_WARNING
  • 4:E_PARSE
    但切記,上線之後要關閉我們的報錯,將我們的錯誤程式碼寫入到錯誤日誌中,方便查錯

遮蔽錯誤非常低效

養成不用 @ 的好習慣

$handle = @file('a.txt');

用FALSE表示錯誤, 用NULL表示不存在

對於操作類的函式, 失敗返回FALSE, 表示”操作失敗了”, 而對於查詢類的函式,
如果找不到想要的值, 則應該返回NULL, 表示”找不到”.

優先使用PHP內建函式

正則耗時, 儘量避免, 而採用直接的字串處理函式代替, 如:

filter_var('[email protected]', FILTER_VALIDATE_EMAIL);

有用的PHP內建函式

usort — 使用使用者自定義的比較函式對陣列中的值進行排序
rawurlencode — 按照 RFC 1738URL 進行編碼
parse_url — 解析 URL,返回其組成部分
http_build_query — 生成 URL-encode 之後的請求字元串
exif_imagetype — 判斷一個影象的型別
uniqid — 生成一個唯一ID
get_browser — 獲取瀏覽器具有的功能
str_word_count — 返回字元串中單詞的使用情況

我們php手冊中常見的字串函式和陣列函式,也需要熟悉,優先使用

防禦式程式設計思想

不要相信外部的一切輸入! 所有的輸入都要檢查!

<?php
$username = htmlspecialchars($_GET['username']);

使用PDO操作MySQL

# 寫法一
$sql = "select * from chapter where id=:id";
// 預處理 SQL 語句
$res = $db->prepare($sql);
// 執行 SQL
if ($res->execute([":id" => 1])) {
// 獲取一行結果集
$row = $res->fetch();
print_r($row);
}
# 寫法二
$sql = "select * from chapter where id=? and status=?";
// 預處理 SQL 語句
$res = $db->prepare($sql);
// 執行一條預處理語句
if ($res->execute([2, 1])) {
// 獲取一行結果集
$row = $res->fetch();
print_r($row);
}

PHP的語法糖即語言結構

echo(), print(),die(),isset(),unset(),include(),include_once(),requ
ire(),require_once(),array(),list(),empty(),eval()

echo的逗號和點號

$foo = 'hello';
$bar = 'world';
echo $foo . $bar;
echo $foo , $bar;

逗號優於點號

指令碼執行效率檢測

microtime()對指令碼的執行計時
參考文件:
https://www.php.net/manual/zh/function.error-reporting.php

判斷字串的長度

$str = 'hello';
if (strlen($str) === 5) echo 'do sth...';
if (!isset($str[5])) echo 'do sth..';

strlen()函式函式執行起來相當快,只返回在zval 結構中儲存的已知字串長
度。但是由於strlen()是函式,多多少少會有些慢,isset()是語法糖,因為函式的呼叫會在記憶體裡開闢記憶體空間增加記憶體消耗

使用[]代替array()

$arr = array();
$arr = [];
$arr = array(1,2,3,4);
$arr = [1,2,3,4];

用 … 定義變長引數函式

function addAll(...$num){
    $sum = '';
    $sum = array_sum($num);
    return $sum;
}
addAll(1,2,3,4,5,6,7);

不用eval()

eval() 能夠執行所有的php程式碼,非常的危險!慎用!

//執行當前檔案程式所在目錄
eval('echo `pwd`;');

解決方案:

  1. 編譯php環境時去除eval()語法糖
  2. 使用Suhosin保護PHP應用系統

PHP程式碼的優化

if程式碼塊的優化

<?php
if ( 1 == $orderState ) {
$status = 'success';
}else{
$status = 'error';
}
return $status;
#### 完全可以簡化成如下程式碼
//1 先宣告變數賦值,2 判斷是否等於1,是則怎麼樣不是則怎麼樣
$orderState = 'error';
if ( 1 == $orderState ) {
$status = 'success';
}
return $status;

使用三元運算子來替換if

<?php
if ( !empty($_POST['action']) ) {
$action = $_POST['action'];
}else{
$action = 'default';
}
#### 完全可以簡化成如下程式碼
$action = !empty($_POST['action']) ? $_POST['action'] : 'default'

中間結果賦值給變數

<?php
$str = 'this_is_test';
$res = implode('', array_map('ucfirst', explode('_', $str)));
#### 完全可以簡化成如下程式碼
$str = 'this_is_test';
$words = explode('_', $str);
$uWords = array_map('ucfirst', $words);
$res = implode(' ', $uWords);

結果:
在這裡插入圖片描述

使用更加精悍短小的程式碼

  • 函式的最佳最大長度是 50-150行程式碼 ,更容易理解也方便修改
  • 函式引數 不超過7個
  • 只做一件事情的函式更易於複用

PHP的編碼規範

https://github.com/PizzaLiu/PHP-FIG
1、psr-1編碼規範(重要)
https://github.com/PizzaLiu/PHP-FIG/blob/master/PSR-1-basic-coding-standard-cn.md

  • PHP程式碼檔案必須以 <?php 或 <?= 標籤開始;
  • PHP程式碼檔案必須以 不帶BOM的 UTF-8 編碼;
  • PHP程式碼中應該只定義類、函式、常量等宣告,或其他會產生 從屬效應 的操作(如:生成檔案輸出以及修改.ini配置檔案等),二者只能選其一;
  • 名稱空間以及類必須符合 PSR 的自動載入規範:PSR-4;
  • 類的命名必須遵循 StudlyCaps 大寫開頭的駝峰命名規範;
  • 類中的常量所有字母都必須大寫,單詞間用下劃線分隔;
  • 方法名稱必須符合 camelCase 式的小寫開頭駝峰命名規範。

2、psr-2編碼規範(重要)
https://github.com/PizzaLiu/PHP-FIG/blob/master/PSR-2-coding-style-guide-cn.md

  • 程式碼必須遵循 PSR-1 中的編碼規範 。
  • 程式碼必須使用4個空格符而不是 tab鍵 進行縮排。
  • 每行的字元數應該軟性保持在80個之內, 理論上一定不可多於120個, 但一定不能有硬性限制。
  • 每個 namespace 名稱空間宣告語句和 use 宣告語句塊後面,必須插入一個空白行。
  • 類的開始花括號({)必須寫在其聲明後自成一行,結束花括號(})也必須寫在其主體後自成一行。
  • 方法的開始花括號({)必須寫在函式聲明後自成一行,結束花括號(})也必須寫在函式主體後自成一行。
  • 類的屬性和方法必須新增訪問修飾符(private、protected 以及 public), abstract 以及 final 必須宣告在訪問修飾符之前,而 static 必須宣告在訪問修飾符之後。
  • 控制結構的關鍵字後必須要有一個空格符,而呼叫方法或函式時則一定不能有。
  • 控制結構的開始花括號({)必須寫在宣告的同一行,而結束花括號(})必須寫在主體後自成一行。
  • 控制結構的開始左括號後和結束右括號前,都一定不能有空格符。

以下例子程式簡單地展示了以上大部分規範:

<?php
namespace Vendor\Package;

use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class Foo extends Bar implements FooInterface
{
    public function sampleFunction($a, $b = null)
    {
        if ($a === $b) {
            bar();
        } elseif ($a > $b) {
            $foo->bar($arg1);
        } else {
            BazClass::bar($arg2, $arg3);
        }
    }

    final public static function bar()
    {
        // method body
    }
}

3、psr-3編碼規範-定義日誌規範(重要)
https://github.com/PizzaLiu/PHP-FIG/blob/master/PSR-3-logger-interface-cn.md

4、psr-4名稱空間編碼規範(重要)
https://github.com/PizzaLiu/PHP-FIG/blob/master/PSR-4-autoloader-cn.md