PHP中PSR-[0-4]代碼規范


PHP-FIG

在說啥是PSR-[0-4]規范的之前,我覺得我們有必要說下它的發明者和規范者:PHP-FIG,它的網站是:www.php-fig.org。就是這個聯盟組織發明和創造了PSR-[0-4]規范,膜拜吧,屌絲們!

FIG 是 Framework Interoperability Group(框架可互用性小組)的縮寫,由幾位開源框架的開發者成立於 2009 年,從那開始也選取了很多其他成員進來,雖然不是 “官方” 組織,但也代表了社區中不小的一塊。組織的目的在於:以最低程度的限制,來統一各個項目的編碼規范,避免各家自行發展的風格阻礙了程序設計師開發的困擾,於是大伙發明和總結了PSR,PSR是Proposing a Standards Recommendation(提出標准建議)的縮寫,截止到目前為止,總共有5套PSR規范,分別是:

PSR-0 (Autoloading Standard) 自動加載標准 
PSR-1 (Basic Coding Standard) 基礎編碼標准 
PSR-2 (Coding Style Guide) 編碼風格向導 
PSR-3 (Logger Interface) 日志接口 
PSR-4 (Improved Autoloading) 自動加載的增強版,可以替換掉PSR-0了。

接下來的篇目,我們會針對這5套,深入了解下。仔細學習下受萬千PHPer熱捧的這5套規范到底有啥出眾之處。

PSR-0 規范

PRS-0規范是他們出的第1套規范,主要是制定了一些自動加載標准(Autoloading Standard),如果你英文比較好,可以直接看官網的這個:PSR-0,很短。我們打開PSR-0的主頁時,發現多了一個警告:

Deprecated - As of 2014-10-21 PSR-0 has been marked as deprecated. PSR-4 is now recommended as an alternative.

大概意思:

不推薦使用 - 在2014年10月21日PSR-0已被標記為過時。PSR-4現在推薦作為替代。

那么也就是說PSR-0已!經!過!時!了!,別哭,PHP代碼狗。雖說已經過時,但是我們也可以看看嘛,這不影響我們的學習,好了。廢話不說了,開始吧:

PSR-0強制性要求幾點:

  1. 一個完全合格的namespace和class必須符合這樣的結構:“\< Vendor Name>(< Namespace>)*< Class Name>”
  2. 每個namespace必須有一個頂層的namespace("Vendor Name"提供者名字)
  3. 每個namespace可以有多個子namespace
  4. 當從文件系統中加載時,每個namespace的分隔符(/)要轉換成 DIRECTORY_SEPARATOR(操作系統路徑分隔符)
  5. 在類名中,每個下划線(_)符號要轉換成DIRECTORY_SEPARATOR(操作系統路徑分隔符)。在namespace中,下划線(_)符號是沒有(特殊)意義的。
  6. 當從文件系統中載入時,合格的namespace和class一定是以 .php 結尾的
  7. verdor name,namespaces,class名可以由大小寫字母組合而成(大小寫敏感的)

是不是有點看不懂啊。什么namespace啊,什么autoloading啊。所以,如果你對命名空間還不是特別懂的話,可以google下namespace 和 自動加載相關的php知識。或者看下一篇,我專門來講講他們:namespace 和 autoloading

好,我們接着一條條舉例來分析下:

第1條

比如我的文件 /Doctrine/Common/IsolatedClassLoader.php 這樣子的一個類文件,那么你的namespace命名就必須聲明稱這樣:

聲明:namespace  \Doctrine\Common\
調用:\Doctrine\Common\IsolatedClassLoader

其中,Doctrine 表示一個模塊目錄 Vendor name, common就是namesapce, IsolatedClassLoader是class name。這樣一看就知道這個文件的目錄層次,一目了然。

再比如:/path/to/project/lib/vendor/Symfony/Core/Request.php 文件:

聲明:namespace \Symfony\Core
調用:\Symfony\Core\Request

第2,3條

namespace \Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php
namespace \Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php

必須有一個頂級的zend的namespace, zend 下面可以有message子命名空間。

第4條

看這個例子,我們需要new 一個這樣的類

new \Symfony\Core\Request

那么我再加載這個類文件時候,就要將分隔符 \ 轉換成 目錄,也就是去 Vendor -> Symfony->Core->Request.php 一層層的目錄找到這個文件。其實也就是和第1,2,3是反過來的對應關系。

第5條

第5條是說namespace命名中的這個 _ 符號 沒有任何用處,就是用來表示目錄分隔符的,但是注意在PRS-4中已經取消了這個_ ,那么我們還是看一下,這個過時的規定是怎么樣的:

\namespace\package\Class_Name => /path/to/project/lib/vendor/namespace/package/Class/Name.php

\namespace\package_name\Class_Name => /path/to/project/lib/vendor/namespace/package_name/Class/Name.php

以上2個namespace中的 _ 其實是目錄分隔符。並不是class name就是那樣的。現在PSR-4出來后,確實覺得這樣的規定有點不好。怪怪的。

第6條

第6條不用多說。既然你用php,文件名當然是得用.php 后綴結尾。這個規定的原因,我大致猜一下,估計是有人用 .php3 后綴的。好吧。這個是個神話了。因為在apache的配置文件中是允許的:

<IfModule dir_module>
    DirectoryIndex index.php index.php3 index.html index.htm
</IfModule>

所以,老老實實的用.php作為后綴名吧。

第7條

文件大小寫的問題,這個其實是很重要的。因為Linux系統下是區分文件名和目錄名大小寫的,而在Windows下是不區分的。所以就會經常出現問題,比如:

namespace  \Doctrine\Common\IsolatedClassLoader

在Linux下就去嚴格按照大小寫去找目錄和文件了。但是如果你在Windows下開發,全是小寫也不會報錯,你一發布到Linux上就悲劇了,提示找不到文件。所以,大小寫太重要了。

PSR-1 規范

還是那句話,如果你英文比較好,可以直接看官網的這個:PSR-1,也不長,基本能看懂。但是如果你英語不好,那么還是請繼續往下看

  1. PHP源文件必須只使用 <?php 和 <?= 這兩種標簽。
  2. 源文件中php代碼的編碼格式必須是不帶字節順序標記(BOM)的UTF-8。
  3. 一個源文件建議只用來做聲明(類(class),函數(function),常量(constant)等)或者只用來做一些引起副作用的操作(例如:輸出信息,修改.ini配置等),但不建議同時做這兩件事。
  4. 命名空間(namespace)和類(class) 必須遵守PSR-0標准。
  5. 類名(class name) 必須使用駱駝式(StudlyCaps)寫法 (注:駝峰式(cameCase)的一種變種,后文將直接用StudlyCaps表示)。
  6. 類(class)中的常量必須只由大寫字母和下划線(_)組成。
  7. 方法名(method name) 必須使用駝峰式(cameCase)寫法。

好,就是上面的基本7大點,有些很簡單,就不過多說明,第3點需要仔細說下。

第1條

這個基本都是大家都懂得的,PHP代碼必須只使用長標簽(<?php ?>)或者短輸出式標簽(<?= ?>);而不要使用其他標簽。

之所以說這個,是因為我們在學習PHP的時候,一般的教材都告訴我們說,php有4種標記風格:php的4種標記風格 所以,很多人就亂來了。特別是asp風格的兼職是折磨好么!!!

第2條

這個不多說,保存的時候格式必須是無BOM的UTF-8格式,否則會出現很多無法解釋的千奇百怪的問題。千萬別傻逼的用Windows下的text文本編輯器保存文件啊

第3條

這個通俗的說呢。就是別把一些輸出和修改的操作(副作用) 和 類文件混合在一起,專注一點,這個文件專門來聲明Class, 那個文件專門來修改配置文件,別混在一起寫:

所以,以下的這個文件是有問題的,最好不要這樣:

// 副作用:修改了ini配置
ini_set('error_reporting', E_ALL);

// 副作用:載入了文件
include "file.php";

// 副作用:產生了輸出
echo "<html>\n";

// 聲明 function
function foo()
{
	// 函數體
}

你看上面看起來多亂啊。最好全部分開來寫:

namespace Lib;

class Name
{
	public function __construct()
	{
		echo __NAMESPACE__ . "<br>";
	}

	public static function test()
	{
		echo __NAMESPACE__ . ' static function test <br>';
	}
}

修改ini:

ini_set('error_reporting', E_ALL);

require 文件:

require DIR . '/loading.php';

spl_autoload_register("\\AutoLoading\\loading::autoload");

你看是不是整齊好看多了。當然這個是很難約束的。自己仔細划分。

第4條

第4條是約束namespace的,前面已經說過,不多說。值得說的是名字要是駝峰方式來

第5條

class name必須要用駝峰方式寫,駝峰又分小駝峰和大駝峰(小駝峰是第一個字母是小寫)這樣寫看着舒服也比較規范,不做要求,反正是駝峰就可以了。我喜歡用小駝峰:

class getUserInfo
{
}

第6條

是規定類中的常量名(const)聲明必須要全部大寫,如果有多個單詞,就用_分開:

class getUserInfo
{
	// 全部大寫
	const NAME = 'phper';

	// 用_隔開
	const HOUSE_INFO = '已經深圳買房';

	public function getUserName()
	{
		//
	}
}​

第7條

method name必須要用駝峰方式寫,大小駝峰都可以,不做要求,我喜歡用小駝峰:

class getUserInfo
{
	public function getUserName()
	{
		//
	}
}

PRSR-2 規范

PSR-2 規范的官網鏈接在此:PSR-2 這一規范主要是約束代碼風格的,可是說是所有里面最關鍵最重要的,也是需要好好規范和共同遵守的。

我們一個個來看下,只能我大略的寫一些比較重要的,或者說平時用的最多的。

1、源文件

  1. 文件末尾必須空一行。
  2. 必須使用Unix LF(換行)作為行結束符。
  3. 純PHP代碼源文件的關閉標簽?>必須省略。

第3點其實是蠻重要的,我之前還老寫閉合,現在不寫了。這可以避免在 PHP 結束標記之后萬一意外加入了空格或者換行符,會導致 PHP 開始輸出這些空白,而腳本中此時並無輸出的意圖。

2、縮進

必須使用4個空格來縮進,不能使用Tab鍵。當然你如果把Tab在編輯器里手動設置為4個空格也可以。這樣的目的是因為:每個人的機器上的Tab鍵都不一樣,有些是4個空格,有些是8個空格,在你的機器上看着很爽的代碼,在別人機器上了就各種惡心了。所以,統一搞成4個空格,不管在哪里打開都是美觀的。

3、行

一行推薦的是最多寫80個字符,多於這個字符就應該換行了,一般的編輯器是可以設置的。

4、關鍵字和 True/False/Null

php的關鍵字,必須小寫,boolean值:true,false,null 也必須小寫

下面是php的keyword,必須小寫。

'__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor'

5、命名空間(Namespace)和導入(Use)聲明

先簡單文字描述下:

  1. 命名空間(namespace)的聲明后面必須有一行空行。
  2. 所有的導入(use)聲明必須放在命名空間(namespace)聲明的下面。
  3. 一句聲明中,必須只有一個導入(use)關鍵字。
  4. 在導入(use)聲明代碼塊后面必須有一行空行。

用代碼來說明下:

<?php
namespace Lib\Databases; // 下面必須空格一行

class Mysql
{
}

namespace下空一行,才能使用use,再空一行,才能聲明class

<?php
namespace Lib\Databases; // 下面必須空格一行

use FooInterface; // use 必須在namespace 后面聲明
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass; // 下面必須空格一行

class Mysql
{
}

6、類(class),屬性(property)和方法(method)

(1)、繼承(extends) 和實現(implement) 必須和 class name 寫在一行,切花括號要換行寫。

<?php
namespace Lib\Databaes;

class Mysql extends ParentClass implements \PDO, \DB // 寫一行
{ // 換行寫{
	
}

(2)、屬性(property)必須聲明其可見性,到底是 public 還是 protected 還是 private,不能省略,也不能使用var, var是php老版本中的什么方式,等用於public。

<?php
namespace Lib\Databaes;

class Mysql extends ParentClass implements \PDO, \DB // 寫一行
{
	public $foo = null;
	private $name = 'yangyi';
	protected $age = '17';
}

(3)、方法(method),必須 聲明其可見性,到底是 public 還是 protected 還是 private,不能省略。並且,花括號{必須換行寫。如果有多個參數,第一個參數后緊接, ,再加個空格,且函數name和( 之間必須要有個空格:function_name ($par, $par2, $pa3), 如果參數有默認值,也要用左右空格分開。

<?php
namespace Lib\Databaes;

class Mysql extends ParentClass implements \PDO, \DB // 寫一行
{
	public getInfo ($name, $age, $gender = 1) // 函數名getInfo和(之間有個空格,參數之間也要有空格。默認參數也要左右都有空格
	{ // 必須換行寫 {
	}
}

(4)、當用到抽象(abstract)和終結(final)來做類聲明時,它們必須放在可見性聲明 (public 還是protected還是private)的前面。而當用到靜態(static)來做類聲明時,則必須放在可見性聲明的后面。

直接上代碼:

<?php
namespace Vendor\Package;

abstract class ClassName
{
	protected static $foo; // static放后面

	abstract protected function zim(); // abstract放前面

	final public static function bar() // final放前面,static放最后。
	{
		// 方法主體部分
	}
}

7、控制結構

控制接口,就是 if else while switch等。這一類的寫法規范也是經常容易出現問題的,也要規范一下。

(1)、if,elseif,else寫法,直接上規范代碼吧:

<?php
if ($expr1) { // 左右空格
	// if body
} elseif ($expr2) { // elesif 連着寫
	// elseif body
} else {
	// else body;
}

(2)、switch,case 注意左右空格和換行,還是直接上規范代碼:

<?php
switch ($expr) { // 左右空格
	case 0:
		echo 'First case, with a break'; // 對齊
		break; // 換行寫break,也對齊。
	case 1:
		echo 'Second case, which falls through';
		// no break
	case 2:
	case 3:
	case 4:
		echo 'Third case, return instead of break';
		return;
	default:
		echo 'Default case';
		break;
}

(3)、while,do while 的寫法也是類似,要左右空格,上代碼:

<?php
while ($expr) { // 左右空格
	// structure body
}

do {
	// structure body; // 左右空格
} while ($expr);

(4)、for的寫法

<?php
for ($i = 0; $i < 10; $i++) { // 注意幾個參數之間的空格
	// for body
}

(5)、foreach的寫法

<?php
foreach ($iterable as $key => $value) { // 還是空格問題
	// foreach body
}

(6)、try catch的寫法

<?php
try {
	// try body
} catch (FirstExceptionType $e) { // 同樣也是注意空格。
	// catch body
} catch (OtherExceptionType $e) {
	// catch body
}

基本用到的就是這些了,其他什么閉包啥的用的不多就不過多的累述了。

PSR-3 規范

PSR-3規范主要是來規范日志接口(Logger Interface)的,老實講,其實平常接觸的不是特別多,所以就不說了,可以去看官網的PSR-3

PSR-4 規范

PSR-4規范是剛出沒多久的一條新的規范,它也是規范 自動加載(autoload)的,是對PSR-0的修改,屬於補充規范,

我簡單說下,主要是以下幾點: 

  1. 廢除了PSR-0中_就是目錄分割符的寫法,_下划線在完全限定類名中是沒有特殊含義了。 
  2. 類文件名要以 .php 結尾。 
  3. 類名必須要和對應的文件名要一模一樣,大小寫也要一模一樣。

 

 

參考:

https://www.zybuluo.com/phper/note/65033

http://segmentfault.com/a/1190000000380008

http://www.4wei.cn/archives/1002186 

http://wenku.baidu.com/view/7a21e44b48d7c1c708a14577.html#10002-tsina-1-87843-e29b4784eda5d1f51fb0c2a97a15da08 

https://github.com/hfcorriez/fig-standards


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM