دستورزبان توصیهشدهی PHP
توی این پست میخوایم درمورد روشهای استاندارد کدنویسی که بهتره توی کدنویسی رعایت کنید صحبت کنیم. البته این روشها فقط درصورتیکه بخواین توی توسعهی کدایگنایتر مشارکت داشته باشین، الزامی هستن.
قالب فایل
فایلها باید با کدگذاری یونیکد (UTF-8) ذخیره بشن. BOM «نباید» استفاده بشه. برخلاف UTF-16 و UTF-32، هیچ کارکتر Byte Order خاصی برای مشخصکردن فایل UTF-8 نیاز نیست و BOM میتونه یه تأثیر منفی روی ارسال خروجی PHP داشته باشه که باعث میشه برنامه نتونه هدرهای خودش رو تنظیم کنه. همچنین باید از کارکتر پایان خطوط Unix استفاده کنید (LF). در اینجا نحوهی انجام اینکار رو در دو مورد از ادیتورهای معروف بیان میکنیم. روش انجام کار توی ادیتور شما ممکنه متفاوت باشه و باید به مستنداتش مراجعه کنید.
TextMate
- تنظیمات برنامه رو باز کنین
- روی گزینهی Advanced کلیک و سربرگ Saving رو باز کنین
- توی قسمت File Encoding گزینهی UTF-8 (recommended) رو انتخاب کنین
- توی قسمت Line Endings گزینهی LF (recommended) رو انتخاب کنین
- اختیاری: گزینهی Use for existing files as well رو هم انتخاب کنین اگه میخواین کارکترهای انتهای خطوط توی فایلهایی که باز کردین هم با تنظیمات جدید اصلاح بشه
BBEdit
- تنظیمات برنامه رو باز کنین
- از قسمت سمت چپ Text Encoding رو انتخاب کنین
- در قسمت Default text encoding for new documents گزینهی Unicode (UTF-8, no BOM) رو انتخاب کنین
- اختیاری: در قسمت If file's encoding can't be guessed, use گزینهی Unicode (UTF-8, no BOM) رو انتخاب کنین
- از قسمت سمت چپ Text Files رو انتخاب کنین
- در قسمت Default line breaks گزینهی Mac OS X and Unix (LF) رو انتخاب کنین
بستن تگ PHP
بستن تگ PHP ازنظر مفسر PHP اختیاریه. هرچند اگه استفاده بشه، هر کارکتر فضای سفید (مثل Space یا Tab یا Enter و...) که بعدش توسط توسعهدهنده، کاربر، برنامهی ویرایشگر یا FTP تولید شده باشه، ممکنه خروجی نامناسبی ایجاد کنه که موردنظر شما نباشه یا حتی باعث بروز خطای PHP در تغییر هدرها، یا ایجاد صفحات خالی و... بشه. برای جلوگیری از این مشکل، تمام فایلهای PHP باید بدون تگ بستن PHP در انتهای خودشون باشن و انتهای این فایلها باید یک تگ باز PHP وجود داشته باشه که آخرین خطش، یک خط خالیه.
نامگذاری فایلها
اسامی کلاسها باید با ساختار Ucfirst باشن (یعنی حرف اول با حروف بزرگ نوشته بشه) درحالیکه هر فایل دیگری (تنظیمات، ویوها، اسکریپتهای عمومی و...) باید تماماً با حروف کوچک نوشته بشن.
این مثالها اشتباه هستن:
1 2 3 4 5 6 7 8 | somelibrary.php
someLibrary.php
SOMELIBRARY.php
Some_Library.php
Application_config.php
Application_Config.php
applicationConfig.php
|
اما این اسامی درست هستن:
1 2 3 4 5 | Somelibrary.php
Some_library.php
applicationconfig.php
application_config.php
|
بعلاوه، فایلهای حاوی کلاسها باید با اسم خود کلاس مطابقت داشته باشن. برای مثال اگه کلاسی بهاسم Myclass دارین، فایلش هم باید Myclass.php باشه.
نامگذاری کلاسها و متدها
اسم کلاسها همیشه باید با یک حرف بزرگ شروع بشه و اسامی چندکلمهای باید با خطزیر جدا بشن نه اینکه بصورت CamelCased نوشته بشه. مثال:
1 2 3 4 5 6 7 8 9 10 11 | class superclass
class SuperClass
class Super_class
class Super_class
{
public function __construct()
{
}
}
|
اسامی متدها باید تماماً با حروف کوچک نوشته بشه و اسمشون باید بهوضوع کارکردشون رو نشون بده و ترجیحاً بصورت فعل باشه. سعی کنید از اسامی خیلی طولانی خودداری کنید. اسامی چندکلمهای باید با خطزیر از هم جدا بشن:
1 2 3 4 5 6 7 | function fileproperties()
function fileProperties()
function getfileproperties()
function getFileProperties()
function get_the_file_properties_from_the_file()
function get_file_properties()
|
اسامی متغیرها
قواعد نامگذاری متغیرها خیلی شبیه اسامی نامگذاری متدهای کلاسه. متغیرها باید فقط از حروف کوچک استفاده کرده باشن و کلماتشون با خطزیر از هم جدا بشه و اسمشون هم مفهوم و کاربردشون و محتواشون رو منتقل کنه. اسامی خیلی کوتاه و غیر کلمهای فقط باید بعنوان متغیرهای حلقه بکار برن. مثال:
1 2 3 4 5 6 7 8 9 10 11 | $j = 'foo' ;
$Str
$bufferedText
$groupid
$name_of_last_city_used
for ( $j = 0; $j < 10; $j ++)
$str
$buffer
$group_id
$last_city
|
توضیحات
بطور کلی کد باید بطور گسترده حاوی توضیحات باشه. اینکار نهتنها کمک میکنه چرخهی کاری و هدف کدها برای برنامهنویسان کمتجربهتر توضیح داده بشه، بلکه میتونه وقتی چند ماه بعد به سراغ کدتون میاین تا تغییراتی داخلش ایجاد کنید، ارزش غیرقابلتوصیفی داشته باشه. قالب خاصی برای توضیحات بعنوان اجبار وجود نداره، ولی این ساختار پیشنهاد میشه:
توضیحات بهسبک
DocBlock قبلاز کلاسها، متدها و متغیرها میتونه توسط IDEها شناسایی بشه و توی پنجرهی AutoComplete اونها به نمایش در بیاد:
1 2 3 4 5 6 7 | function xml_encode( $str )
|
از توضیحات تکخطی در داخل کد استفاده کنین و یک خط خالی بین توضیحات طولانی و کدتون قرار بدین:
1 2 3 4 5 6 7 8 9 10 11 12 | $parts = explode ( "n" , $str );
$parts = $this ->foo( $parts );
|
ثابتها
ثابتها از ساختاری مشابه متغیرها پیروی میکنن، بجز اینکه ثابتها باید همیشه تماماً با حروف بزرگ نوشته بشن. همیشه از ثابتهای داخلی کدایگنایتر (مثل SLASH و LD و RD و PATH_CACHE و...) در زمانهای موردنیاز استفاده کنید. مثال:
1 2 3 4 5 6 7 8 9 | myConstant
N
S_C_VER
$str = str_replace ( '{$foo}' , 'bar' , $str );
MY_CONSTANT
NEWLINE
SUPER_CLASS_VERSION
$str = str_replace (LD. 'foo' .RD, 'bar' , $str );
|
TRUE و FALSE و NULL
این مقادیر باید همیشه با حروف بزرگ نوشته بشن. مثال:
1 2 3 4 5 6 7 8 9 | if ( $foo == true)
$bar = false;
function foo( $bar = null)
if ( $foo == TRUE)
$bar = FALSE;
function foo( $bar = NULL)
|
عملگرهای منطقی
استفاده از علمگر یا بصورت || مناسب نیست چون وضوحش در برخی دستگاههای خروجی پایینه (برای مثال شبیه 11 بنظر میرسه). استفاده از && نسبتبه AND ترجیح داده میشه ولی هردو قابلقبول هستن و ضمناً قبل و بعد از ! باید فاصله گذاشته بشه. مثال:
1 2 3 4 5 6 7 8 9 10 11 | if ( $foo || $bar )
if ( $foo AND $bar )
if (! $foo )
if (! is_array ( $foo ))
if ( $foo OR $bar )
if ( $foo && $bar )
if ( ! $foo )
if ( ! is_array ( $foo ))
|
مقایسهی مقادیر بازگشتی و تبدیل نوع
برخی از توابع PHP درصورت عدم موفقیت، خروجی FALSE تولید میکنن ولی ممکنه که خروجی معتبری هم با مقدار 0 یا رشتهی خالی داشته باشن که میتونه بعنوان FALSE هم در مقایسههای معمولی که نوع رو بررسی نمیکنن، ارزیابی بشه. در چنین مقایسههایی، صراحتاً مشخصکنین که دنبال چی هستین. موقع بررسی مقادیر بازگشتی و چککردن متغیرهای معمولی خودتون، سختگیری کنین و از === یا ==! استفاده کنین. مثال:
1 2 3 4 5 6 | if ( strpos ( $str , 'foo' ) == FALSE)
if ( strpos ( $str , 'foo' ) === FALSE)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | function build_string( $str = "" )
{
if ( $str == "" )
{
}
}
function build_string( $str = "" )
{
if ( $str === "" )
{
}
}
|
همچنین اطلاعات
تبدیل نوع رو هم مطالعه کنین که میتونن مفید باشن. تبدیل نوع، میتونه تأثیر نسبتاً متفاوتی با اونچه که قابل انتظاره داشته باشه. وقتی یه متغیر رو بصورت رشته تبدیل میکنین، برای مثال NULL و FALSE تبدیل به رشتهی خالی میشن و 0 (یا سایر اعداد) بصورت رشتهای از ارقام در میان و TRUE هم به رشتهی "1" تبدیل میشه:
کدهای اشکالزدایی
هیچوقت کدهای اشکالزدایی رو توی ارسال نهایی روی سرور رها نکنید، حتی اگه بصورت کامنت (توضیحات) قرار گرفته باشن. مواردی مثل
var_dump() یا
print_r() یا دستورات
die() و
exit() نباید توی کد شما قرار گرفته باشن، مگه اینکه هدفی بجز اشکالزدایی داشته باشن.
فاصلههای خالی در فایلها
هیچ فاصلهی خالی نباید قبلاز بازشدن تگ PHP یا بعد از بستن تگ PHP قرار گرفته باشه. خروجی در بافر قرار میگیره، بنابراین فواصل خالی توی فایل شما ممکنه باعث بشن خروجی قبلاز اینکه کدایگنایتر ارسال خروجی خودش رو شروع کنه، برای مرورگر کاربر ارسال بشه و درنتیجه باعث بروز خطا بشه و کدایگنایتر نتونه هدرهای خودش رو تنظیم کنه.
سازگاری
کدایگنایتر پیشنهاد میکنه از PHP5.6 یا بالاتر استفاده کنین ولی میتونه با PHP5.3.7 هم سازگار باشه. کدتون باید با این نیازمندیها سازگاری داشته باشه و اگه از نسخههای قدیمی استفاده بشه، جایگزین مناسب براش نوشته باشین یا اینکه قابلیت خاصی باشه که به آرامی درصورت عدم سازگاری، غیرفعال بشه بدون اینکه به برنامهی نهایی آسیبی بزنه.
بعلاوه، از توابع داخلی PHP که نیاز به نصب کتابخانههای غیر پیشفرض دارن استفاده نکنین، مگه اینکه کدتون شامل روش جایگزین برای مواقعی که اون کتابخانهها موجود نیست، باشه.
یک فایل بهازای هر کلاس
از فایلهای جداگانه برای هر کلاس استفاده کنین، مگه اینکه کلاسها بهشدت بههم وابسته باشن. یکی از مثالهایی که یک فایل CodeIgniter شامل چند کلاس هست، فایل کتابخانهی Xmlrpc هست.
فضاهای خالی
از Tab برای فاصلههای خالی توی کد استفاده کنید نه Space. اینکار ممکنه بنظر کوچک بیاد ولی استفاده از Tab بجای فاصلههای خالی باعث میشه که توسعهدهندگانی که به کد شما نگاه میکنن، بتونن هرجور دوست دارن توی ویرایشگرشون نمایش محتوا رو سفارشیسازی کنن. ازطرف دیگه، حجم فایل هم (کمی) کاهش پیدا میکنه. ذخیرهسازی یک کارکتر Tab بجای چهار کارکتر Space، فضای کمتری اشغال میکنه.
شکستن خطوط
فایلهای باید با کارکترهای انتهای خطوط Unix ذخیره بشن. اینکار بیشتر برای کسانی که با Windows کار میکنن ممکنه مشکل باشه، ولی درهرحال مطمئن بشین که ویرایشگر متنی شما برای ذخیرهی فایلها با کارکترهای انتهای خط Unix تنظیم شده.
تورفتگی کد
از روش تورفتگی Allman استفاده کنید. در این روش، بجز تعریف کلاسها، در بقیهی موارد آکولادها همیشه در یک خط جداگانه قرار میگیرن و ازنظر تورفتگی، همسطح با دستور والد خودشون خواهند بود. مثال:
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 | function foo( $bar ) {
}
foreach ( $arr as $key => $val ) {
}
if ( $foo == $bar ) {
} else {
}
for ( $i = 0; $i < 10; $i ++)
{
for ( $j = 0; $j < 10; $j ++)
{
}
}
try {
}
catch () {
}
|
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 | function foo( $bar )
{
}
foreach ( $arr as $key => $val )
{
}
if ( $foo == $bar )
{
}
else
{
}
for ( $i = 0; $i < 10; $i ++)
{
for ( $j = 0; $j < 10; $j ++)
{
}
}
try
{
}
catch ()
{
}
|
فاصلههای کروشهها و پرانتزها
بطور کلی، پرانتزها و کروشهها نباید حاوی هیچ فاصلهی اضافهای باشن. تنها استثنا، وجود یک فاصله در جاهایی هست که یک ساختار کنترلی PHP آرگومانهای خودش رو توی پرانتز دریافت میکنه (declare و do-while و elseif و for و foreach و if و switch و while) تا کمک کنه با توابع و متدها اشتباه گرفته نشن و خوانایی افزایش پیدا کنه:
1 2 3 4 5 | $arr [ $foo ] = 'foo' ;
$arr [ $foo ] = 'foo' ;
|
1 2 3 4 5 6 7 8 9 10 11 | function foo ( $bar )
{
}
function foo( $bar )
{
}
|
1 2 3 4 5 | foreach ( $query ->result() as $row )
foreach ( $query ->result() as $row )
|
متن بومیسازیشده
کتابخانههای کدایگنایتر میتونن از مزایای فایلهای زبان مناسب در زمان امکان استفاده کنن. برای مثال:
1 2 3 4 5 | return "Invalid Selection" ;
return $this ->lang->line( 'invalid_selection' );
|
متدها و متغیرهای خصوصی
متدها و متغیرهایی که فقط بصورت داخلی مورد استفاده قرار میگیرن (مثل توابع کمکی و سودمندی که متدهای عمومی شما برای خلاصهسازی کد ازشون کمک میگیرن)، باید با کارکتر خطزیر شروع بشن. مثال:
1 2 | public function convert_text()
private function _convert_text()
|
خطاهای PHP
کد شما باید بدون خطا اجرا بشه و وابسته به پنهانکردن هشدارها و یادآوریها نباشه. برای مثال، هیچوقت متغیری رو که خودتون تعریف نکردین، مستقیماً مورد دسترسی قرار ندین (مثل کلیدهای آرایهی
$_POST) مگه اینکه قبلش وجود اونها رو با
isset() بررسی کرده باشین.
مطمئن بشین که محیط توسعهی شما گزارش خطا رو برای تمام کاربران فعال کرده و نمایش خطاها هم توی محیط PHP فعاله. میتونین این موضوع رو با چنین کدی بررسی کنین:
1 2 3 4 | if ( ini_get ( 'display_errors' ) == 1)
{
exit "Enabled" ;
}
|
دربرخی از سرورها display_errors غیرفعاله و شما هم دسترسی به php.ini ندارین. در اغلب مواقع مشابه این وضعیت، میتونین با دستور زیر نمایش خطاها رو فعال کنین:
1 | ini_set ( 'display_errors' , 1);
|
نقل قول:نکته: تنظیمکردن display_errors با دستور ini_set در زمان اجرا، مشابه فعالکردنش ازطریق تنظیمات PHP نیست. برای مثال، هیچ تأثیری روی اسکریپتی که خطاهای مرگبار (Fatal Errors) داشته باشه، نداره.
تگهای کوتاه بازکردن
همیشه در مواقعی که یک سرور خاص، short_open_tags رو فعال نکرده باشه، از تگ کامل PHP برای بازکردن استفاده کنین. برای مثال:
1 2 3 4 5 6 | <? echo $foo ; ?>
<?= $foo ?>
<?php echo $foo ; ?>
|
نقل قول:نکته: از نسخهی PHP5.4 بهبعد، همیشه شکل خلاصهشدهی echo قابل استفاده است.
یک دستور در هر خط
هیچوقت چند دستور رو در یک خط ادغام نکنید:
1 2 3 4 5 6 7 | $foo = 'this' ; $bar = 'that' ; $bat = str_replace ( $foo , $bar , $bag );
$foo = 'this' ;
$bar = 'that' ;
$bat = str_replace ( $foo , $bar , $bag );
|
رشتهها
همیشه رشتهها رو داخل کوتیشن تک بگذارین، مگه اینکه نیاز به پردازش متغیرها داشته باشین و در چنین شرایطی، متغیرها رو داخل آکولاد قرار بدین تا جلوی تفسیر حریصانهی متغیرها گرفته بشه. همچنین درصورتیکه توی رشته از کارکتر کوتیشن تک استفاده شده باشه، ممکنه که بخواین از کوتیشن جفت برای محصورکردن کل رشته استفاده کنین تا نخواین کوتیشن تک رو مدام خنثیسازی کنین. مثال:
1 2 3 4 5 6 7 8 9 | "My String"
"My string $foo"
'SELECT foo FROM bar WHERE baz = ' bag ''
'My String'
"My string {$foo}"
"SELECT foo FROM bar WHERE baz = 'bag'"
|
پرسوجوهای SQL
کلمات کلیدی SQL رو همیشه با حروف بزرگ بنویسین: SELECT و INSERT و UPDATE و WHERE و AS و JOIN و ON و IN و...
کوئریهای طولانی رو به چند خط بشکنین تا خواناتر بشه. ترجیحاً این شکستگی رو در بین بخشهای کوئری انجام بدین. مثال:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | $query = $this ->db->query("select foo, bar, baz, foofoo, foobar as raboof, foobaz from exp_pre_email_addresses
...where foo != 'oof' and baz != 'zab' order by foobaz limit 5, 100");
$query = $this ->db->query("
SELECT foo, bar, baz, foofoo, foobar AS raboof, foobaz
FROM exp_pre_email_addresses
WHERE
(
foo != 'oof'
AND baz != 'zab'
)
ORDER BY foobaz
LIMIT 5, 100
");
|
آرگومانهای پیشفرض توابع
هر زمان که امکان داشت، برای توابع خودتون مقادیر پیشفرض تعریف کنین. اینکار جلوی بسیاری از خطاهای PHP رو که بخاطر فراخوانیهای اشتباه و بدون مقدارهای مناسب توسط کاربر اتفاق میفته میگیره و باعث میشه کدتون هم برای کارکردن با مقادیر پیشفرض، کوتاهتر بشه. برای مثال:
1 | function foo( $bar = '' , $baz = FALSE)
|