PSR-2: Chuẩn trình bày code PHP đẹp
PSR-2: Coding Style Guide Bộ quy tắc này được tạo ra nhằm giảm bới những khó khăn trong việc đọc code của người khác, trình bày theo quy tắc ở đây áp dụng cho tất cả các Project, giúp cho code sáng sủa, dễ hiểu, dễ bảo trì hơn. Bài viết này yêu cầu bạn xem qua PSR-1: Chuẩn viết code PHP cơ bản ...
PSR-2: Coding Style Guide Bộ quy tắc này được tạo ra nhằm giảm bới những khó khăn trong việc đọc code của người khác, trình bày theo quy tắc ở đây áp dụng cho tất cả các Project, giúp cho code sáng sủa, dễ hiểu, dễ bảo trì hơn. Bài viết này yêu cầu bạn xem qua PSR-1: Chuẩn viết code PHP cơ bản bởi vì chuẩn PSR-2 dựa trên PSR-1 và mở rộng thêm
1. Nguyên tắc chung
1.1. Tuân thủ PSR-1
PSR-2 dựa trên PSR-1 và mở rộng thêm cho nên tuân thủ theo PSR-1 là điều hoàn toàn dễ hiểu phải không nào, đọc ngay PSR-1 tại đây: PSR-1: Chuẩn viết code PHP cơ bản
1.2. Đối với file php
- Mọi PHP files phải dùng Unix LF (linefeed) line ending.
- Mọi PHP files phải kết thúc bằng một dòng trống.
- Trong một file chỉ bao gồm code PHP thì không được viết tag đóng ?> nhé.
Nếu bạn dùng Editor/IDE, bạn nên cài EditorConfig để Editor/IDE giúp bạn trong việc này nhé, đọc ở đây Chuẩn hóa code style trên Editor/IDE bằng EditorConfig, trên sublime text Editor sẽ là end_of_line = lf và insert_final_newline = true
1.3. Lines - Về các dòng code
- Không có hard limit về độ dài của một dòng. Tức là bạn có thể code 1 dòng dài đến tận cùng thế giới vẫn được.
- Soft limit của độ dài một dòng phải là 120 chữ. Chương trình check style tự động phải báo warning nhưng không được báo error khi vượt quá soft limit.
- Một dòng nên có không quá 80 chữ. Dòng mà dài quá 80 chữ thì nên chia nhỏ ra thành nhiều dòng với độ dài mỗi dòng không quá 80 chữ.
Trong Sublime Text, bạn có thể chỉnh như sau để biết mình quá 80 ký tự hay không nha, ở trên thanh menu các bạn chọn View ➡Ruler➡80 - Một dòng mà có ký tự thì không được dư khoảng trắng ở cuối dòng.
public function foo() { return true;・・・・ } // ・・・・ chính là khoảng trắng
- Không được phép có quá một statement (lệnh) trên một dòng.
// sai quá sai $website = 'https://chungnguyen.xyz'; $name = 'Chung Nguyễn Blog'; // phải như vầy $website = 'https://chungnguyen.xyz'; $name = 'Chung Nguyễn Blog';
1.4. Indenting - Canh lề
Canh lề không dùng tab mà phải dùng 4 dấu cách. Các Editor/IDE thông minh sẽ tự convert nút tab trên bàn phím thành dấu cách, các bạn search google sẽ ra nhé. Hình dưới là cách cấu hình cho sublime text
1.5. Keywords và True/False/Null
Những keywords của PHP phải được viết thường. (không viết hoa)
Những constants của PHP là true, false, và null cũng cần phải viết thường. TRUE, True gì cơ bản là sai nguyên tắc hết nhé.
2. Khai báo Namespace và Use
- Cần phải có một dòng trắng phía sau khai báo namespace.
- Những phần khai báo use phải được đặt phía sau phần khai báo namespace.
- Phải dùng một từ use cho mỗi khao báo.
- Phải có một dòng trắng phía sau đoạn code use.
Ví dụ:
<?php namespace VendorPackage; use FooClass; use BarClass as Bar; use OtherVendorOtherPackageBazClass; use Auth, View, Session; // sai, phải tách thành 3 dòng use // ... additional PHP code ...
3. Classes, Properties, and Methods (Lớp, Thuộc tính và Phương thức - hàm)
Từ class ở đây được hiểu là cả những class bình thường, hay cả interfaces và traits.
3.1. Extends và Implements
Từ khoá extends và implements phải được viết cùng dòng với tên class.
Dấu mở ngoặc nhọn của class phải đứng trên một dòng riêng. Dấu đóng ngoặc phải được viết ở dòng sau của phần body.
<?php namespace VendorPackage; use FooClass; use BarClass as Bar; use OtherVendorOtherPackageBazClass; class ClassName extends ParentClass implements ArrayAccess, Countable { // constants, properties, methods }
Danh sách những interface được implements có thể được viết trên nhiều dòng, trong đó mỗi dòng theo sau được indent (canh lề) 1 lần. Khi thực hiện việc đó thì tên interface đầu tiên phải được đặt trên 1 dòng mới, và mỗi dòng chỉ được phép chứa tên 1 interface.
Ví dụ
<?php namespace VendorPackage; use FooClass; use BarClass as Bar; use OtherVendorOtherPackageBazClass; class ClassName extends ParentClass implements ArrayAccess, Countable, Serializable { // constants, properties, methods }
3.2. Properties - thuộc tính
Tính Visibility (public, protected, private) phải được khai báo ở mọi properties.
Không được dùng từ khoá var để khai báo một property.
Trên một dòng thì không được khai báo quá một property.
Tên property không nên được prefix bởi dấu gạch dưới _ để biểu thị tính protected hay private.
Khai báo property giống như sau.
<?php namespace VendorPackage; class ClassName { public $foo = null; }
3.3. Methods
Tương tự với property, tính Visibility phải được khao báo ở mọi methods
Tên Method không nên được prefix bởi dấu gạch dưới _ để biểu thị tính protected hay private.
Khi khai báo tên method thì không được để một khoảng trắng ở phía sau tên method. Dấu mở ngoặc nhọn phải được nằm trên một dòng riêng, và dấu đóng ngoặc phải được nằm trên dòng ngay sau phần thân của method. Không được có khoảng trắng sau dấu mở ngoặc tròn, và không được có khoảng trắng phía trước dấu đóng ngoặc tròn.
Khai báo một hàm giống như sau. Chú ý đến vị trí của dấu ngặc đơn, dấu phẩy, khoảng trắng và dấu ngoặc nhọn.
<?php namespace VendorPackage; class ClassName { public function fooBarBaz($arg1, &$arg2, $arg3 = []) { // method body } }
3.4. Method Arguments - Tham số của phương thức
Trong danh sách argument (tham số - đối số) thì không được có khoảng trắng trước mỗi dấu phẩy, và phải có một khoảng trắng sau mỗi dấu phẩy. Giống y như chính tả của ta vậy.
Những tham số mà có giá trị mặc định phải được đặt ở cuối của danh sách tham số. Ví du:
<?php namespace VendorPackage; class ClassName { public function foo($arg1, &$arg2, $arg3 = [], $arg4 = true) { // method body } }
Danh sách argument có thể được tách thành nhiều dòng, trong đó mỗi dòng theo sau được indent một lần. Khi làm vậy thì argument đầu tiên trong danh sách phải được đặt ở trên một dòng mới, và mỗi dòng chỉ được phép có một argument.
Khi mà danh sách argument được chia làm nhiều dòng, thì dấu đóng ngoặc tròn và dấu mở ngoặc nhọn phải được đặt cùng nhau trên một dòng, với một khoảng trắng ở giữa.
<?php namespace VendorPackage; class ClassName { public function aVeryLongMethodName( ClassTypeHint $arg1, &$arg2, array $arg3 = [], $arg4 = true ) { // method body } }
3.5. abstract, final, và static
Khi được sử dụng, abstract và final phải được đặt trước phần khai báo visibility.
Khi được sử dụng, static phải được đặt sau phần khai báo visibility.
<?php namespace VendorPackage; abstract class ClassName { protected static $foo; abstract protected function zim(); final public static function bar() { // method body } }
3.6. Gọi Method và Function
Khi gọi một method hay một function thì
- không được phép có khoảng trắng giữa tên của method hay function và dấu mở ngoặc tròn.
- Không được phép có khoảng trắng sau dấu mở ngoặc tròn.
- Và không được phép có khoảng trắng trước dấu đóng ngoặc tròn.
- Trong danh sách argument, không được phép có khoảng trắng trước mỗi dấu phẩy, và phải có một khoảng trắng sau mỗi dấu phẩy.
<?php bar (); // sai cái số 1 bar() ; // sai cái số 2 bar( ); // sai cái số 3 bar($arg1 , $arg2); // sai cái số 4 // đúng phải như vầy bar(); $foo->bar($arg1); Foo::bar($arg2, $arg3);
Danh sách tham số có thể được tách ra thành nhiều dòng, trong đó mỗi dòng theo sau được indent một lần. Khi làm như vậy thì tham số đầu tiên phải được đặt trên một dòng mới, và mỗi dòng chỉ được phép chứa một tham số.
<?php $foo->bar($firstArgument // sai vì tham số đầu tiên phải ở dòng mới $longArgument, // sai vì k có 1 canh lề $longerArgument, $longerArgument2, // sai vì có 2 tham số trên 1 dòng $muchLongerArgument ); // chuẩn $foo->bar( $longArgument, $longerArgument, $muchLongerArgument );
4. Control Structures - cấu trúc điều khiển
Những quy tắc chung khi viết Control Structures bao gồm:
- Phải có một khoảng trắng sau control structure keyword
- Không được có một khoảng trắng sau dấu mở ngoặc tròn
- Không được có một khoảng trắng trước dấu đóng ngoặc tròn
- Phải có một khoảng trắng sau đấu đóng ngoặc tròn và trước dấu mở ngoặc nhọn
- Phần thân của structure phải được indent một lần
- Dấu đóng ngoặc nhọn phỉa được đặt trên một dòng mới sau phần thân
Phần thân của mỗi structure phải được đặt trong dấu đóng mở ngoặc kép. Điều này sẽ làm tiêu chuẩn hoá cách viết structures, và làm giảm thiểu việc phát sinh ra lỗi khi mà có những dòng mới được thêm vào phần thân.
5.1. if, elseif, else
Một if structure được viết như sau. Hãy chú ý đến vị trí của dấu ngoặc tròn, khoảng trắng, dấu ngoặc nhọn. else và elseif được đặt trên cùng một dòng với dấu đóng ngoặc nhọn của phần body phía trước.
<?php if ($expr1) { // if body } elseif ($expr2) { // elseif body } else { // else body; }
5.2. switch, case
Một switch structure được viết như sau. Hãy chú ý đến vị trí của dấu ngoặc tròn, khoảng trắng và dấu ngoặc nhọn. Phần case phải được indent một lần so với switch, và break keyword (hay các keyword ngắt khác) phải được indent giống với phần thân của case. Phải có một comment kiểu như // no break nếu phần thân của case không trống, và được cố tình cho qua (không có 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
Một câu lệnh while được viết như sau. Hãy chú ý vào vị trí của dấu ngoặc tròn, khoảng trắng và dấu ngoặc nhọn.
<?php while ($expr) { // structure body }
Tương tự như vậy, một câu lệnh do while được viết như sau. Hãy chú ý vào vị trí của dấu ngoặc tròn, khoảng trắng và dấu ngoặc nhọn.
<?php do { // structure body; } while ($expr);
5.4. for
Một câu lệnh for được viết như sau. Hãy chú ý vào vị trí của dấu chấm phẩy, dấu ngoặc tròn, khoảng trắng và dấu ngoặc nhọn.
<?php for ($i = 0; $i < 10; $i++) { // for body }
5.5. foreach
Một câu lệnh foreach được viết như sau. Hãy chú ý vào vị trí của =>, dấu ngoặc tròn, khoảng trắng và dấu ngoặc nhọn.
<?php foreach ($iterable as $key => $value) { // foreach body }
5.6. try, catch
Một block try catch được viết như sau. Hãy chú ý vào vị trí của dấu ngoặc tròn, khoảng trắng và dấu ngoặc nhọn.
<?php try { // try body } catch (FirstExceptionType $e) { // catch body } catch (OtherExceptionType $e) { // catch body }
5. Closures
Closures phải được định nghĩa mới một khoảng trắng phía sau keywork function, và một khoảng trắng ở phía trước cũng như phía sau của keywork use.
Dấu mở ngoặc ngọn phải được đặt ở cùng dòng, và dấu đóng ngoặc nhọn phải được đặt ở một dòng mời phía sau phần thân.
Không được phép có một khoảng trắng ở phía sau dấu mở ngoặc tròn của phần khai báo danh sách argument hay variable, và không được phép có một khoảng trắng ở phía trước dấu đóng ngoặc tròn của phần khai báo danh sách argument hay variable.
Trong danh sách arugment hay variable, không được phép có khoảng trắng trước mỗi dấu phẩy, và phải có một khoảng trắng phía sau mỗi dấu phẩy.
Arguments của Closure mà có giá trị mặc định thì phải được đặt ở cuối của danh sách argument.
Cách định nghĩa một closure trông như sau.
A closure declaration looks like the following. Hãy chú ý vào vị trí của dấu ngoặc tròn, dấu phẩy, khoảng trắng và dấu ngoặc nhọn.
Danh sách argument và danh sách variable có thể được tách ra làm nhiều dòng, trong đó mỗi dòng theo sau được indent một lần. Khi làm như vậy thì argument hay variable đầu tiên phải được đặt ở trên một dòng mới, và mỗi dòng chỉ được phép chứa một argument hay một variable.
Khi mà kết thúc của danh sách (kể cả arguments hay variables) được chia thành nhiều dòng, thì dấu đóng ngoặc tròn và dấu mở ngoặc nhọn phải được đặt cùng nhau trên một dòng, với một khoảng trắng ở giữa.
Dưới đây là những ví dụ về các closures có và không có danh sách argument hay variable được chia thành nhiều dòng.
Chú ý rằng những quy tắc trên còn được áp dụng khi một closure được sử dụng trục tiếp như một argument trong một lời gọi hàm hay method.
6. Kết luận
Có rất nhiều yếu tố về style hay practice khác được cố tình bỏ qua trong hướng dẫn này. Có thể kể ra như:
-
Khai báo biến global (global variables) hay hằng global (global constants)
-
Khai báo hàm (functions)
-
Toán tử và phép gán
-
Inter-line alignment
-
Khối Comments và Documentation
-
Tiền tố và hậu tố trong tên Class
-
Best practices
Những recommendations sau này có thể xem xét lại và mở rộng hướng dẫn này để đề cập đến những yếu tố về style hay practice ở trên hay hoàn toàn khác.
Chúc các bạn nhớ hết các nguyên tắc này nhé