PSR-2 编码风格手册

PSR-2 Coding Style Guide


這份文件(PSR-2)從PSR -1 這份基本編碼標準所延伸、擴充 。

本文件希望能藉由一套共用的規則讓大家可以格式化 PHP 程式,以期降低大家在看各作者間程式碼時,因風格的不同所造成的衝擊。

此處的風格規則由不同專案的成員所合作。各成員彼此合作於多個專案間,而這份指導方針讓他們使用在各個專案間。因此,這份文件的優點就是沒有規則,而唯一的規則就是分享。

在文件中所使用到的關鍵字 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, 以及 “OPTIONAL” 皆引用自 RFC 2199 中說明。

譯註:
為了讓語句順暢,這邊就不先針對每個字翻譯;而為了維持原文件中之強調性,所以都會將這幾個關鍵字加粗並在其後接上原字,例如一定 (MUST)

1. 總覽


  • 程式碼一定 (MUST) 得依循 PSR-1(翻譯)。
  • 程式碼的縮排一定 (MUST) 是用四個空白,而非 tab。
  • 每行的字數長度需 (SHOLD) 得少於 80 字元;一定 (MUST) 要將相對限制(soft limit) 設定在 120 字元;必不要 (MUST NOT) 寫到絕對限制 (hard limit)。
  • 宣告 命名空間 (namespace) 之下一定(MUST) 要空一行,以及宣告  use 之下一定 (MUST) 也要空一行。
  • 類別 (class) 所使用的成對花括號,一定(MUST) 要將開始的放在宣告的下一行,以及程式碼本體結束的下一行。
  • 方法 (method) 所使用的成對花括號,一定(MUST) 要將開始的放在宣告的下一行,以及程式碼本體結束的下一行。
  • 所有屬性或是方法的可視屬性(visibility)一定(MUST) 要宣告, abstract 以及 final 一定(MUST) 是宣告在可視屬性之前; static 則一定(MUST) 是宣告在可視屬性之後。
譯註:
PHP 的 visibility 其實就是大家比較常聽到的修飾詞,private、protected 以及 public 這幾個封裝屬性、函式用的文字。
  • 控制結構 (control structure) 的關鍵字一定(MUST) 要在其後加入一個空白;方法(Method) 與函式(Function)則一定不要(MUST NOT)
  • 控制結構的開始(左)花括號一定(MUST) 要在宣告啟始的同一行,而結束(右)花括號則一定(MUST) 要在其程式碼本體結束的下一行。
  • 控制結構中,用到括弧時,其開始(左)括弧之後與結束(右)括弧之前一定不要(MUST NOT) 有空白。

1.1 範例

下面這個範例包含一些總覽中的規則

<?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()
    {
        // 方法程式碼本體
    }
}


2. 通則


2.1 基本編碼標準

程式碼一定 (MUST) 要依循 PSR-1(翻譯) 的說明。

2.2 檔案

所有 PHP 檔案一定(MSUT) 要使用 Unix LF(Line Feed) 做為行的結束。

所有 PHP 檔案在最後結尾處一定(MSUT) 要有一空白行。

在只有 PHP 程式碼的檔案裡,最後一定 (MUST) 不要有結束標籤 ?> 。

2.3 行

每行長度一定不要 (MUST NOT) 用到絕對限制 (hard limit)。

每行的相對限制 (soft limit) 一定 (MUST) 要設定在 120 個字元;自動風格在偵測相對限制時,一定 (MUST) 要設定為警告(warn),而不要 (MUST NOT) 設定為錯誤(error)。

每行最好不要 (SHOULD NOT) 超過 80 個字元;若是超過,最好(SHOULD) 是拆成多行並維持每行長度 80 字元內。

在非空行的尾端一定不要(MUST NOT) 有空白。

可以 (MAY) 增加空白行增加可讀性,同時可以表達段程式碼是有關連的。

每行一定不要 (MUST NOT) 超過一個敘述 (statement)。

2.4 縮排

程式碼的縮排一定 (MUST) 是使用四個空白,而不要 (MUST NOT) 使用跳格做為縮排。

備註:只使用空白,不要將空白與 tabs 混用,以避免在散播、補釘、歷史版本以及備註時所發生的問題。而使用空白讓我們在進一步做子縮排時,都很容易地做到對齊的動作。

2.5 關鍵字以及 True/False/Null

PHP 的關鍵字一定 (MUST) 是小寫。

PHP 的 true、 false 以及 null 這幾個常數也一定 (MUST) 是小寫。

 

3. Namespace 與 use 宣告


當存在時,在宣告 namespace 的下一行一定(MUST) 要是空行。

當存在時,所有 use 宣告都一定(MUST) 要在 namespace 宣告之後。

每個宣告都一定(MUST) 要有關鍵字 use 。

在 use 區塊之後一定(MUST) 要有一行空行隔開。

範例:

<?php
namespace Vendor\Package;

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

// ... additional PHP code ...


4. 類別、屬性以及函式


Class  一詞包含所有類別、介面以及其所有特性。
譯註:trait 在 PHP 5.4 中泛指所有能被重覆使用的函式。 http://php.net/manual/en/language.oop5.traits.php

4.1 繼承與實作

這 extends 以及 implements 關鍵字與其類別名稱必需被宣告在同一行。

所使用的成對的大括號之左括號 “{” 一定 (MUST) 是自己獨立一行,而右括號 “}” 也一定 (MUST) 是獨立在程式本體的下一行。

<?php
namespace Vendor\Package;

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

class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
    // constants, properties, methods
}

而實作類別的清單 可以 (MAY) 拆開成數行,而緊接在後的每一行皆要縮排。若是要這麼做時,清單中的第一個類別 一定 (MUST) 是在宣告的下一行,而每行就是獨立一個介面。

<?php
namespace Vendor\Package;

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

class ClassName extends ParentClass implements
    \ArrayAccess,
    \Countable,
    \Serializable
{
    // constants, properties, methods
}

4.2 屬性

所以屬性在宣告時一定 (MUST) 要給予初始值。

屬性的宣告一定不能 (MUST NOT) 使用關鍵字 var 。

每一次的宣告必不能 (MUST NOT) 超過一個屬性。

屬性若是 protected 或是 private 時,其名稱不需要 (SHOULD NOT) 有個底線做為前置。

一個屬性的宣告方式看起來如下。

<?php
namespace Vendor\Package;

class ClassName
{
    public $foo = null;
}

4.3 方法

每個方法的可視屬性(visibility) 一定(MUST) 要宣告。

方法名稱不需要(SHOULD NOT) 在 protected 或是 private 這兩個屬性前加上下底線(“_”)為前置符號。

方法名稱之後一定不要(MUST NOT) 有空白。開始(左)花括號請務必(MUST) 讓他自己存在於一行,且結束(右)花括號也一定(MUST) 要置於程式碼本體之下一行。而開始(左)括弧之後以及結束(右)括弧之前一定不要(MUST NOT) 有空白。

一個方法的宣告可參考下面範例。請注意括弧、逗號、空白以及花括號的位置:

<?php
namespace Vendor\Package;

class ClassName
{
    public function fooBarBaz($arg1, &$arg2, $arg3 = [])
    {
        // 方法程式碼本體
    }
}

4.4 方法的參數

在參數清單中,每個逗號前一定不要 (MUST NOT) 有空白,而其後一定 (MUST) 要有空白。

方法的參數若是有預設值,則一定(MUST) 要放在參數清單的最後。

<?php
namespace Vendor\Package;

class ClassName
{
    public function foo($arg1, &$arg2, $arg3 = [])
    {
        // 方法程式碼本體
    }
}


參數清單可以(MAY) 拆開成多行,而每行就是獨立一個參數。若是要這麼做,其第一個參數一定(MUST)要在宣告的下一行,每行一定(MUST) 只有一個參數。

當參數清單要拆成多行,其結束(右)括弧以及開始(左)花括號一定(MUST) 要在同一行,同時其中間要以空白隔開。

<?php
namespace Vendor\Package;

class ClassName
{
    public function aVeryLongMethodName(
        ClassTypeHint $arg1,
        &$arg2,
        array $arg3 = []
    ) {
        // 方法程式碼本體
    }
}

4.5 abstract、final以及static

當出現 abstract 以及 final 宣告時,一定(MUST) 要在將之宣告於可視屬性(visbility) 之前。

當出現 static 宣告時,一定(MUST) 要將之宣告於可視屬性(visbility) 之後。

<?php
namespace Vendor\Package;

abstract class ClassName
{
    protected static $foo;

    abstract protected function zim();

    final public static function bar()
    {
        // 方法程式碼本體
    }
}

4.6 方法與函式呼叫

當建立一個方法(method)或是函式(function)時,在函式名稱以及開始括弧之間一定不要 (MUST NOT) 有空白,而開始括弧後與結束括弧前也一定不要 (MUST NOT) 有空白。在參數列所用的逗號前一定不要 (MUST NOT) 有空白,而每個逗號後一要 (MUST) 有空白。

<?php
bar();
$foo->bar($arg1);
Foo::bar($arg2, $arg3);

<?php
bar();
$foo->bar($arg1);
Foo::bar($arg2, $arg3);

參數列可以 (MAY) 拆成多行,而每行都縮排。若是要這麼做,第一個參數一定 (MUST) 要再下一行,而且每行就一定 (MUST) 只有一個參數。

<?php
$foo->bar(
    $longArgument,
    $longerArgument,
    $muchLongerArgument
);

5. 控制結構


控制結構的通用規則如下:

  • 在控制結構的關鍵字之後一定 (MUST) 要用一個空白隔開。
  • 在左括弧 “(” 之後一定不要 (MUST NOT) 有空白。
  • 在右括弧 “)” 之前一定不要 (MUST NOT) 有空白。
  • 在右括弧 “)” 以及開始大(花)括號 ”{“ 之間 一定 (MUST) 要有一個空白隔開。
  • 結構本體一定 (MUST) 要有一次縮排。
  • 結束的大括號 “}” 一定 (MUST) 要在結構本體的下一行。

每個結構內容都一定 (MUST) 要被包覆在成對的大括號之間。這種標準化看起來會比較有結構,而且可以降低當有新內容要加入主體時錯置的可能性。

5.1 if、elseif、else

一個 if 結構看起來如下。請注意括弧、空白以及大括號的位置;還有 else 以及 elseif 跟結束的大括號 “}” 在主體前的同一行裡。

<?php
if ($expr1) {
    // if 主體
} elseif ($expr2) {
    // elseif 主體
} else {
    // else 主體;
}

所有 else if 這個關鍵字需 (SHOULD) 用 elseif 來取代之。

5.2 switch、case

一個 switch 結構看起來如下。請注意括號、空白以及大括號的位置。 case 敘述一定 (MUST) 要比switch 再縮排一次,而關鍵字 break (或其他結束關鍵字) 的縮排層級一定 (MUST) 是同於 case 的程式本體。當今天有一個直透非空的 case 本體之狀況一定 (MUST) 要註解 // no break 。

<?php
switch ($expr) {
    case 0:
        echo 'First case, with a 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;
}

5.3 while、do while

一個 while 結構看起來如下。請注意括號、空白以及大括號的位置。

<?php
while ($expr) {
    // 結構本體
}


同樣地,一個 do while 結構看起來如下。請注意括號、空白以及大括號的位置。

<?php
do {
    // 結構本體
} while ($expr);

5.4 for

一個 for 敘述看起來如下。請注意括號、空白以及大括號的位置。

<?php
for ($i = 0; $i < 10; $i++) {
    // for 本體
}


5.5 foreach

一個 foreach 敘述看起來如下。請注意括號、空白以及大括號的位置。

<?php
foreach ($iterable as $key => $value) {
    // foreach 本體
}

5.6 try、catch

一個 try catch 敘述看起來如下。請注意括號、空白以及大括號的位置。

<?php
try {
    // try 本體
} catch (FirstExceptionType $e) {
    // catch 本體
} catch (OtherExceptionType $e) {
    // catch 本體
}


6. 閉包


宣告閉包時一定(MUST) 要有一個空白在 function 這個關鍵字之後,以及在關鍵字 user 的前後都要有一個空白。

開始(左)花括號一定(MUST)是與其宣告起始在同一行,且結束(右)花括號一定(MUST) 在程式本體結束的下一行。

在開始(左)括弧以及結束(右)括弧與參數或是變數清單之間一定不要(MUST NOT) 有空白。

在參數以及變數清單中的逗號前一定不要(MUST NOT) 有空白,以及逗號之後一定(MUST) 要有一個空白。

閉包中的參數若是有預設值時,一定(MUST) 要放置在參數清單之最後。

閉包的宣告可以參考下面範例。請注意括弧、逗號、空白以及花括號之位置。

<?php
$closureWithArgs = function ($arg1, $arg2) {
    // 程式碼本體
};

$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
    // 程式碼本體
};

參數以及變數清單可以(MAY) 被拆成多行,其每行皆只有獨立一個。當打算這麼做時,清單中的第一個參數/變數一定(MUST) 要在在宣告的下一行,以及每行一定(MUST) 只能有一個參數或變數。

當清單被拆成多行其最後(參數或變數皆是如此),所使用的結束(右)括弧以及開始(左)花括號一定(MUST)要在同一行並用空白將二者隔開。

下面是閉包的範例。

<?php
$longArgs_noVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) {
   // 程式碼本體
};

$noArgs_longVars = function () use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // 程式碼本體
};

$longArgs_longVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // 程式碼本體
};

$longArgs_shortVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use ($var1) {
   // 程式碼本體
};

$shortArgs_longVars = function ($arg) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // 程式碼本體
};


請注意若是要在閉包中的參數使用方法 (method) 或是函式 (function) 的格式如下:

<?php
$foo->bar(
    $arg1,
    function ($arg2) use ($var1) {
        // body
    },
    $arg3
);

 

7. 總結


在這份文件中有許多刻意被省略的元素以及做法。這裡僅列出部份:

  • 宣告全域變數與全域常數
  • 宣告功能
  • 運算元與設定值
  • 行內的對齊
  • 註解以及文件說明區塊
  • 類別名稱的前置以及結尾
  • 最佳的實作

建議未來可以(MAY) 修改以及擴充這份文件以解決這些或是其他風格以及實作的元素。

 

附錄 A. 檢視


這份檢視為撰寫這份風格文件過程中,整個團隊之所有成員在專案中共同決定參照結果。在此留給大家參考。

A.1 檢視資料

url,http://www.horde.org/apps/horde/docs/CODING_STANDARDS,http://pear.php.net/manual/en/standards.php,http://solarphp.com/manual/appendix-standards.style,http://framework.zend.com/manual/en/coding-standard.html,http://symfony.com/doc/2.0/contributing/code/standards.html,http://www.ppi.io/docs/coding-standards.html,https://github.com/ezsystems/ezp-next/wiki/codingstandards,http://book.cakephp.org/2.0/en/contributing/cakephp-coding-conventions.html,https://github.com/UnionOfRAD/lithium/wiki/Spec%3A-Coding,http://drupal.org/coding-standards,http://code.google.com/p/sabredav/,http://area51.phpbb.com/docs/31x/coding-guidelines.html,https://docs.google.com/a/zikula.org/document/edit?authkey=CPCU0Us&hgd=1&id=1fcqb93Sn-hR9c0mkN6m_tyWnmEvoswKBtSc0tKkZmJA,http://www.chisimba.com,n/a,https://github.com/Respect/project-info/blob/master/coding-standards-sample.php,n/a,Object Calisthenics for PHP,http://doc.nette.org/en/coding-standard,http://flow3.typo3.org,https://github.com/propelorm/Propel2/wiki/Coding-Standards,http://developer.joomla.org/coding-standards.html
voting,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,no,no,no,?,yes,no,yes
indent_type,4,4,4,4,4,tab,4,tab,tab,2,4,tab,4,4,4,4,4,4,tab,tab,4,tab
line_length_limit_soft,75,75,75,75,no,85,120,120,80,80,80,no,100,80,80,?,?,120,80,120,no,150
line_length_limit_hard,85,85,85,85,no,no,no,no,100,?,no,no,no,100,100,?,120,120,no,no,no,no
class_names,studly,studly,studly,studly,studly,studly,studly,studly,studly,studly,studly,lower_under,studly,lower,studly,studly,studly,studly,?,studly,studly,studly
class_brace_line,next,next,next,next,next,same,next,same,same,same,same,next,next,next,next,next,next,next,next,same,next,next
constant_names,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper
true_false_null,lower,lower,lower,lower,lower,lower,lower,lower,lower,upper,lower,lower,lower,upper,lower,lower,lower,lower,lower,upper,lower,lower
method_names,camel,camel,camel,camel,camel,camel,camel,camel,camel,camel,camel,lower_under,camel,camel,camel,camel,camel,camel,camel,camel,camel,camel
method_brace_line,next,next,next,next,next,same,next,same,same,same,same,next,next,same,next,next,next,next,next,same,next,next
control_brace_line,same,same,same,same,same,same,next,same,same,same,same,next,same,same,next,same,same,same,same,same,same,next
control_space_after,yes,yes,yes,yes,yes,no,yes,yes,yes,yes,no,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes
always_use_control_braces,yes,yes,yes,yes,yes,yes,no,yes,yes,yes,no,yes,yes,yes,yes,no,yes,yes,yes,yes,yes,yes
else_elseif_line,same,same,same,same,same,same,next,same,same,next,same,next,same,next,next,same,same,same,same,same,same,next
case_break_indent_from_switch,0/1,0/1,0/1,1/2,1/2,1/2,1/2,1/1,1/1,1/2,1/2,1/1,1/2,1/2,1/2,1/2,1/2,1/2,0/1,1/1,1/2,1/2
function_space_after,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no
closing_php_tag_required,no,no,no,no,no,no,no,no,yes,no,no,no,no,yes,no,no,no,no,no,yes,no,no
line_endings,LF,LF,LF,LF,LF,LF,LF,LF,?,LF,?,LF,LF,LF,LF,?,,LF,?,LF,LF,LF
static_or_visibility_first,static,?,static,either,either,either,visibility,visibility,visibility,either,static,either,?,visibility,?,?,either,either,visibility,visibility,static,?
control_space_parens,no,no,no,no,no,no,yes,no,no,no,no,no,no,yes,?,no,no,no,no,no,no,no
blank_line_after_php,no,no,no,no,yes,no,no,no,no,yes,yes,no,no,yes,?,yes,yes,no,yes,no,yes,no
class_method_control_brace,next/next/same,next/next/same,next/next/same,next/next/same,next/next/same,same/same/same,next/next/next,same/same/same,same/same/same,same/same/same,same/same/same,next/next/next,next/next/same,next/same/same,next/next/next,next/next/same,next/next/same,next/next/same,next/next/same,same/same/same,next/next/same,next/next/next


A.2 檢視說明

indent_type  : 縮排類型。  tab  = 使用 tab 鍵一次。  2  或  4  = 幾個空白鍵。

line_length_limit_soft  : 相對限制長度的字元數。  ?  = 沒有可識別或是無回應。  no  沒有限制。

line_length_limit_hard  : 絕對限制長度的字元數。  ?  = 沒有可識別或是無回應。  no  沒有限制。

class_names  : 類別如何命名。  lower  = 只能小心、  lower_under:  小寫加底線符號、  studly  = 大寫開頭之駝峰命名法。

class_brace_line  : 開始(左)花括號是否和關鍵字 class 在同(  same )一行,或是在其下(  next )一行?

constant_name  : 如何命名常數?  upper  = 大寫加底線符號。

true_false_null  : 關鍵字   true  、  false  以及  null  是否全小寫(  lower )或全大寫( upper  )。

method_names  : 如何命名方法的名稱?  camel  = 小寫開頭的駝峰命名法,  lower_under  = 小寫加底線符號。

method_brace_line  : 開始(左)花括號是否和方法名稱在同(  same )一行,或是在其下(  next )一行?

control_brace_line  : 開始(左)花括號是否和控制結構在同(  same )一行,或是在其下(  next )一行?

control_space_after  : 控制結構關鍵字之後是否要有一個空白?

always_use_control_braces  : 控制結構是否都要有花括號?

else_elseif_line  : 用到  else  或是  elseif  時,前一個敘述的結束(右)花括號是否要在同一行,或是在下一行?

case_break_indent_from_switch  : 關鍵字  case  與  break  與開始的  switch  敘述要使用幾次縮排?

function_space_after  : 在呼叫函式時,其函式名稱以及開始(左)括弧之間是否要有空白?

closing_php_tag_required  : 在一個謹有 PHP 內容的檔案中,是否需要結束(  ?>  )標籤?

line_endings  : 要以什麼類型做為每行的結束?

static_or_visibility_first  : 在宣告方法時,是要  static  在前還是可視屬性在前?

control_space_parens  : 控制結構的表示式其開始(左)括弧之後與結束(右)括弧之前是否要有一個空白?  yes   =  if ( $expr )  ,   no   =  if ( $expr )  。

blank_line_after_php  : 是否有一行空行在 PHP 開始標籤(  <?php   )之後。

class_method_control_brace  : 彙整開始括號要在類別、方法以及控制結構的哪一行。

A.3 檢視結果

indent_type:
    tab: 7
    2: 1
    4: 14
line_length_limit_soft:
    ?: 2
    no: 3
    75: 4
    80: 6
    85: 1
    100: 1
    120: 4
    150: 1
line_length_limit_hard:
    ?: 2
    no: 11
    85: 4
    100: 3
    120: 2
class_names:
    ?: 1
    lower: 1
    lower_under: 1
    studly: 19
class_brace_line:
    next: 16
    same: 6
constant_names:
    upper: 22
true_false_null:
    lower: 19
    upper: 3
method_names:
    camel: 21
    lower_under: 1
method_brace_line:
    next: 15
    same: 7
control_brace_line:
    next: 4
    same: 18
control_space_after:
    no: 2
    yes: 20
always_use_control_braces:
    no: 3
    yes: 19
else_elseif_line:
    next: 6
    same: 16
case_break_indent_from_switch:
    0/1: 4
    1/1: 4
    1/2: 14
function_space_after:
    no: 22
closing_php_tag_required:
    no: 19
    yes: 3
line_endings:
    ?: 5
    LF: 17
static_or_visibility_first:
    ?: 5
    either: 7
    static: 4
    visibility: 6
control_space_parens:
    ?: 1
    no: 19
    yes: 2
blank_line_after_php:
    ?: 1
    no: 13
    yes: 8
class_method_control_brace:
    next/next/next: 4
    next/next/same: 11
    next/same/same: 1
    same/same/same: 6


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值