40 نکته مهم در PHP 1


روش های بهینه جهت افزایش کارایی اپلیکیشن

1. بهتر است از آدرس دهی Relative یا نسبی پرهیز کنید. توصیه می شود بجای آن یک ثابت تعریف کنید که آدرس کامل/مطلق ROOT سایت شما را بیان می کند:

خیلی وقت ها شده که کدهایی نظیر زیر را مشاهده کرده اید:

require_once('../../lib/some_class.php');

این روش کاستی های بسیاری دارد که در زیر شرح داده می شود:

این تابع ابتدا پوشه هایی را که در include path فایل تنظیمات php تعریف شده اند را جستجو می کند، سپس از پوشه ی جاری جستجو را ادامه می دهد. به همین جهت بسیاری از پوشه ها مورد جستجو قرار می گیرند. زمانی که یک اسکریپت در پوشه ای دیگر، اسکریپت دیگری را دربرمی گیرد، آنگاه اسم پوشه ی پایه (base directory) اسکریپت دوم به اسکیرپت دربرگیرنده (اسکریپت اول) تغییر می یابد.

مسئله ی دیگر که باید به آن اشاره شود این است که زمانی که یک اسکرپیت توسط ابزار cron اجرا می شود، ممکن است پوشه ی والد یا میزبان خود را به عنوان پوشه ی فعال جاری (working directory) نداشته باشد.

از این جهت توصیه می کنیم همیشه path را به صورت کامل و absolute اعلان نمایید:

define('ROOT' , '/var/www/project/');  require_once(ROOT . '../../lib/some_class.php');  //rest of the code  

حال این path یک آدرس کامل و absolute هست که همیشه ثابت باقی می ماند. اما دستور فوق هنوز جای بهتر شدن دارد. دایرکتوری /var/www/project می تواند تغییر کند. آیا هر بار آن را تغییر می دهیم؟ خیر، بلکه با استفاده از magic constant ها (نظیر __FILE__) به این ثوابت قابلیت حمل (portable) را اعطا می کنیم (ثوابتی که با توجه به بستر جاری خود تغییر می کنند را magic constant گویند). به نمونه ی زیر دقت کنید:

//suppose your script is /var/www/project/index.php  //Then __FILE__ will always have that full path.  define('ROOT' , pathinfo(__FILE__, PATHINFO_DIRNAME));  require_once(ROOT . '../../lib/some_class.php');  //rest of the code  

حال زمانی که پروژه ی خود را به پوشه ی دیگری انتقال دهید، برای مثال آن را به سرور آنلاین جابجا کنید، همان کد بدون هیچ گونه تغییری اجرا می شود.

2. از require، include، require_once یا include_once استفاده نکنید:

اسکریپت شما می تواند فایل های مختلفی در بالای سلسله مراتب فایل ها داشته باشد. برای مثال ممکن است class library، فایل هایی حاوی ابزار و توابع کمکی (utility function) نظیر ذیل در ابتدای ساختار سلسله مراتبی خود داشته باشد:

require_once('lib/Database.php');  require_once('lib/Mail.php');  require_once('helpers/utitlity_functions.php');  

روش فوق کمی ابتدایی و ناکارامد است. این کد را می توان به صورت منعطف و کاراتر تنظیم کرد. می توانید تعدادی تابع کمکی تعریف کرده و با استفاده از آن ها (helper function) آسان تر به ابزار مورد نیاز دسترسی پیدا نموده و آن ها را پروژه بارگذاری نمایید:

function load_class($class_name)  {      //path to the class file      $path = ROOT . '/lib/' . $class_name . '.php');      require_once( $path );   }  load_class('Database');  load_class('Mail');  

کد حاضر قطعا بهتر از نمونه ی قبلی عمل می کند. هر چند می توانید به روش زیر آن را بهتر نمایید:

                              function load_class($class_name)  {      //path to the class file      $path = ROOT . ‘/lib/’ . $class_name . ‘.php’);      if(file_exists($path))      {          require_once( $path );       }  }  

اکنون با قطعه کد بهینه سازی شده ی زیر می توان کارهای مختلفی انجام داد:

  • چندین فایل را جهت دستیابی به class file مورد نظر (یکسان) جستجو کرد.
  • پوشه ی دربردارنده ی class file ها را بدون اینکه کد دچار مشکل شود (بدون شکستن کد)، تغییر داد.
  • از توابع یکسان برای بارگذاری فایل هایی که دربردارنده ی توابع کمکی، محتوای html و غیره … هستند، استفاده کرد.

3. نگهداشت محیط خطایابی و اشکال زدایی (debug environment) در اپلیکیشن:

در طول توسعه ی اپلیکیشن پیغام کوئری های دیتابیس را با دستور echo چاپ می کنیم، متغیرهای مشکل زا را با تابع dump اشکال زدایی نموده (اطلاعاتی نظیر نوع و مقدار متغیر نمایش می دهد) و سپس زمانی که خطا برطرف شد، آن ها را به صورت comment در می آوریم یا به طور کلی از برنامه پاک می کنیم. اما توصیه می شود که بگذارید همه چیز به شکل خود باقی بماند و در دراز مدت پروژه را تعمیر و نگهداری نمایید.

در دستگاهی که پروژه ی سایت (development machine) را می نویسید، می توانید به این صورت اقدام نمایید:

define('ENVIRONMENT' , 'development');  if(! $db->query( $query )  {      if(ENVIRONMENT == 'development')      {          echo "$query failed";      }      else      {          echo "Database error. Please contact administrator";      }      }  

در سمت سرویس دهنده (server) نیز می توانید کد زیر را بنویسید:

define('ENVIRONMENT' , 'production');  if(! $db->query( $query )  {      if(ENVIRONMENT == 'development')      {          echo "$query failed";      }      else      {          echo "Database error. Please contact administrator";      }      }  

4. منتشر کردن پیغام های مربوط به اطلاعات وضعیت (status message) با استفاده از (متغیر) session

Status message آن دسته از پیغام هایی هستند که پس از انجام یک task یا عملیات خاص تولید شده و اطلاعاتی در خصوص عملیات انجام شده ارائه می دهند.

        
...

کدهایی مانند نمونه ی فوق رایج هستند. استفاده از متغیر برای ذخیره و نمایش status message ها چندان کارا نبوده و محدودیت های خود را دارد. در واقع امکان ارسال متغیر از طریق redirect (زمانی که کاربر را به صفحه دیگری هدایت می کنید) وجود ندارد (مگر اینکه آن ها را از طریق متغیرهای GET به اسکریپت بعدی پاس دهید (propagate) که روشی ناکارامد تلقی می شود). در اسکریپت های بزرگ ممکن است چندین پیغام تولید شود.

بهترین روش برای انتشار (propagate) پیغام ها، خواه بین صفحات مختلف و خواه داخل صفحه جاری، استفاده از متغیر session می باشد. برای این منظور لازم است در هر صفحه یک تابع session_start وجود داشته باشد.

function set_flash($msg)  {      $_SESSION['message'] = $msg;  }  function get_flash()  {      $msg = $_SESSION['message'];      unset($_SESSION['message']);      return $msg;  }  

در اسکریپت php شما:

      Status is :   
...

5. تعریف توابع انعطاف پذیر:

function add_to_cart($item_id , $qty)  {      $_SESSION['cart'][$item_id] = $qty;  }  add_to_cart( 'IPHONE3' , 2 );  

به هنگام افزودن یک آیتم جدید، از تابع فوق استفاده می کنید. حال اگر لازم باشد چندین آیتم را اضافه نمایید، آیا تابع دیگری تعریف می کنید؟ خیر، بلکه تابع را از همان اول طوری تعریف می کنید که قادر باشد پارامترهای مختلف را به عنوان ورودی قبول کند. به کد زیر دقت نمایید:

function add_to_cart($item_id , $qty)  {      if(!is_array($item_id))      {          $_SESSION['cart'][$item_id] = $qty;      }      else      {          foreach($item_id as $i_id => $qty)          {              $_SESSION['cart'][$i_id] = $qty;          }      }  }  add_to_cart( 'IPHONE3' , 2 );  add_to_cart( array('IPHONE3' => 2 , 'IPAD' => 5) );   

اکنون تابع قادر است چندین ورودی متفاوت را دریافت کند. با پیاده سازی روش فوق می توانید کد خود را بسیار سریع و کارا (agile) نمایید.

6. چنانچه تگ بسته ی php آخرین آیتم در اسکریپت جاری می باشد، آن را حذف کنید:

این نکته ی بسیاری مهمی است که در بسیاری از پست های آموزش PHP لحاظ نمی شود.

  

با این کار بسیاری از مشکلات اپلیکیشن شما برطرف می شود. به مثال زیر دقت کنید:

class file super_class.php:

  //super extra character after the closing tag  

حال توجه خود را به کد index.php جلب نمایید:

require_once('super_class.php');  //echo an image or pdf , or set the cookies or session data  

با این خطا مواجه می شوید: Headers already sent. چرا؟ به این خاطر که رشته ی “super extra character” قبلا چاپ (echo) شده و تمامی header ها همراه با آن ارسال شده اند. حال فرایند خطایابی و اشکال زدایی را آغاز می کنید. ممکن است ساعت ها طول بکشد تا super extra space را پیدا کنید.

توصیه می شود همیشه تگ بسته ی php را حذف نمایید:

  

همان طور که می بینید تگ بسته در کد فوق حذف شده و به همین دلیل خطای نام برده دیگر رخ نمی دهد.

7. تمامی خروجی ها را در یک مکان واحد جمع کرده و سپس آن ها را یکجا به مرورگر ارسال کنید:

این تکنیک در اصطلاح output buffering یا ذخیره خروجی ها در حافظه ی میانی خوانده می شود. فرض کنید که محتوای مورد نظر را از توابع مختلف همچون ذیل به مرورگر (با تابع echo) ارسال می کنید:

function print_header()  {      echo "

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *