Yii2 service locator

Ko'pchiligimiz Yii2 loyihalar yasagan paytimizda ko'p marta ko'rganmiz, agar yangi componentlar qo'shsak config/web.php ni o'zgartiramiz. Ko'pincha agar composer orqali yangi kutubxonalar (ya'ni library) o'rnatsak ko'pincha web.php dagi components degan massiv ichiga qo'shimcha kod kiritamiz va bu kodga Yii::$app dan turub murojaat qilsak bo'ladi. Buning sababi Yii2 ning asosi Service Locator patterndan tashkil topgan. Service Locator bu dasturda zarurati kelganda kerakli servicelarni qaytaruvchi obyekt.

Bu obyekt asosi 3ta metodan iborat bu get (kerakli serviceni beruvchi), set (kerakli serviceni ro'yxatdan o'tkazuvchi) va has (service ro'yxatdan o'tganmi yoki yo'q shuni tekshiradi). Misol uchun Yii::$app bu juda katta bo'lgan service locator obyektidir. Unga yangi service qo'shish uchin siz set() metodiga murojaat qilasiz, masalan, Yii::$app->set('dateFormater','app\components\DateFormater'). Bu yo'l orgali siz yangi serviceni dasturga qo'shasiz va bu serviceni dasturning har qanday qismidan turub ham murojaat qilsa bo'ladi. Masalan mana bunday qilib.

//Service ni string yani satr triqasida setga berish usuli.
Yii::$app->set('dateFormater','app\components\DateFormater');
<span class="redactor-invisible-space">//Service ni Klassni class nomi orqali berish usuli
Yii::$app->set('dateFormater','app\components\DateFormater');
//Service ga murojaat get metodi orqali
</span
Yii::$app->get('dateFormater');
<span class="redactor-invisible-space">//Servicega to'g'ridan-to'g'ri murojaat qilish.
Yii::$app->dateFormater;
//Service bor yoki yo'qligini tekshirish
</span>
Yii::$app->has('dateFormater');

Tepadagi misollarda qanday qilib service locator bilan ishlash mumkin ekanligiga misol keltirilgan. Service Locator klassi yii\base\Object dan meros olgani sababli har qanday getter ga (ya'ni o'zgaruvchini ismi bilan qaytaruvchi metod) to'g'ridan murojaat qilsa bo'ladi. Aslida service ga murojaat bunday bo'lishi kerak: Yii::$app->get('dateFormater') ammo unga oddiygina qilib Yii::$app->dateFormater qilib murojaat qilsa ham bo'ladi.

Siz o'zingizni shaxsiy service locator klassingizni yasasangiz bo'ladi bunining uchun oddiygina ServiceLocator klassiga murojaat qilib, undan obyekt yasashingiz kerak.

Misol uchun bunday qilib:

$sloc=new ServiceLocator();
$sloc->set('dateFormatter','app\components\dateFormatter');
$sloc->get('dateFormatter');
$sloc->dateFormatter;

Service Locatorni ishatilishning asosiy sababi obyektlar o'rtasidagi qaramlikni (ya'ni tightly coupling) yo'qotadi. Ya'ni obyeklar mustaqil ravishda ishlatilinadi. Keling endi sal qiyinroq misol ko'ramiz. Yii2 dagi config/web.php dagi components ga qarang. Bu ancha kattagina massiv bo'lib, bu Yii::$app ning servicelari ko'rsatilgan joydir. U yerga har bir massiv kaliti bu qaysidir klassga murojaat qilish uchun ishlatilinadi. Misol uchun:

'mailer' => [
    'class' => 'yii\swiftmailer\Mailer',
    // send all mails to a file by default. You have to set
    // 'useFileTransport' to false and configure a transport
    // for the mailer to send real emails.
    'useFileTransport' => true,
],

mailer kaliti Yii::$app->mailer(ya'ni email jo'natuvchi klassni )ni chaqirishda ishlatilinadi. Demak, ko'rib turibsizki birinchi bo'lib biz kalit so'zni kiritamiz, so'ng u qaysi klassga bog'langanini ko'rsatamiz.

Keling endi o'zimizning shaxsiy servicesimizni yasaylikda, uni components ga qo'shib qo'yaylik. Yasaydigan servicesimiz oddiygina berilgan timestampni sanaga o'girsin.

namespace app\components
class DateFormatter
{
   public function timeToDate($timestamp)
   {
      return date('d-m-Y',$timestamp);
   }
}

Mana endi bu classni config/web.php ga qo'shsak bo'ldi.

'components' => [
   'dateFormatter'=>[
      'class'=>\app\components\DateFormatter::class
   ],
//components ni davomi

Mana endi siz bemalol Yii::$app->dateFormater ga murojaat qilsangiz bo'ladi. Masalan:

echo Yii::$app->dateFormatter->timeToDate(time()); //Jabov 30-12-2017

Aytaylik siz formatni boshqacha qilib ishlatmoqchisiz, ammo boshqa joydagi shu klassdan yasalgan obyektlarga ko'rsatishni istamayapsiz. Unda DateFormatter klassimizga oddiygina qo'shimcha o'zgaruvchi qo'shib shu o'zgaruvchi qiymati bo'yicha vaqtni ko'rsatamiz.

namespace app\components;

class DateFormatter
{
  public $format='d-m-Y';
  public function timeToDate($timestamp)
  {
     return date($this->format,$timestamp);
  }
}

Ko'rib turganingizdek, $format deb nomlanuvchi o'zgaruvchi qiymati bo'yicha biz vaqtni ko'rsatyapmiz. Endi faqat config/web.php da shuni formatini to'g'rilab qo'ysak bo'ldi. Aytaylik biz servicesimizda vaqni 30 Dec 17 holatida ko'rsatmoqchimiz. Demak uni bunday qilib yozamiz.

'components' => [

   'dateFormatter'=>[
     'class'=>\app\components\DateFormatter::class ,
     'format' => 'd M y'
   ],

Mana bo'ldi, biz qo'shimcha qilib DateFormatterni ochiq (yani public) o'zgaruvchisiga kerakli formatni berdik.

Agar siz hech qanday o'zgaruvchisiz oddiy class bilan ishlashni xohlasangiz unda anonim funksiyadan ham foydalansa bo'ladi, masalan:

'components' => [

   'dateFormatter'=>function()
    {
        return new \app\components\DateFormatter();
    },

Mana bo'ldi, hozircha shu agar taklif va savollaringiz bo'lsa izohlarda qoldiring.

E'tiboringiz uchun rahmat!


Ziyavuddin

Muallif haqida

Vakhobov Ziyavuddin PHP da Yii2 Laravel va Symfonyda ishliman.


Blogdagi so‘nggi maqolalar:


Birinchi bo‘ling!

Iltimos, fikr bildirish uchun saytga kiring yoki ro‘yxatdan o‘ting!