Semasa mengerjakan projek Symfony dengan pasukan saya, saya perlu menyuntik tika Objek Nilai tertentu ke dalam salah satu perkhidmatan saya. Nilai itu sendiri, dalam kes khusus ini, perlu ditetapkan daripada nilai yang disediakan dalam fail .env kami.
Saya boleh, sudah tentu, hanya menghantar nilai rentetan terus ke dalam perkhidmatan saya dan meminta perkhidmatan membuat instantiate Objek Nilai dalam pembina, tetapi saya ingin melihat sama ada ia mungkin untuk mengkonfigurasinya dalam fail services.yaml dan menyuntik sebaliknya objek yang dibuat sepenuhnya. Ini akan membolehkan saya menghantar contoh objek tersebut kepada berbilang perkhidmatan dan tidak perlu mengulangi penciptaan Objek Nilai di dalam setiap satu.
Begini cara saya melakukannya...
Aplikasi kami menggunakan Twilio SDK. Kami mempunyai pelbagai perkhidmatan yang membungkus panggilan SDK, dan mereka perlu menggunakan nilai konfigurasi khusus persekitaran kami (Kunci API syarikat kami untuk setiap persekitaran, dsb.).
API Twilio menggunakan Pengecam Rentetan atau SID. Setiap jenis SID mempunyai awalan 2 huruf berbeza yang dikaitkan dengannya, diikuti dengan 32 aksara yang terdiri daripada digit 0 hingga 9 dan huruf A hingga F (huruf besar dan kecil).
Contohnya:
Saya ingin memastikan Objek Nilai untuk setiap jenis SID mengesahkan bahawa nilai yang diluluskan mempunyai awalan yang sesuai untuk jenis SID tersebut, bersama-sama dengan memastikan rentetan adalah panjang yang betul dan hanya terdiri daripada aksara yang dibenarkan .
Setiap jenis SID saya menggunakan logik dan fungsi pengesahan yang sama, hanya membezakan dengan awalan jenis SID, jadi masuk akal untuk mencipta Trait asas. Ini boleh menjadi Kelas Abstrak jika anda mahu. Saya tidak memerlukan konsep TwilioStringIdentifier dalam apl sebagai jenis parameter atau apa-apa seperti itu, jadi saya lebih suka Ciri daripada Kelas Abstrak di sini.
Sifat ini mentakrifkan kaedah abstrak getPrefixForSidType() yang mesti dilaksanakan oleh setiap jenis SID, memberikan awalan yang sesuai untuk jenis yang diberikan. Ia juga melaksanakan logik pengesahan.
namespace App\Domain\Model\Twilio\Sid; use Assert\Assert; trait TwilioStringIdentifier { private readonly string $sid; abstract private function getPrefixForSidType(): string; public static function fromString(string $string): self { return new self($string); } public function __construct(string $sid) { Assert::that($sid) ->startsWith($this->getPrefixForSidType()) ->length(34) ->regex('/^[a-zA-Z]{2}[0-9a-fA-F]{32}$/') ; $this->sid = $sid; } public function asString(): string { return $this->sid; } }
Kelas Objek Nilai yang mewakili setiap jenis SID adalah mudah. Mereka hanya perlu menggunakan TwilioStringIdentifier Trait dan untuk menentukan awalan yang betul melalui kaedah getPrefixForSidType().
namespace App\Domain\Model\Twilio\Sid; final readonly class AccountSid { use TwilioStringIdentifier; private function getPrefixForSidType(): string { return 'AC'; } }
Kelas jenis SID yang lain adalah sama kecuali untuk awalan yang ditentukan.
Oleh kerana Objek Nilai ini akan digunakan di seluruh aplikasi dan dengan pelbagai nilai yang dikaitkan, dan bukan hanya nilai global syarikat kami, saya memerlukan cara untuk menyuntik ke dalam perkhidmatan objek jenis tertentu yang telah digunakan dengan nilai yang ditentukan dalam fail .env kami
Saya tahu bahawa Symfony mempunyai keupayaan untuk mentakrifkan perkhidmatan untuk dijadikan instantiated melalui Kilang tetapi tidak pernah benar-benar melihat (yang saya ingat) apa-apa tentang menyuntik objek yang merupakan hasil daripada panggilan kaedah dari tempat lain. Saya juga tahu kaedah Kilang ini boleh menghantar hujah kepada mereka, cuma saya tidak pasti cara melakukannya dengan satu contoh Objek Nilai.
Takrif perkhidmatan Symfony membolehkan anda menamakan setiap perkhidmatan. Biasanya ia dilakukan dengan nama kelas Perkhidmatan:
App\Path\To\My\Service: class: App\Path\To\My\Service arguments: []
Tetapi, nama perkhidmatan itu tidak perlu sepadan dengan nama kelas. Ia boleh jadi app.my_service atau FooBarBazService atau apa sahaja.
Jadi, bagaimana jika saya mencipta perkhidmatan dengan nama unik yang merupakan contoh instan bagi Objek Nilai yang saya perlukan? Saya boleh menghantar nilai .env sebagai hujah dan kemudian meminta contoh objek itu untuk disuntik ke dalam kelas perkhidmatan saya!
# Create services named with a Global "namespace" Global\Twilio\Sid\Account: factory: ['App\Domain\Model\Twilio\Sid\AccountSid', 'fromString'] arguments: ['%env(TWILIO_ACCOUNT_SID)%'] Global\Twilio\Sid\Api: factory: ['App\Domain\Model\Twilio\Sid\ApiSid', 'fromString'] arguments: ['%env(TWILIO_API_SID)%'] Global\Twilio\Sid\Application: factory: ['App\Domain\Model\Twilio\Sid\ApplicationSid', 'fromString'] arguments: ['%env(TWILIO_APP_SID)%']
Kemudian hantar perkhidmatan tersebut (objek) ke dalam perkhidmatan Twilio saya melalui hujah bernama:
App\Service\Vendor\Twilio\TwilioService: arguments: $accountSid: '@Global\Twilio\Sid\Account' $apiSid: '@Global\Twilio\Sid\Api' $applicationSid: '@Global\Twilio\Sid\Application' $apiSecret: '%env(TWILIO_API_SECRET)%'
Kini kelas perkhidmatan saya boleh mengharapkan untuk menerima contoh Objek Nilai yang dibuat sepenuhnya:
namespace App\Service\Vendor\Twilio; use App\Domain\Model\Twilio\Sid\AccountSid; use App\Domain\Model\Twilio\Sid\ApiSid; use App\Domain\Model\Twilio\Sid\ApplicationSid; final readonly class TwilioService { public function __construct( private AccountSid $accountSid, private ApiSid $apiSid, private ApplicationSid $applicationSid, private string $apiSecret ) {} }
Vila!
Symfony cukup fleksibel dan cukup intuitif sehingga mudah untuk mengetahui cara melakukannya. Memandangkan saya tidak dapat mencari rujukan pantas untuk melakukan ini di tempat lain, saya fikir saya akan menulis ini sebagai rujukan untuk Future Me dan sesiapa sahaja yang mungkin perlu melakukan sesuatu yang serupa
Sola, dan Selamat Mengekod!
Atas ialah kandungan terperinci Suntikan Objek Nilai Ke dalam Perkhidmatan Symfony Berwayar Auto. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!