การฉีดการพึ่งพา Laravel พร้อมการสืบทอด

สมมติว่าฉันมีกรณีต่อไปนี้:

<?php

abstract class Service {

    protected $config;

    public function __construct($config)
    {
        $this->config = $config;
    }
}

class ClientService extends Service {

}

class ProductService extends Service {

}

เป็นไปได้หรือไม่ที่จะลงทะเบียนการฉีดการพึ่งพาสำหรับคลาสพาเรนต์ Abstract ของบริการของฉันในผู้ให้บริการของฉัน

ฉันมี API ที่สร้างขึ้นแบบไดนามิกจากข้อกำหนด และแต่ละคลาสเหล่านั้นต้องขยาย abstract Service เพื่อให้สามารถสืบทอดสำหรับฟังก์ชันพื้นฐานได้

ฉันจะแทรกการพึ่งพาในบริการนามธรรมของฉันได้อย่างไรเมื่อฉันสร้างอินสแตนซ์บริการย่อย


แก้ไข: คำถามนี้ถูกถามโดยเฉพาะสำหรับการแทรกคลาส Abstract โดยไม่มีความเป็นไปได้ที่จะผูกคลาสย่อยที่สร้างขึ้นโดยอัตโนมัติ


person kitensei    schedule 18.06.2015    source แหล่งที่มา


คำตอบ (2)


ในตัวอย่างของคุณ คุณต้องส่งอ็อบเจ็กต์ config ด้วยตนเองทุกครั้งที่คุณสร้างอินสแตนซ์จากคลาส Service หรือคลาสลูก

ดังนั้นเมื่อคุณต้องการยกตัวอย่างบริการเด็กโดยตรง คุณสามารถใช้คำสั่งเช่น $cs = new ClientService(new Config());

อย่างไรก็ตาม คุณสามารถใช้ข้อได้เปรียบที่แท้จริงของ DI ได้ (เนื่องจากคุณใช้ Laravel) โดยพิมพ์ชื่อคลาสในตัวสร้างตามด้านล่าง

public function __construct(\Config $config)

ด้วยวิธีนี้ หากคุณไม่ส่งพารามิเตอร์เมื่อสร้างอินสแตนซ์ ค่าเริ่มต้นจะสร้างอ็อบเจ็กต์ของคลาส type-hinted และแทรกเข้าไป ดังนั้นคุณสามารถใช้มันได้เหมือน

$cs = new ClientService();

สิ่งนี้จะแทรกอินสแตนซ์ Laravel Config ลงในวัตถุ ClientService

person blackpla9ue    schedule 18.06.2015
comment
ตกลง ฉันไม่มีวิธีจริง ๆ ที่จะฉีดโค้ดเฉพาะเจาะจงมากกว่านี้ในคลาสนามธรรมใช่ไหม ฉันต้องใช้ DI อัตโนมัติจาก laravel ในกรณีนี้หรือไม่ - person kitensei; 18.06.2015
comment
ใช่ แต่ข้อดีคือ หากคุณใช้คลาสนี้ที่อื่น คุณจะมีตัวเลือกในการส่งผ่าน config instance ที่คุณอาจมีด้วยตนเอง คุณสามารถทำได้เสมอ ClientService(new SomeOtherConfig()); - person blackpla9ue; 18.06.2015

มีสองสิ่งที่เป็นไปได้ที่คุณสามารถทำได้ที่นี่ ขั้นแรก ถ้า $config เป็นคลาส คุณสามารถพิมพ์คำใบ้ในคลาส abstract ได้:

abstract class Service {

    protected $config;

    public function __construct(ClassName $config)
    {
        $this->config = $config;
    }
}

จากนั้นทุกครั้งที่คลาสย่อยได้รับการแก้ไขผ่านการฉีดหรือโดยการเรียก App::make('ClientService') คลาส config จะถูกฉีดเข้าไป

หากการกำหนดค่าไม่ใช่คลาสและไม่สามารถระบุประเภทได้ คุณจะต้องผูกคลาสย่อยเข้ากับคอนเทนเนอร์ทีละรายการ:

App::bind('ClientService', function () {
    // Get $config from somewhere first

    return new ClientService($config);
});

App::bind('ProductService', function () {
    // Get $config from somewhere first

    return new ProductService($config);
});

จากนั้นคุณจะสามารถโทร App::make('ClientService') หรือให้แก้ไขปัญหาผ่านทาง DI

person James Flight    schedule 18.06.2015
comment
อันที่จริงฉันคิดเกี่ยวกับเรื่องนี้ แต่ฉันต้องการหลีกเลี่ยงเนื่องจากคลาสบริการถูกสร้างขึ้นจากข้อมูลจำเพาะด้วยงาน cron ดังนั้น (มันไม่ควรเกิดขึ้น แต่ใครจะรู้) สามารถเพิ่มคลาสบางคลาสได้ และฉันจะต้องอัปเดต ผู้ให้บริการด้วยตนเอง - person kitensei; 18.06.2015
comment
แน่นอนว่าจะไม่หยุดตัวเลือกแรกทำงานใช่ไหม - person James Flight; 18.06.2015
comment
แน่นอน ฉันคิดว่านั่นคือสิ่งที่ฉันจะทำ ฉันจะเลือกคำตอบอื่นตามที่ตอบกรณีของฉันก่อนหน้าคุณ - person kitensei; 18.06.2015