یادآوری از OOP (بخش سوم)

27 شهریور 1398
پروژه ساخت شبکه ی اجتماعی: یادآوری از OOP (بخش سوم)

کار با Setter و Getter در PHP

در جلسه ی قبل در رابطه با constructor و deconstructor ها صحبت کردیم و مثالی را هم از آن ها حل کردیم. این جلسه می خواهیم در مورد سه مفهوم صحبت کنیم: Access Modifier ها و Setter ها و Getter ها در PHP.

برای این جلسه فایلی جدید به نام 2_5 با پسوند php می‌ سازیم. در مورد Access Modifier ها باید بدانید:

  • متدها یا خصوصیات public توسط همه (خارج از کلاس نیز) قابل دسترسی هستند.
  • متدها یا خصوصیات private تنها از داخل خودِ کلاس قابل دسترسی هستند.
  • متدها یا خصوصیات protected تنها توسط فرزن ها یا از داخل خود کلاس قابل دسترسی هستند.

جهت اطلاعات بیشتر به دوره ی آموزش برنامه نویسی شیء گرا مراجعه کنید.

برای شروع کار مانند قبل کلاس user را می نویسیم:

class User {
    private $name;
    private $age;

    public function __construct($name, $age){
      $this->name = $name;
      $this->age = $age;
    }
  }

توجه داشته باشید که constructor را طوری تنظیم کرده ایم که نام و سن را گرفته و به مقداری که ما بگوییم تنظیم کند. همچنین باید متوجه شده باشید که این متغیرها را به صورت private قرار داده ایم در صورتی که در قسمت قبل تمام آن ها public بودند. اگر در مورد constructor ها اطلاعات ندارید به قسمت قبل یا دوره ی آموزشی مخصوص شیء گرایی مراجعه کنید.

حالا که این مقادیر را به صورت private قرار داده ایم، آیا می توانیم از آن به همان روش قدیمی خروجی بگیریم؟

class User {
    private $name;
    private $age;

    public function __construct($name, $age){
      $this->name = $name;
      $this->age = $age;
    }

  $user1 = new User('John', 40);
  echo $user1->name;

در کد بالا یک شیء جدید از کلاس user ساخته ایم؛ فردی به نام john با 40 سال سن. در خط بعد نیز نام این کاربر را echo کرده ایم. به نظر شما خروجی John خواهد بود؟ خیر! خروجی خطای Fatal Error خواهد بود چرا که مقدار private یعنی فقط از درون خود تابع می توانیم به خصوصیات ها و متدهای آن دسترسی داشته باشیم. از طرفی کد echo نیز خارج از کلاس است بنابراین به خطا برمی خوریم. در این مثال می خواستیم مقدار property خاصی را get کنیم، یعنی دریافت کنیم.

حتی اگر بخواهیم مقداری را set کنیم (یعنی تنظیم کنیم) اجازه نخواهیم داشت:

  $user1->name = 'Jeff';
  echo $user1->name;

هر دوی این دستورها به خطا برخواهند خورد.

راه حل این مشکل تعریف یک getter (به معنی «گیرنده» - منظور گرفتن اطلاعاتی مثل نام کاربر است) و setter (به معنی «وضع کننده» - ثبت و تغییر اطلاعات) است. به کد زیر توجه کنید:

class User {
    private $name;
    private $age;

    public function __construct($name, $age){
      $this->name = $name;
      $this->age = $age;
    }

    public function getName(){
      return $this->name;
    }

در کد بالا تابعی تعریف کرده ایم (از نوع public) به نام getName (یعنی «نام را دریافت کن»). این تابع به ما اجازه خواهد داد که مقدار نام را دریافت کنیم. نکته ی مهم این است که حتما باید این تابع را درونِ خودِ کلاس تعریف کنید. برای دریافت نام باید کد زیر را بنویسید:

echo $user1->getName();

خروجی این کد، عبارت John خواهد بود (شیء ای که قبلا ساختیم).

حالا یک setter می نویسیم:

public function __construct($name, $age){
      $this->name = $name;
      $this->age = $age;
    }

    public function getName(){
      return $this->name;
    }

    public function setName($name){
      $this->name = $name;
    }

تابع setName یک متغیر می گیرد که همان نام کاربر است و در آن می گوییم که نام کاربر را به نام پاس داده شده تغییر بده. بنابراین برای تغییر نام John می گوییم:

echo $user1->setName('Jeff');

خروجی این کد نام Jeff خواهد بود.

سوال بسیار مهم: در برنامه های واقعی ممکن است تعداد خصوصیات (property) بسیار زیاد باشد. در چنین حالت هایی آیا باید برای هر خصوصیت یک setter و getter تعریف کنیم؟

پاسخ: خیر! در زبان PHP دو متد جادویی دیگر معرفی شده اند که این کار را برای ما انجام می دهند؛ set__ و get__ .

در کد زیر می خواهیم یک Getter تعیین کنیم که برای تمامی خصوصیت ها کار کند و نیازی به تعریف جداگانه ی setter ها نداشته باشیم. در چنین حالتی می گوییم:

public function __get($property){
      if(property_exists($this, $property)){
        return $this->$property;
      }
    }

ابتدا باید نام تابع جادویی get__ را تایپ کنید (public funtion __get) سپس درون آن می گوییم اگر (if) خصوصیت درخواست شده در کلاس موجود بود، فلان کار را انجام بده. تابع property_exists دو پارامتر میگیرد: اولین پارامتر یعنی در کدام کلاس دنبال خصوصیت بگردم؟ ما گفته ایم this یعنی در همین کلاس. پارامتر دوم نیز می گوید دنبال چه خصوصیتی باشم؟ ما گفته ایم property$ یعنی همان متغیری که به متد جادویی function __get داده شده است. به زبان ساده تر می گوییم اگر خصوصیتی به تو داشته شد آن را در این کلاس پیدا کن، اگر وجود داشت آنگاه return $this->$property  (یعنی آن خصوصیت را برگردان).

حالا می توانیم کدهای قبلی را حذف کرده و با این کدها مقدار نام را دریافت کنیم:

  echo $user1->__get('age');
  echo $user1->__get('name');

خروجی این کدها 40 (سن فرد) و John است. توجه داشته باشید برای استفاده از get جادویی باید خصوصیت موردنظر را درون quotation (علامت ' ' یا " ") قرار دهید (مانند کد بالا).

حالا باید یک set جادویی بسازیم:

public function __set($property, $value){
      if(property_exists($this, $property)){
        $this->$property = $value;
      }
      return $this;
    }

برای get یک پارامتر اضافه به نام value داریم. value همان مقدار جدیدی است که می خواهید برای یک خصوصیت قرار دهید. پس از آنکه چک کردیم تا مطمئن شویم آن خصوصیت در کلاس ما وجود دارد، مقدار آن را برابر با value قرار می دهیم. در آخر نیز return می کنیم. حالا اگر بخواهیم سن فرد را از 40 به 41 سال تغییر دهیم کد زیر را می نویسیم:

$user1->__set('age', 41);

توجه کنید که زمانی که Set می کنیم (یعنی مقداری را تغییر می دهیم) نمی توانیم آن را echo کنیم. نمایش دادن مقدار تغییر یافته بر عهده ی getter ها است.

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

<?php
  class User {
    private $name;
    private $age;

    public function __construct($name, $age){
      $this->name = $name;
      $this->age = $age;
    }

    public function getName(){
      return $this->name;
    }

    public function setName($name){
      $this->name = $name;
    }

    //  __get متد جادویی
    public function __get($property){
      if(property_exists($this, $property)){
        return $this->$property;
      }
    }

    // __set متد جادویی
    public function __set($property, $value){
      if(property_exists($this, $property)){
        $this->$property = $value;
      }
      return $this;
    }
  }

  $user1 = new User('John', 40);

  //$user1->name = 'Jeff';
  //echo $user1->name;

  // echo $user1->setName('Jeff');
  // echo $user1->getName();

  $user1->__set('age', 41);
  echo $user1->__get('age');

دانلود فایل کدها تا این جلسه (جلسه ی چهارم)

امیدوارم از این مقاله لذت برده باشید. در قسمت بعد در مورد وراثت (inheritance) صحبت خواهیم کرد.

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

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