Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Satu artikel untuk memahami dan melaksanakan bekas IOC dalam rangka kerja PHP moden

Satu artikel untuk memahami dan melaksanakan bekas IOC dalam rangka kerja PHP moden

WBOY
WBOYke hadapan
2022-12-29 10:39:074689semak imbas

Artikel ini membawa anda pengetahuan yang berkaitan tentang PHP, yang terutamanya memperkenalkan kandungan yang berkaitan tentang bekas IOC ialah: Inversion Of Control, inversion control lihat, harap ia membantu semua orang.

Satu artikel untuk memahami dan melaksanakan bekas IOC dalam rangka kerja PHP moden

Apakah bekas?

Saya percaya ramai orang pernah mendengar tentang suntikan kebergantungan Syarat asas untuk pelaksanaan suntikan kebergantungan tidak dapat dipisahkan daripada bekas digunakan untuk menguruskan kebergantungan kelas dan komponen penyuntikan pemahaman adalah Kita boleh memahami bekas sebagai tatasusunan super besar yang didedikasikan untuk menyimpan objek.

Satu artikel untuk memahami dan melaksanakan bekas IOC dalam rangka kerja PHP moden

Seperti yang ditunjukkan dalam rajah, pemanggil mendapatkan contoh objek melalui label bekas Seperti yang boleh dilihat dalam rajah, ia boleh diperolehi melalui ::class atau terus melalui objek Menunjukkan mendapat objek contoh.

Apakah itu IOC?

Anda mungkin pernah mendengar tentang bekas IOC Nama penuh IOC ialah: (Inversion Of Control).

Mari kita fahami apa itu penyongsangan kawalan Dalam pengekodan tradisional kami, kebergantungan kami antara kelas biasanya ialah kami mencipta objek baharu dan kemudian menghantarnya melalui pengekodan Menggunakan penyongsangan kawalan yang anda boleh berikan kawalan objek itu wadah atau rangka kerja untuk pelaksanaan. Tujuannya adalah untuk membolehkan kita mencipta objek tanpa pengekodan keras Seperti yang anda lihat dari Rajah 1, terdapat banyak objek yang disimpan dalam bekas, yang boleh digunakan secara langsung apabila kita ingin menggunakannya. Objek dalam bekas tidak memerlukan kami menciptanya dalam kod. Apabila objek kelas tertentu diperlukan, objek akan diperoleh daripada bekas Jika objek tidak wujud, ia akan dibuat secara automatik. Ini bermakna kami meninggalkan proses mencipta objek dalam kod dan bekas membantu kami merealisasikan proses penciptaan ini. Ini dipanggil kawalan penyongsangan. Untuk meringkaskan IOC dalam satu ayat: pindahkan kawalan untuk mencipta objek kepada instantiasi kelas pelaksanaan kontena.

Contohnya: tanpa menggunakan IOC, kami mahu mencipta kelas

<?php
class Sunny{
}
$sunny = new Sunny();

Kami perlu mencipta kelas baharu secara manual dalam kes ini, ia dikodkan dengan keras dalam kod.

Kod menggunakan bekas IOC boleh ditulis seperti ini.

<?php
class Sunny{
}
$sunny = Container::getBean(Sunny::class);

Bantu kami melaksanakan kelas ini di dalam bekas Sesetengah pelajar mungkin mempunyai soalan apabila mereka melihat ini Jika saya menggunakan Sunny baharu, bukankah kod itu akan menjadi lebih pendek dan ringkas? Mari kita lihat contoh selepas melihat suntikan pergantungan.

Suntikan Ketergantungan

Sekarang kita tahu apa itu IOC, persoalan baharu timbul Apabila kita mencipta kelas, apakah yang perlu kita lakukan jika pembina beberapa kelas memerlukan kita untuk lulus parameter? Melalui kajian IOC, kita tahu bahawa bekas IOC akan membantu kita menyelesaikan masalah penciptaan contoh objek Apabila mencipta objek dalam bekas, jika didapati bahawa kelas mempunyai kebergantungan lain, ia akan melakukan carian ketergantungan proses bekas mencari objek yang diperlukan dipanggil DL ( Dependency Lookup, dependency lookup). Menyuntik kebergantungan yang diperlukan ke dalam serpihan kod dipanggil DI (Suntikan Ketergantungan, suntikan kebergantungan).

Sebagai contoh, contoh Sunny baharu yang disebut dalam IOC. Jika terdapat banyak kebergantungan antara kelas.

<?php
class Computer{
    public function run(){
        echo "编程中....\n";
    }
}
class Sunny{
    private $computer;
    public function __construct(Computer $computer){
        $this->computer = $computer;
    }
    public function program(){
        $this->computer->run();
    }
}
$sunny = new Sunny(new Computer());
$sunny->program();

Di sini anda dapat melihat bahawa kelas Sunny ingin bergantung pada kelas Komputer untuk pengaturcaraan Jika anda menggunakan bekas IOC untuk melaksanakan suntikan pergantungan, kodnya akan menjadi mudah.

<?php
class Computer{
    public function run(){
        echo "编程中....\n";
    }
}
class Sunny{
    private $computer;
    public function __construct(Computer $computer){
        $this->computer = $computer;
    }
    public function program(){
        $this->computer->run();
    }
}
$sunny = Container::getBean(Sunny::class);
$sunny->program();

Ringkasan satu ayat: Selesaikan pergantungan pada kelas lain apabila mencipta tika kelas dan secara dinamik menyediakan objek dengan objek lain yang diperlukannya.

Penyongsangan Ketergantungan

Masalah yang diselesaikan oleh penyongsangan kebergantungan adalah untuk melonggarkan kebergantungan berat antara modul-modul atas tidak seharusnya bergantung pada modul yang lebih rendah, semuanya harus bergantung pada abstraksi. Biasanya, pemahaman mudah tentang penyongsangan kebergantungan ialah pengaturcaraan ke arah antara muka atau abstraksi. Mari kita lihat pengaturcaraan berorientasikan antara muka melalui contoh berikut.

class Cache{
    public function set($key,$value){
        $redis = new CFile();
        $redis->set($key,$value);
    }
}
class CFile{
    public function set($key,$value){
        echo "file:{$key}->{$value}\n";
    }
}
$cache = new Cache();
$cache->set("name","sunny");

Kod di atas nampaknya tiada masalah besar, tetapi bagaimana jika suatu hari cache fail ditukar kepada cache Redis?

class Cache{
    public function set($key,$value){
        $redis = new CRedis();
        $redis->set($key,$value);
    }
}
class CRedis{
    public function set($key,$value){
        echo "redis:{$key}->{$value}\n";
    }
}
$cache = new Cache();
$cache->set("name","sunny");

Daripada kod ini dapat dilihat bahawa apabila pemacu yang digunakan oleh cache berubah, kod Cache juga mesti membuat perubahan yang sepadan, kerana kod itu ditulis pada pemanggil dan darjah gandingan berubah tinggi. Ia sama seperti mengubah suai kod, membenarkan pengaturcara untuk memprogram ke arah antara muka, menjadikan kod lebih serba boleh dan piawai.

interface ICache{
    public function set($key,$value);
}
class CRedis implements ICache {
    public function set($key,$value)
{
        echo "redis:{$key}->{$value}\n";
    }
}
class CFile implements ICache{
    public function set($key,$value)
{
        echo "file:{$key}->{$value}\n";
    }
}
class Cache{
    private $drive;
    public function __construct(ICache $drive)
{
        $this->drive = $drive;
    }
    public function set($key,$value){
        $this->drive->set($key,$value);
    }
}
$cache = new Cache(new CFile());
$cache->set("name","sunny");

Ramai orang berfikir apabila mereka melihat kod ini, bukankah saya patut menghantar objek yang dikehendaki terus ke dalam pembina? Mengapa kita perlu menentukan antara muka? Malah, antara muka ditakrifkan untuk menyeragamkan kod Tidak kira pemacu mana yang anda gunakan, selagi ia melaksanakan antara muka saya, anda boleh menggunakannya Tanpa antara muka, pembangun tidak akan tahu kaedah apa yang perlu dimasukkan dalam pemacu semasa membangunkan pemandu itu. Apabila kita menggunakan antara muka, kita hanya perlu memprogramkan untuk antara muka Cache tidak mengambil berat tentang bagaimana kelas dilaksanakan hanya mengikut kaedah antara muka.

Ringkasan satu ayat: Penyongsangan kebergantungan mencapai gandingan longgar

Pertempuran praktikal: Melaksanakan bekas berdasarkan prinsip kontena

<?php
class Container
{
    // 当前容器对象
    private static $instance;
    // 存放在容器里面到实例
    protected $instances = [];
    private function __construct()
{
    }
    public static function getInstance()
{
        if (!self::$instance) {
            self::$instance = new static();
        }
        return self::$instance;
    }
    /**
     * 获取对象实例
     * @param $key
     * @return mixed
     */
    public function get($key)
{
        if (isset($this->instances[$key])) {
            return $this->instances[$key];
        }
    }
    /**
     * 绑定对象、闭包、类到容器
     * @param $key
     * @param null $concrete
     * @return Container
     */
    public function bind($key, $concrete = null)
{
        if ($concrete instanceof Closure) {
            $this->instances[$key] = $concrete;
        } elseif (is_object($concrete)) {
            $this->instances[$key] = $concrete;
        }
        return $this;
    }
}
class Sunny
{
    public function getName()
{
        echo time() . "\n";
    }
}
$app = Container::getInstance();
$sunny = $app->bind(Sunny::class,new Sunny());
$sunny = $app->get(Sunny::class);
$sunny->getName();

Pertempuran praktikal: Melaksanakan suntikan pergantungan

Container.php
<?php
class Container
{
    // 当前容器对象
    private static $instance;
    // 存放在容器里面到实例
    protected $instances = [];
    private function __construct()
{
    }
    public static function getInstance()
{
        if (!self::$instance) {
            self::$instance = new static();
        }
        return self::$instance;
    }
    /**
     * 获取对象实例
     * @param $key
     * @return mixed
     * @throws ReflectionException
     */
    public function get($key)
{
        if (isset($this->instances[$key])) {
            return $this->instances[$key];
        }
        return $this->make($key);
    }
    /**
     * 绑定对象、闭包、类到容器
     * @param $key
     * @param null $concrete
     * @return Container
     * @throws ReflectionException
     */
    public function bind($key, $concrete = null)
{
        if ($concrete instanceof Closure) {
            $this->instances[$key] = $concrete;
        } elseif (is_object($concrete)) {
            $this->instances[$key] = $concrete;
        } else {
            $this->make($key, $concrete);
        }
        return $this;
    }
    /**
     * 创建类绑定到类实例
     * @param $abstract
     * @param null $atgs
     * @return mixed
     * @throws ReflectionException
     */
    public function make($abstract, $atgs = null)
{
        if (isset($this->instances[$abstract])) {
            return $this->instances[$abstract];
        }
        $object = $this->invokeClass($abstract);
        $this->instances[$abstract] = $object;
        return $object;
    }
    /**
     * 反射解析类
     * @param $abstract
     * @return object
     * @throws ReflectionException
     */
    public function invokeClass($abstract)
{
        $reflectionClass = new \ReflectionClass($abstract);
        // 获取构造方法
        $construct = $reflectionClass->getConstructor();
        // 获取参数得到实例
        $params = $construct ? $this->parserParams($construct) : [];
        $object = $reflectionClass->newInstanceArgs($params);
        return $object;
    }
    /**
     * 解析构造方法参数
     * @param $reflect
     * @return array
     * @throws ReflectionException
     */
    public function parserParams(ReflectionMethod $reflect)
{
        $args = [];
        $params = $reflect->getParameters();
        if (!$params) {
            return $args;
        }
        if (count($params) > 0) {
            foreach ($params as $param) {
                $class = $param->getClass();
                if ($class) {
                    $args[] = $this->make($class->getName());
                    continue;
                }
                // 获取变量的名称
                $name = $param->getName();
                // 默认值
                $def = null;
                // 如果有默认值,从默认值获取类型
                if ($param->isOptional()) {
                    $def = $param->getDefaultValue();
                }
                $args[] = $_REQUEST[$name] ?? $def;
            }
        }
        return $args;
    }
}
Test.php
<?php
class Test
{
    public $name;
    private $test1;
    public function __construct(Test1 $test1)
{
        $this->test1 = $test1;
        $this->name = $this->test1->getName();
    }
}
Test1.php
<?php
class Test1
{
    public function getName(){
        return "test1返回的名字";
    }
}
Sunny.php
<?php
require_once "./Container.php";
require_once "./Test.php";
require_once "./Test1.php";
class Sunny
{
    private $test;
    public function __construct(Test $test)
{
        $this->test = $test;
    }
    public function getName()
{
        echo "获取test里面的name:{$this->test->name}\n";
    }
}
$app = Container::getInstance();
$sunny = $app->get(Sunny::class);
$sunny->getName();

Pembelajaran yang disyorkan: "Tutorial Video PHP"

Atas ialah kandungan terperinci Satu artikel untuk memahami dan melaksanakan bekas IOC dalam rangka kerja PHP moden. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:IT不是挨踢微信公众号. Jika ada pelanggaran, sila hubungi admin@php.cn Padam