PSR-2 : راهنمای نوع کدنویسی
همانطور که در پست های قبلی گفته شد، هدف اصلی استاندارد PSR این است که سردرگمی شما به عنوان برنامه نویس را در زمانی که کدهای دیگران را میبینید کاهش دهد، که اینکار با رعایت نکات و استایل های کدنویسی توسط تمام برنامه نویسان PHP قابل انجام است.
استفاده از این استانداردها در تمام پروژه های PHP چه متن باز یا تجاری توصیه میشود که باعث هماهنگی بیشتر بین برنامه نویسان خواهد شد.
در ادامه آشنایی با استانداردهای PSR، در این مطلب میخواهیم با استاندارد PSR-2 آشنا شویم. این استاندارد به نوعی گسترش استاندارد PSR-1 است.
مرور کلی
عمومی
استاندارد پایه کدنویسی
استانداردهای PSR-1 باید رعایت شود.
فایل ها
تمام فایلهای PHP باید از Unix LF برای ایجاد خط جدید یا شناسایی پایان خط استفاده کنند (سیستم عامل ویندوز از CR استفاده میکند).
تمام فایلهای PHP باید دارای یک خط خالی در پایان فایل باشند.
علامت تگ پایان PHP یا <؟ باید در فایلهایی که تنها، حاوی کد PHP هستند حذف شوند.
خطوط
محدودیت شدیدی بر روی طول خط نباید وجود داشته باشد.
محدودیت ملایم بر روی طول خط باید ۱۲۰ کاراکتر باشد، که در صورتی که بیشتر از ۱۲۰ کاراکتر شد برنامه باید هشدار بدهد، اما هیچ اجباری مبنی بر رعایت آن نباید وجود داشته باشد.
خطها نباید بیشتر از ۸۰ کاراکتر باشند و خطهای طولانیتر باید به چند خط تبدیل شوند.
انتهای خط های غیر خالی نباید هیچ کاراکتر فاصلهای وجود داشته باشد.
فایلهای PHP میتوانند دارای خطهای خالی برای افزایش خوانایی باشند.
در هر خط تنها باید یک statement وجود داشته باشد.
تورفتگی
فایلهای PHP باید از ۴ کاراکتر فاصله (نه Tab) برای تورفتگی استفاده کنند.
کلمات کلیدی و True/False/Null
کلمات کلیدی PHP باید به صورت حروف کوچک (Lower Case) استفاده شوند.
کلمات کلیدی (ثابتهای) true, false و null باید به صورت حروف کوچک (Lower Case) استفاده شوند.
- Namespace and Use Declarations
زمانی که از namespace استفاده میشود باید یک خط خالی بعد از آن وجود داشته باشد.
تمام استفاده از کلمه کلیدی use باید بعد از namespace مورد استفاده قرار بگیرد.
هر use فقط باید برای یک کلاس مورد استفاده قرار بگیرد.
یک خط خالی بعد از استفاده از کلمات کلیدی use باید وجود داشته باشد.
مثال:
1 2 3 4 5 6 7 8 |
<?php namespace Vendor\Package; use FooClass; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; // ... additional PHP code ... |
- کلاس ها، ویژگی ها و متدها
لغت class به تمام کلاس ها، واسط ها و ویژگی ها اشاره می کند.
Exteneds و پیاده سازی ها
کلمات کلیدی extends و implements باید در همان خطی که کلاس تعریف شده است، مورد استفاده قرار بگیرد.
پرانتز (Braces) یا {} باید در خطهای جداگانه تعریف شوند.
مثال:
1 2 3 4 5 6 7 8 9 10 11 |
<?php namespace Vendor\Package; use FooClass; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; class ClassName extends ParentClass implements \ArrayAccess, \Countable { // constants, properties, methods } |
لیست implementهای کلاس میتواند به چند خط تقسیم شود. در این صورت در هر خط باید یک implement تعریف و در خط تعریف کلاس هیچ implementیی تعریف نشود، همچنین خطهای تعریف implement باید یک تورفتگی داشته باشند.
این قانون در مورد extend از interfaceها نیز صحیح میباشد (این بخش در PSR-2 Meta آمده است).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?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 } |
ویژگی ها
Visibility ویژگی ها باید همیشه تعریف شوند (مانند public, protected و private).
کلمه کلیدی var نباید در تعریف خواص مورد استفاده قرار بگیرد.
در هر خط باید یک ویزگی (property ) تعریف شود.
ابتدای ویژگی ها نباید با _(single underscore) شروع شود.
تعریف یک ویژگی به صورت زیر است:
1 2 3 4 5 6 7 |
<?php namespace Vendor\Package; class ClassName { public $foo = null; } |
متدها (Methods)
Visibility متدها باید همیشه تعریف شوند (مانند public, protected و private).
ابتدای متدها نباید با _ (single underscore) شروع شود.
نام متدها باید با یک فاصله بعد از کلمه کلیدی function تعریف شوند.
پرانتز (Braces) یا {} باید در خطهای جداگانه تعریف شوند.
در تعریف متد، قبل از پرانتز شروع و بعد از پرانتز پایان نباید فاصله ای وجود داشته باشد.
1 2 3 4 5 6 7 8 9 10 |
<?php namespace Vendor\Package; class ClassName { public function fooBarBaz($arg1, &$arg2, $arg3 = []) { // method body } } |
پارامترهای متد (Method Arguments)
در لیست پارامترهای متد باید یک فاصله قبل از پارامتر وجود داشته باشد و همچنین هیچ فاصلهای نباید بعد از پارامتر وجود داشته باشد.
پارامترهایی که دارای مقدار اولیه هستند باید در انتهای لیست تعریف شوند.
1 2 3 4 5 6 7 8 9 10 |
<?php namespace Vendor\Package; class ClassName { public function foo($arg1, &$arg2, $arg3 = []) { // method body } } |
لیست پارامترهای کلاس میتواند به چند خط تقسیم شود. در این صورت در هر خط باید یک پارامتر تعریف و در خط تعریف متد هیچ پارامتریی تعریف نشود، همچنین خطهای تعریف پارامتر باید یک تورفتگی داشته باشند.
زمانی که لیست پارامترها به چند خط تقسیم میشود، پرانتز باز کننده و پرانتز بسته کننده باید با هم در یک خط تعریف شوند.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php namespace Vendor\Package; class ClassName { public function aVeryLongMethodName( ClassTypeHint $arg1, &$arg2, array $arg3 = [] ) { // method body } } |
کلمات کلیدی abstract, final و static
کلمات کلیدی abstract و final باید قبل از کلمات کلیدی visibility استفاده شوند.
کلمه کلیدی static باید بعد از کلمات کلیدی visibility استفاده شوند.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php namespace Vendor\Package; abstract class ClassName { protected static $foo; abstract protected function zim(); final public static function bar() { // method body } } |
فراخوانی متد و تابع
زمان فراخوانی تابع یا متد، هیچ فاصلهایی نباید بین نام تابع و پرانتز باز کننده وجود داشته باشد. همچنین هیچ فاصلهایی بعد از پرانتز باز کننده و قبل از پرانتز بسته کنند نباید باشد.
در لیست آرگومانهای متد یا تابع باید یک فاصله قبل از آرگومان وجود داشته باشد و همچنین هیچ فاصلهای نباید بعد از آرگومان وجود داشته باشد.
1 2 3 4 |
<?php bar(); $foo->bar($arg1); Foo::bar($arg2, $arg3); |
لیست آرگومانهای تابع یا متد میتواند به چند خط تقسیم شود. در این صورت در هر خط باید یک آرگومان تعریف و در خط فراخوانی تابع یا متد هیچ آرگومانی تعریف نشود، همچنین خطهای تعریف آرگومان باید یک تورفتگی داشته باشند.
1 2 3 4 5 6 |
<?php $foo->bar( $longArgument, $longerArgument, $muchLongerArgument ); |
ساختارهای کنترلی
قوانین عمومی زیر برای تمام ساختارهای کنترلی میباشد:
- یک فاصله باید بعد از کلمه کلیدی ساختار کنترلی وجود داشته باشد.
- هیچ فاصلهایی نباید بعد از پرانتز باز کننده وجود داشته باشد.
- هیچ فاصلهایی نباید قبل از پرانتز بسته کننده وجود داشته باشد.
- یک فاصله باید بین پرانتز بسته کننده و پرانتز باز کننده وجود داشته باشد.
- بدنه ساختار کنترلی باید یک تورفتگی داشته باشند.
- پرانتز بسته کننده باید در خطی جداگانه وجود داشته باشد.
ساختار if, elseif و else
ساختار if باید به صورت زیر باشد. به جایگاه پرانتزها، فاصله ها و بریسها توجه کنید. همچنین کلمات کلیدی else و elseif در همان خط بریس بسته کننده ساختار قبلی هستند.
1 2 3 4 5 6 7 8 |
<?php if ($expr1) { // if body } elseif ($expr2) { // elseif body } else { // else body; } |
کلمه کلیدی elseif باید به جای کلمه کلیدی else if استفاده شود.
ساختار switch و case
ساختار switch باید به صورت زیر باشد. به جایگاه پرانتزها، فاصله ها و بریسها توجه کنید. کلمه کلیدی case باید یک تورفتگی از switch داشته باشند و کلمه کلیدی break باید با همان تورفتگی بدنه case نوشته شوند.
یک خط کامنت (مانند no break) در caseهایی که دارای break یا return نیستند باید وجود داشته باشد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?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; } |
ساختار while و do while
ساختار while باید مشابه زیر باشد. به جایگاه پرانتزها، فاصله ها و بریسها توجه کنید.
1 2 3 4 |
<?php while ($expr) { // structure body } |
همچنین do while
1 2 3 4 |
<?php do { // structure body; } |
ساختار for و foreach
ساختار for و foreach باید مشابه زیر باشد. به جایگاه پرانتزها، فاصله ها و بریسها توجه کنید.
1 2 3 4 |
<?php for ($i = 0; $i < 10; $i++) { // for body } |
1 2 3 4 |
<?php foreach ($iterable as $key => $value) { // foreach body } |
ساختار try و catch
ساختار try و catch باید مشابه زیر باشد. به جایگاه پرانتزها، فاصله ها و بریسها توجه کنید.
1 2 3 4 5 6 7 8 |
<?php try { // try body } catch (FirstExceptionType $e) { // catch body } catch (OtherExceptionType $e) { // catch body } |
Closures
در closureها باید یک فاصله بعد از کلمه کلیدی function و یک فاصله قبل و بعد از کلمه کلیدی use وجود داشته باشد.
پرانتز باز کننده باید در همان خط تعریف closure باشد و پرانتز بسته کننده آن باید در خطی جداگانه باشد.
هیچ فاصلهایی بعد از پرانتز باز کننده و قبل از پرانتز بسته کنند نباید باشد.
در لیست آرگومانها و متغیرهای closure باید یک فاصله قبل از آرگومان و متغیر وجود داشته باشد و همچنین هیچ فاصلهای نباید بعد از آرگومان و متغیر وجود داشته باشد.
آرگومانهای اختیاری باید در انتهای closure تعریف شوند.
ساختار closure باید مشابه زیر باشد. به جایگاه پرانتزها، فاصله ها و بریسها توجه کنید.
1 2 3 4 5 6 7 8 |
<?php $closureWithArgs = function ($arg1, $arg2) { // body }; $closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) { // body }; |
لیست آرگومانها و متغیرها میتواند به چند خط تقسیم شود. در این صورت در هر خط باید یک آرگومان یا متغیر تعریف و در خط تعریف closure هیچ آرگومانی تعریف نشود، همچنین خطهای تعریف آرگومان و متغیر باید یک تورفتگی داشته باشند.
زمانی که لیست آرگومانها و متغیرها به چند خط تقسیم میشود، پرانتز بسته کننده و بریس باز کننده باید با هم در یک خط تعریف شوند.
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 |
<?php $longArgs_noVars = function ( $longArgument, $longerArgument, $muchLongerArgument ) { // body }; $noArgs_longVars = function () use ( $longVar1, $longerVar2, $muchLongerVar3 ) { // body }; $longArgs_longVars = function ( $longArgument, $longerArgument, $muchLongerArgument ) use ( $longVar1, $longerVar2, $muchLongerVar3 ) { // body }; $longArgs_shortVars = function ( $longArgument, $longerArgument, $muchLongerArgument ) use ($var1) { // body }; $shortArgs_longVars = function ($arg) use ( $longVar1, $longerVar2, $muchLongerVar3 ) { // body }; |
فرمتهای بالا باید در زمانی که closure در واقع یک آرگومان متد یا تابع است نیز رعایت شوند.
1 2 3 4 5 6 7 8 |
<?php $foo->bar( $arg1, function ($arg2) use ($var1) { // body }, $arg3 ); |
همچنین ساختار زیر در استاندارد PSR-2 کاملاً درست است (این بخش در PSR-2 Meta آمده است).
1 2 3 4 5 6 7 8 |
<?php somefunction($foo, $bar, [ // ... ], $baz); $app->get('/hello/{name}', function ($name) use ($app) { return 'Hello '.$app->escape($name); }); |
نتیجهگیری
ساختارها و عناصر بیشتری نیز وجود دارند که در این استاندارد به آنها اشارهایی نشده که شامل زیر است ولی محدود به آن نیست.
- تعریف متغیرها و ثابت های سراسری
- تعریف توابع
- عملوندها و انتسابها
- کامنتها و بلاکهای اسناد
- پیشوند و پسوندهای کلاس
- بهترین شیوهها
- این مطلب از سری مطال