برنامه نویسی شیء گرا PHP – ضمیمه 2: متد ها و خصوصیات استاتیک (static)

درسنامه درس 12 از سری شی گرایی در PHP
php-oop-static-method-and-properties

با سلام، این مقاله، مقاله ی دوم از ضمیمه های برنامه نویسی شیء گرا PHP است. در این قسمت می خواهیم با متدها و خصوصیات استاتیک (static) آشنا شویم.

متدها و خصوصیات استاتیک چه هستند؟

در بعضی از موارد خاص می میخواهیم بدون ساختن یک شی از یک کلاس به خصوصیات و متدهای آن دسترسی داشته باشیم. در چنین حالتی می توانیم متدها و خصوصیات آن کلاس را به صورت استاتیک تعریف کنیم.

باید ذکر کنیم که از نظر کد نویسی استفاده از متدها و خصوصیات استاتیک پیشنهاد نمی شود و عادت بدی است اما در بعضی از موارد خاص توجیه پذیر است.

تا به حال با سه عدد از access modifier ها آشنا شده اید: Public و Private و Protected؛ کلید واژه ی Static چهارمین access modifier می باشد.

چطور از متدها و خصوصیات استاتیک استفاده کنیم؟

برای تعیین یک خصوصیت یا متد به عنوان متد یا خصوصیتِ استاتیک باید از کلید واژه ی static استفاده کنید:

class Utilis {
  // static methods and properties are defined with the static keyword.
  static public $numCars = 0;
}

برای استفاده از این متدها و خصوصیات از اپراتور scope resolution (::) استفاده می کنیم. در جلسات قبل در مورد این اپراتور صحبت کردیم. این اپراتور که علامتش دو جفت دو نقطه می باشد، به شما اجازه می دهد به متدها و خصوصیات استاتیک (static) و ثابت (constant) و همینطور به متدها و خصوصیات override شده دسترسی پیدا کنید. مطالعه ی بیشتر در مورد این اپراتور در این لینک.

در مثال زیر، برای کار با خصوصیت استاتیکِ numCars$ از این اپراتور استفاده می کنیم:

// تعیین کردن تعداد ماشین ها
Utilis::$numCars = 3;
 
// دریافت تعداد ماشین ها
echo Utilis::$numCars;

نتیجه ی این کد عدد 3 خواهد بود.

نکته: دقت کنید که بعد از این اپراتور از علامت $ استفاده کرده ایم! این ساختار را از یاد نبرید.

اگر یادتان باشد ما از کلید واژه ی this$ استفاده می کردیم تا به متدها و خصوصیات یک کلاس، در درونِ خودش اشاره کنیم. حال برای اشاره به متدها و خصوصیات استاتیک از کلید واژه ی self استفاده می کنیم.

در مثال زیر تابعی به نام ()addToNumCars (به معنی "بر تعداد ماشین ها اضافه کن") داریم. کار این تابع این است که ابتدا تعداد ماشین ها را در درون خود کلاس از خصوصیت استاتیک numCars$ بگیرد، آن هم با استفاده از کلید واژه ی self:

class Utilis {
  static public $numCars = 0;
 
  static public function addToNumCars($int)
  {
    $int = (int)$int;
    self::$numCars += $int;
  }
}

حالا از کدی که قبلا نوشته بودیم کمک میگیریم و تعداد ماشین ها را تعیین کرده و دوباره میگیریم:

echo Utilis::$numCars;
 
Utilis::addToNumCars(3);
echo Utilis::$numCars;
 
Utilis::addToNumCars(-1);
echo Utilis::$numCars;

خروجی این کد به ترتیب عدد های 0 و 3 و 2 خواند بود.

چه زمانی از این متدها و خصوصیات استاتیک استفاده کنیم؟

دلیل اصلی استفاده از این متدها و خصوصیات، نیاز به شمارنده ها (counter) و کلاس های ابزاری (utility classes) است. در واقع همانطور که گفتیم استفاده از متدها و خصوصیات استاتیک توصیه شده نیست اما برخی اوقات ممکن است نیاز پیدا کنید که از یک متد یا خصوصیت بدون ساختن هیچ شیء ای استفاده کنید. حتما سوال میپرسید که شمارنده ها و کلاس های ابزاری (نام دیگرشان کلاس های کمکی (Helper) است) چه هستند...

مثال از counters (شمارنده ها)

شمارنده ها می توانند آخرین مقداری که به آن ها داده شده را ذخیره نگه دارند. به طور مثال متد ()add1ToCars هر بار که صدا زده شود یک واحد به خصوصیت  numberOfCars$ اضافه می کند:

class Utilis {
  // تعداد ماشین ها را ذخیره نگه می دارد
  static public $numberOfCars = 0;
 
  // هر بار که متد صدا زده شود یک واحد به تعداد ماشین ها اضافه کن
  static public function add1ToCars()
  {
    self::$numberOfCars++;
  }
}
 
echo Utilis::$numberOfCars;
 
Utilis::add1ToCars();
echo Utilis::$numberOfCars;
 
Utilis::add1ToCars();
echo Utilis::$numberOfCars;
 
Utilis::add1ToCars();
echo Utilis::$numberOfCars;

خروجی کد ما به ترتیب به صورت 0 و 1 و 2 و 3 خواهد بود.

مثال از utility classes (کلاس های ابزاری)

استفاده از متدهای استاتیک برای utility class ها بسیار شایع است. تنها فلسفه ی وجودی utility class ها، ارائه ی خدمات به کلاس های اصلی است (برای همین نامشان کلاس های ابزاری یا کمکی است).

utility class ها می توانند انواع وظایف مختلف را انجام دهند که از جمله ی آن ها می توان این موارد را نام برد: تبدیل واحد های اندازه گیری به هم (مانند پوند به کیلوگرم و ...)، کد گذاری (encryption)، پاک سازی داده های ورودی (sanitation) و هر چیز دیگری که به غیر از خدمتی به کلاس های اصلی هدفی در برنامه ما ندارد.

مثال زیر متد استاتیکی با نام redirect است که کاربر را به URL ای که ما تعیین کنیم redirect می کند:

class Utilis {
  //(ها Header این متد کاربر را به صفحه ی جدیدی انتقال می دهد (با استفاده از 
  static public function redirect($url)
  {
    header("Location: $url");
    exit;
  }
}

حالا برای استفاده از متد ()redirect تنها کافیست که آن را از کلاس Utilis صدا بزنیم، بدون اینکه نیاز باشد شیء ای برایش بسازیم.

Utilis::redirect("https://www.roxo.ir/plus");

چرا باید در مورد استفاده از static احتیاط کنیم؟

هر زمان که خواستید از متدها یا خصوصیات استاتیک استفاده کنید، اطمینان حاصل کنید که هدف شما استفاده برای utility class ها است و هیچ وقت برای راحتی کار از آن ها استفاده نکنید چرا که استفاده از static بدی های زیر را دارد:

  • انجام تست های اتوماتیک (automated testing) روی کلاس هایی که از متدهای static استفاده می کنند بسیار سخت خواهد شد.
  • متدها و خصوصیات global هایی به کد می دهند که از هر جایی قابل دسترسی است! و ما به عنوان برنامه نویس باید تا می توانیم از چنین مواردی دوری کنیم چرا که یک ریسک بالقوه امنیتی به حساب می آیند.

مخلص کلام: استفاده از static فقط برای کلاس های ابزاری باشد، نه از زیر کار در رفتن و راحتی شما!

امیدوارم از این قسمت استفاده ی کافی را برده باشید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری شی گرایی در PHP توصیه می‌کند:
نویسنده شوید

دیدگاه‌های شما (1 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

شهریار
02 شهریور 1398
سلام خسته نباشید و سپاس از آموزش های عالی مورد استفاده از استاتیک ها اینطور که شما میگین هست پس چرا لاراول فساد و ارائه داده که باعث میشه به همه امکانات بصورت استاتیک دسترسی داشته باشیم؟ ای مورد مشکل امنیتی بوجود نمیاره؟

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

امیر زوارمی
07 شهریور 1398
سلام دوست عزیز استفاده از static به خودی خود بد نیست بلکه زمان و موقع داره. لاراول یک فریم ورک بزرگ هست و به دلایل مختلفی از facade استفاده میکنه (مثلا راحتی در استفاده از کلاس بدون import کردن اون و ....) و خودشون در پشت صحنه تمامی موارد امنیتی و ... رو چک میکنن. در واقع تیم توسعه ی لاراول میدونن که کجا از چی استفاده کنن و چه مواردی ممکنه باعث مشکلات امنیتی بشه. بنابراین تا زمانی که documentation رسمی رو دنبال کنید هیچ مشکلی براتون پیش نمیاد. البته باید بگم که هنوز هم بعضی از توسعه دهنده ها اعتقاد دارن که در برنامه نویسی دقیق OOP نباید از کلاس های استاتیک استفاده بشه (مگر اینکه واقعا لازم باشه). اونها میگن حتی اگر از فریم ورک ها استفاده میکنید بهتره به صورت دستی فایل ها رو import کنید تا نیازی به استفاده از متد های استاتیک و ... نباشه. این دعوا از اون دعواهایی هست که واقعا مهم نیست. یک مقاله ی خوب در مورد اینکه چه زمانی از static استفاده کنیم: http://verraes.net/2014/06/when-to-use-static-methods-in-php/

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.