目次
中看不中用の代コード分析Iocコンテナ、依赖注入....、中看不中用ioc
[翻訳内容]
IoCコンテナ、laravelの核心
オブジェクトに向かうプロセスでは、以下のような絶え間ない接触があります:
一堆乱麻 —— 可怕的依赖
工厂模式,依赖转移!
更为先进的工厂 —— IoC 容器!
回归正常世界。我们开始重新审视 laravel 的核心。
服务提供者
Facade
和平!我们该总结总结了!
ホームページ バックエンド開発 PHPチュートリアル 使用されていないコード、依存関係注入....、ioc_PHP チュートリアルによる IOC コンテナーの分析

使用されていないコード、依存関係注入....、ioc_PHP チュートリアルによる IOC コンテナーの分析

Jul 12, 2016 am 08:59 AM

中看不中用の代コード分析Iocコンテナ、依赖注入....、中看不中用ioc

<span>/*</span><span>*
 * 通过生产拥有超能力的超人实例 来理解IOC容器
 </span><span>*/</span>

<span>//</span><span>超能力模组接口</span>
<span>interface</span><span> SuperModuleInterface{
    </span><span>public</span> <span>function</span> activate(<span>array</span> <span>$target</span><span>);
}

</span><span>//</span><span>超能力模组</span>
<span>class</span> XPower <span>implements</span><span> SuperModuleInterface{
    </span><span>public</span> <span>function</span> activate(<span>array</span> <span>$target</span><span>){
        </span><span>//</span><span>......</span>
<span>    }
}
</span><span>class</span> UltraBomb <span>implements</span><span> SuperModuleInterface{
    </span><span>public</span> <span>function</span> activate(<span>array</span> <span>$target</span><span>){
        </span><span>//</span><span>......</span>
<span>    }
}

</span><span>//</span><span>超人类</span>
<span>class</span><span> Superman{
    </span><span>protected</span> <span>$module</span><span>;
 
    </span><span>public</span> <span>function</span> __construct(SuperModuleInterface <span>$module</span><span>)
    {
        </span><span>$this</span>->module = <span>$module</span><span>;
    }
}

</span><span>/*</span><span>*
 * 简陋的IOC容器(超级工厂)
 </span><span>*/</span>
<span>class</span><span> Container{
    </span><span>protected</span> <span>$binds</span><span>;
    </span><span>protected</span> <span>$instances</span><span>;
    </span><span>public</span> <span>function</span> bind(<span>$abstract</span>,<span>$concrete</span><span>){
        </span><span>if</span>(<span>$concrete</span><span> instanceof Closure){
            </span><span>$this</span>->binds[<span>$abstract</span>] = <span>$concrete</span><span>;
        }</span><span>else</span><span>{
            </span><span>$this</span>->instances[<span>$abstract</span>] = <span>$concrete</span><span>;
        }
    }

    </span><span>public</span> <span>function</span> make(<span>$abstract</span>,<span>$parameters</span>=<span>[]){
        </span><span>if</span>(<span>isset</span>(<span>$this</span>->instances[<span>$abstract</span><span>])){
            </span><span>return</span> <span>$this</span>->instances[<span>$abstract</span><span>];
        }
        </span><span>array_unshift</span>(<span>$parameters</span>,<span>$this</span><span>);
        </span><span>return</span> <span>call_user_func_array</span>(<span>$this</span>->binds[<span>$abstract</span>],<span>$parameters</span><span>);
    }
}

</span><span>//</span><span>超级工厂生产脚本</span>
<span>$container</span> = <span>new</span><span> Container();
</span><span>$container</span>->bind('superman',
                 <span>function</span>(<span>$container</span>,<span>$moduleName</span><span>)
                       {
                       </span><span>return</span> <span>new</span> Superman(<span>$container</span>->make(<span>$moduleName</span><span>));
                       }
);
</span><span>$container</span>->bind('xpower',<span>function</span>(<span>$container</span>){ <span>return</span> <span>new</span><span> XPower; });
</span><span>$container</span>->bind('ultrabomb',<span>function</span>(<span>$container</span>){ <span>return</span> <span>new</span><span> UltraBomb; });

</span><span>//</span><span>生产</span>
<span>$superman_1</span> = <span>$container</span>->make('superman',['xpower'<span>]);
</span><span>$superman_2</span> = <span>$container</span>->make('superman',['ultrabomb'<span>]);

</span><span>print_r</span>(<span>$superman_1</span><span>);
</span><span>print_r</span>(<span>$superman_2</span><span>);



</span><span>/*</span><span>
Superman Object
(
    [module:protected] => XPower Object
        (
        )

)
Superman Object
(
    [module:protected] => UltraBomb Object
        (
        )

)
 </span><span>*/</span>
ログイン後にコピー

>>>>>>>>>>>>>>>>>>>>>>>>> ;>>>>>>>>>>>>>>>>>>>>>>>>> ;>>>>>>>>>>>>>>>>>>>>>>>>> ;>>>

>>>>>>>>>>>>>>>>>>>>>>>>> ;>>>>>>>>>>>>>>>>>>>>>>>>> ;>>>>>>>>>>>>>>>>>>>>>>>>> ;>>>

>>>>>>>>>>>>>>>>>>>>>>>>> ;>>>>>>>>>>>>>>>>>>>>>>>>> ;>>>>>>>>>>>>>>>>>>>>>>>>> ;>>>

[翻訳内容]

IoCコンテナ、laravelの核心

Laravel の核心は 1 つです」と名付けられており、このコンテナはフレーム全体に必要な一連のサービスを提供します。オブジェクトへの依存の生成と反映方法を理解することで、「依存注入」の面の種類が徐々に理解され、この神奇なデザインの概念が理解されます。 IoC 容器,根据文档,称其为“服务容器

本書の大部分の内容は、例を通じて、

が何であるかを再理解するためのものであり、これらの概念を理解することで、より深く理解できるようになります。 IoC(控制反转)DI(依赖注入) IoCコンテナ誕生の故事

IoC コンテナには非常に多くの文章があり、私も以前に書きました。しかし、私は適切な感覚を利用して新たに始めました。

超人和超能力、依赖の産物!

オブジェクトに向かうプロセスでは、以下のような絶え間ない接触があります:

ここで、インターフェースはある種のプロトタイプであり、その実装されたインターフェースに従う必要があるタイプの 1 つです。これは一例として知られています。 リーリー

我们一“超人”を一类として、

接口还有对象クラス

スーパーマン

    {}
  1. 私たちは、あるスーパーマンが発生する時点で少なくとも 1 つの超能力を持っていると考えており、この超能力は、他の種類の説明を表す 1 つのオブジェクトとして抽象化することもできます。方法、この尽力の想念、しかし目前に私は唯一のプロパティの「超能力」を決定し、能力干啥、我们以後更富:

    クラス
パワー

{
  1. /**

  2. *能力値

  3. */

  4. 保護されている $ability;

  5. /**
  6. *能力範囲または距離

  7. */

  8. protected $range;

  9. public function __construct($ability, $range)

  10. {

  11. $this->ability = $ability;

  12. $this->range = $range;

  13. }

  14. }

这时候我们回过头,修改一下之前的“超人”类,让一个“超人”创建的时候被赋予一个超能力:

  1. class Superman

  2. {

  3. protected $power;

  4. public function __construct()

  5. {

  6. $this->power = new Power(999, 100);

  7. }

  8. }

这样的话,当我们创建一个“超人”实例的时候,同时也创建了一个“超能力”的实例,但是,我们看到了一点,“超人”和“超能力”之间不可避免的产生了一个依赖。

<p>所谓&ldquo;依赖&rdquo;,就是 &ldquo;我若依赖你,我就不能离开你&rdquo;。</p>
ログイン後にコピー

在一个贯彻面向对象编程的项目中,这样的依赖随处可见。少量的依赖并不会有太过直观的影响,我们随着这个例子逐渐铺开,让大家慢慢意识到,当依赖达到一个量级时,是怎样一番噩梦般的体验。当然,我也会自然而然的讲述如何解决问题。

一堆乱麻 —— 可怕的依赖

之前的例子中,超能力类实例化后是一个具体的超能力,但是我们知道,超人的超能力是多元化的,每种超能力的方法、属性都有不小的差异,没法通过一种类描述完全。我们现在进行修改,我们假设超人可以有以下多种超能力:

  • 飞行,属性有:飞行速度、持续飞行时间

  • 蛮力,属性有:力量值

  • 能量弹,属性有:伤害值、射击距离、同时射击个数

我们创建了如下类:

  1. class Flight

  2. {

  3. protected $speed;

  4. protected $holdtime;

  5. public function __construct($speed, $holdtime) {}

  6. }

  7. class Force

  8. {

  9. protected $force;

  10. public function __construct($force) {}

  11. }

  12. class Shot

  13. {

  14. protected $atk;

  15. protected $range;

  16. protected $limit;

  17. public function __construct($atk, $range, $limit) {}

  18. }

*为了省事儿我没有详细写出 __construct() 这个构造函数的全部,只写了需要传递的参数。

好了,这下我们的超人有点“忙”了。在超人初始化的时候,我们会根据需要来实例化其拥有的超能力吗,大致如下:

  1. class Superman

  2. {

  3. protected $power;

  4. public function __construct()

  5. {

  6. $this->power = new Fight(9, 100);

  7. // $this->power = new Force(45);

  8. // $this->power = new Shot(99, 50, 2);

  9. /*

  10. $this->power = array(

  11. new Force(45),

  12. new Shot(99, 50, 2)

  13. );

  14. */

  15. }

  16. }

我们需要自己手动的在构造函数内(或者其他方法里)实例化一系列需要的类,这样并不好。可以想象,假如需求变更(不同的怪物横行地球),需要更多的有针对性的 新的 超能力,或者需要 变更 超能力的方法,我们必须 重新改造 超人。换句话说就是,改变超能力的同时,我还得重新制造个超人。效率太低了!新超人还没创造完成世界早已被毁灭。

<p>这时,灵机一动的人想到:为什么不可以这样呢?超人的能力可以被随时更换,只需要添加或者更新一个芯片或者其他装置啥的(想到钢铁侠没)。这样的话就不要整个重新来过了。</p>
ログイン後にコピー

对,就是这样的。

我们不应该手动在 “超人” 类中固化了他的 “超能力” 初始化的行为,而转由外部负责,由外部创造超能力模组、装置或者芯片等(我们后面统一称为 “模组”),植入超人体内的某一个接口,这个接口是一个既定的,只要这个 “模组” 满足这个接口的装置都可以被超人所利用,可以提升、增加超人的某一种能力。这种由外部负责其依赖需求的行为,我们可以称其为 “控制反转(IoC)”。

工厂模式,依赖转移!

当然,实现控制反转的方法有几种。在这之前,不如我们先了解一些好玩的东西。

<p>我们可以想到,组件、工具(或者超人的模组),是一种可被生产的玩意儿,生产的地方当然是 &ldquo;工厂(Factory)&rdquo;,于是有人就提出了这样一种模式: <code>工厂模式</code>。</p>
ログイン後にコピー

工厂模式,顾名思义,就是一个类所依赖的外部事物的实例,都可以被一个或多个 “工厂” 创建的这样一种开发模式,就是 “工厂模式”。

スーパーマンのスーパーパワーモジュールを作るために、私たちはたった1つの方法で様々なモジュールを作ることができる工場を作りました:

  1. クラス スーパーモジュールファクトリー

  2. {

  3. public function makeModule($moduleName, $options)

  4. {

  5. スイッチ ($moduleName) {

  6. ケース 「ファイト」: リターン 新しい ファイト($options[0], $options[1]);

  7. ケース 'Force': return new Force($options[0]);

  8. ケース 'ショット': return 新しい ショット($options[0], $options[1], $op [2] ]);

  9. }

  10. }

  11. }

現時点では、スーパーマンは最初からこの工場を使用できます!

  1. クラス スーパーマン

  2. {

  3. 保護されています $power;

  4. public function __construct()

  5. {

  6. //初期化ファクトリー

  7. $factory = new SuperModuleFactory;

  8. // 工場が提供するメソッドで必要なモジュールを製造します

  9. $this->power = $factory->makeModule('Fight', [9, 100]);

  10. // $this->power = $factory->makeModule('Force', [45]);

  11. // $this->power = $factory->makeModule('Shot', [99, 50, 2]);

  12. /*

  13. $this->power = array(

  14. $factory->makeModule('Force', [45]),

  15. $factory->makeModule('ショット', [99, 50, 2])

  16. );

  17. */

  18. }

  19. }

Superman の初期化の開始時に多くのサードパーティ クラスを初期化する必要がなくなり、必要に応じてファクトリ クラスを初期化するだけで済むことがわかります。ただし、new キーワードがそれほど多くないことを除けば、以前とあまり変わらないようです。実際、このクラスを少し変更すると、ファクトリ クラスの本当の意味と価値が理解できるようになります。

  1. クラス スーパーマン

  2. {

  3. 保護されています $power;

  4. public function __construct(array $modules)

  5. {

  6. //初期化ファクトリー

  7. $factory = new SuperModuleFactory;

  8. // 工場が提供するメソッドで必要なモジュールを製造します

  9. foreach ($modules as $moduleName => $moduleOptions) {

  10. $this->power[] = $factory-> makeModule($moduleName, $moduleOptions); }

  11. }

  12. }
  13. //スーパーマンを作成します

  14. $スーパーマン

    =
  15. 新しい

    スーパーマン([

  16. 'ファイト' => [9

    ,
  17. 100

    ], 'ショット' => [99

    ,
  18. 50

    , 2] ]);

    修正の結果は満足のいくものになりました。これで、「スーパーマン」の作成は「スーパーパワー」クラスに依存しなくなります。新しいスーパーパワーを変更または追加する場合は、それを変更するだけです
  19. 。スーパーパワーを拡張するときに、スーパーマンのクラスファイルを再編集する必要がなくなり、非常に簡単になりました。しかし、これはほんの始まりにすぎません。
  20. さらに一歩前進! IoC コンテナの重要なコンポーネントである依存関係の注入です。 「スーパーマン」の「スーパーパワー」への依存から「スーパーマン」の「スーパーパワーモジュール工場」への依存に変わった後、小さなモンスターに対処するのが簡単になります。しかし、ご覧のとおり、依存関係は解消されておらず、もともと複数の外部ソースに依存していたものが、1 つの「工場」への依存になっています。工場で何か問題が発生すると、問題は非常に困難になります。

    <p>其实大多数情况下,工厂模式已经足够了。工厂模式的缺点就是:接口未知(即没有一个很好的契约模型,关于这个我马上会有解释)、产生对象类型单一。总之就是,还是不够灵活。虽然如此,工厂模式依旧十分优秀,并且适用于绝大多数情况。不过我们为了讲解后面的 <code>依赖注入</code> ,这里就先夸大一下工厂模式的缺陷咯。</p>
    
    ログイン後にコピー

    我们知道,超人依赖的模组,我们要求有统一的接口,这样才能和超人身上的注入接口对接,最终起到提升超能力的效果。

    事实上,我之前说谎了,不仅仅只有一堆小怪兽,还有更多的大怪兽。嘿嘿。额,这时候似乎工厂的生产能力显得有些不足 —— 由于工厂模式下,所有的模组都已经在工厂类中安排好了,如果有新的、高级的模组加入,我们必须修改工厂类(好比增加新的生产线):

    1. class SuperModuleFactory

    2. {

    3. public function makeModule($moduleName, $options)

    4. {

    5. switch ($moduleName) {

    6. case 'Fight': return new Fight($options[0], $options[1]);

    7. case 'Force': return new Force($options[0]);

    8. case 'Shot': return new Shot($options[0], $options[1], $options[2]);

    9. // case 'more': .......

    10. // case 'and more': .......

    11. // case 'and more': .......

    12. // case 'oh no! its too many!': .......

    13. }

    14. }

    15. }

    看到没。。。噩梦般的感受!

    <p>其实灵感就差一步!你可能会想到更为灵活的办法!对,下一步就是我们今天的主要配角 &mdash;&mdash; DI (依赖注入)</p>
    
    ログイン後にコピー

    由于对超能力模组的需求不断增大,我们需要集合整个世界的高智商人才,一起解决问题,不应该仅仅只有几个工厂垄断负责。不过高智商人才们都非常自负,认为自己的想法是对的,创造出的超能力模组没有统一的接口,自然而然无法被正常使用。这时我们需要提出一种契约,这样无论是谁创造出的模组,都符合这样的接口,自然就可被正常使用。

    1. interface SuperModuleInterface

    2. {

    3. /**

    4. * 超能力激活方法

    5. *

    6. * 任何一个超能力都得有该方法,并拥有一个参数

    7. *@param array $target 针对目标,可以是一个或多个,自己或他人

    8. */

    9. public function activate(array $target);

    10. }

    <p>上文中,我们定下了一个接口 (超能力模组的规范、契约),所有被创造的模组必须遵守该规范,才能被生产。</p>
    <p>其实,这就是 php 中 <code>接口( interface )</code> 的用处和意义!很多人觉得,为什么 php 需要接口这种东西?难道不是 java 、 C# 之类的语言才有的吗?这么说,只要是一个正常的面向对象编程语言(虽然 php 可以面向过程),都应该具备这一特性。因为一个 <code>对象(object)</code> 本身是由他的模板或者原型 &mdash;&mdash; <code>类 (class)</code> ,经过实例化后产生的一个具体事物,而有时候,实现统一种方法且不同功能(或特性)的时候,会存在很多的类(class),这时候就需要有一个契约,让大家编写出可以被随时替换却不会产生影响的接口。这种由编程语言本身提出的硬性规范,会增加更多优秀的特性。</p>
    <p>虽然有些绕,但通过我们接下来的实例,大家会慢慢领会接口带来的好处。</p>
    
    ログイン後にコピー

    这时候,那些提出更好的超能力模组的高智商人才,遵循这个接口,创建了下述(模组)类:

    1. /**

    2. * X-超能量

    3. */

    4. class XPower implements SuperModuleInterface

    5. {

    6. public function activate(array $target)

    7. {

    8. // 这只是个例子。。具体自行脑补

    9. }

    10. }

    11. /**

    12. * 终极* (就这么俗)

    13. */

    14. class UltraBomb implements SuperModuleInterface

    15. {

    16. public function activate(array $target)

    17. {

    18. // 这只是个例子。。具体自行脑补

    19. }

    20. }

    同时,为了防止有些 “砖家” 自作聪明,或者一些叛徒恶意捣蛋,不遵守契约胡乱制造模组,影响超人,我们对超人初始化的方法进行改造:

    1. class Superman

    2. {

    3. protected $module;

    4. public function __construct(SuperModuleInterface $module)

    5. {

    6. $this->module = $module

    7. }

    8. }

    改造完毕!现在,当我们初始化 “超人” 类的时候,提供的模组实例必须是一个SuperModuleInterface 接口的实现。否则就会提示错误。

    正是由于超人的创造变得容易,一个超人也就不需要太多的超能力,我们可以创造多个超人,并分别注入需要的超能力模组即可。这样的话,虽然一个超人只有一个超能力,但超人更容易变多,我们也不怕怪兽啦!

    <p>现在有人疑惑了,你要讲的 <code>依赖注入</code> 呢?</p>
    <p>其实,上面讲的内容,正是依赖注入。</p>
    
    ログイン後にコピー

    什么叫做 依赖注入

    本文从开头到现在提到的一系列依赖,只要不是由内部生产(比如初始化、构造函数__construct 中通过工厂方法、自行手动 new 的),而是由外部以参数或其他形式注入的,都属于 依赖注入(DI) 。是不是豁然开朗?事实上,就是这么简单。下面就是一个典型的依赖注入:

    1. // 超能力模组

    2. $superModule = new XPower;

    3. // 初始化一个超人,并注入一个超能力模组依赖

    4. $superMan = new Superman($superModule);

    关于依赖注入这个本文的主要配角,也就这么多需要讲的。理解了依赖注入,我们就可以继续深入问题。慢慢走近今天的主角……

    更为先进的工厂 —— IoC 容器!

    刚刚列了一段代码:

    1. $superModule = new XPower;

    2. $superMan = new Superman($superModule);

    读者应该看出来了,手动的创建了一个超能力模组、手动的创建超人并注入了刚刚创建超能力模组。呵呵,手动。

    <p>现代社会,应该是高效率的生产,干净的车间,完美的自动化装配。</p>
    
    ログイン後にコピー

    一群怪兽来了,如此低效率产出超人是不现实,我们需要自动化 —— 最多一条指令,千军万马来相见。我们需要一种高级的生产车间,我们只需要向生产车间提交一个脚本,工厂便能够通过指令自动化生产。这种更为高级的工厂,就是工厂模式的升华 —— IoC 容器

    1. class Container

    2. {

    3. protected $binds;

    4. protected $instances;

    5. public function bind($abstract, $concrete)

    6. {

    7. if ($concrete instanceof Closure) {

    8. $this->binds[$abstract] = $concrete;

    9. } else {

    10. $this->instances[$abstract] = $concrete;

    11. }

    12. }

    13. public function make($abstract, $parameters = [])

    14. {

    15. if (isset($this->インスタンス[$abstract])) {

    16. return $this->インスタンス[$abstract];

    17. }

    18. array_unshift($parameters, $this);

    19. return call_user_func_array($this->binds[$abstract], $parameters);

    20. }

    21. }

    この時、とてもラフな容器が誕生しました。確かに今は非常に初歩的なものですが、それがさらなる改善を妨げるものではありません。ここに焦点を当てて、このコンテナの使用方法を見てみましょう。

    1. // コンテナ(以下、スーパーファクトリー)を作成します

    2. $コンテナ= 新しい コンテナ;

    3. //スーパーマンの制作スクリプトをギガファクトリーに追加します

    4. $container->bind('スーパーマン', function($container, $moduleName) {

    5. return new スーパーマン($container->make($moduleName));

    6. });

    7. //スーパーパワーモジュールの生産スクリプトをスーパーファクトリーに追加します

    8. $container->bind('xpower', function($container) {

    9. 戻る 新しい XPower;

    10. });

    11. // 同上

    12. $コンテナ->バインド('ウルトラボム', 関数($コンテナ) {

    13. 復帰 新しい UltraBomb;

    14. });

    15. // ****************** ゴージャスな分割線************************

    16. //生産開始

    17. $superman_1 = $container->make('superman', ['xpower']);

    18. $superman_2 = $container->make('superman', ['ultrabomb']);

    19. $superman_3 = $container->make('superman', ['xpower']);

    20. // ...随意添加

    看到没?通过最初的 绑定(bind) 操作,我们向 超级工厂 注册了一些生产脚本,这些生产脚本在生产指令下达之时便会执行。发现没有?我们彻底的解除了 超人 与 超能力模组 的依赖关系,更重要的是,容器类也丝毫没有和他们产生任何依赖!我们通过注册、绑定的方式向容器中添加一段可以被执行的回调(可以是匿名函数、非匿名函数、类的方法)作为生产一个类的实例的 脚本 ,只有在真正的 生产(make) 操作被调用执行时,才会触发。

    这样一种方式,使得我们更容易在创建一个实例的同时解决其依赖关系,并且更加灵活。当有新的需求,只需另外绑定一个“生产脚本”即可。

    <p>实际上,真正的 IoC 容器更为高级。我们现在的例子中,还是需要手动提供超人所需要的模组参数,但真正的 IoC 容器会根据类的依赖需求,自动在注册、绑定的一堆实例中搜寻符合的依赖需求,并自动注入到构造函数参数中去。Laravel 框架的服务容器正是这么做的。实现这种功能其实理论上并不麻烦,但我并不会在本文中写出,因为&hellip;&hellip;我懒得写。</p>
    <p>不过我告诉大家,这种自动搜寻依赖需求的功能,是通过 <code>反射(Reflection)</code> 实现的,恰好的,php 完美的支持反射机制!关于反射,php 官方文档有详细的资料,并且中文翻译基本覆盖,足够学习和研究!</p>
    <p>http://php.net/manual/zh/book.reflection.php</p>
    
    ログイン後にコピー

    现在,到目前为止,我们已经不再惧怕怪兽们了。高智商人才集思广益,井井有条,根据接口契约创造规范的超能力模组。超人开始批量产出。最终,人人都是超人,你也可以是哦

    回归正常世界。我们开始重新审视 laravel 的核心。

    现在,我们开始慢慢解读 laravel 的核心。其实,laravel 的核心就是一个 IoC 容器,也恰好是我之前所说的高级的 IoC 容器。

    可以说,laravel 的核心本身十分轻量,并没有什么很神奇很实质性的应用功能。很多人用到的各种功能模块比如 Route(路由)Eloquent ORM(数据库 ORM 组件)Request and Response(请求和响应)等等等等,实际上都是与核心无关的类模块提供的,这些类从注册到实例化,最终被你所使用,其实都是 laravel 的服务容器负责的。

    我们以大家最常见的 Route 类作为例子。大家可能经常见到路由定义是这样的:

    1. Route::get('/', function() {

    2. // bla bla bla...

    3. });

    实际上, Route 类被定义在这个命名空间:Illuminate\Routing\Router,文件vendor/laravel/framework/src/Illuminate/Routing/Router.php

    我们通过打开发现,这个类的这一系列方法,如 getpostany 等都不是静态(static)方法,这是怎么一回事儿?不要急,我们继续。

    服务提供者

    我们在前文介绍 IoC 容器的部分中,提到了,一个类需要绑定、注册至容器中,才能被“制造”。

    对,一个类要被容器所能够提取,必须要先注册至这个容器。既然 laravel 称这个容器叫做服务容器,那么我们需要某个服务,就得先注册、绑定这个服务到容器,那么提供服务并绑定服务至容器的东西,就是 服务提供者(ServiceProvider)

    <p>虽然,绑定一个类到容器不一定非要通过 <code>服务提供者(ServiceProvider)</code> 。</p>
    <p>但是,我们知道,有时候我们的类、模块会有需要其他类和组件的情况,为了保证初始化阶段不会出现所需要的模块和组件没有注册的情况,laravel 将注册和初始化行为进行拆分,注册的时候就只能注册,初始化的时候就是初始化。拆分后的产物就是现在的<code>服务提供者</code>。</p>
    
    ログイン後にコピー

    服务提供者主要分为两个部分,register(注册)boot(引导、初始化),具体参考文档。register 负责进行向容器注册“脚本”,但要注意注册部分不要有对未知事物的依赖,如果有,就要移步至 boot 部分。

    Facade

    我们现在解答之前关于 Route 的方法为何能以静态方法访问的问题。实际上这个问题文档上有写,简单说来就是模拟一个类,提供一个静态魔术方法__callStatic,并将该静态方法映射到真正的方法上。

    我们使用的 Route 类实际上是 Illuminate\Support\Facades\Route 通过 class_alias() 函数创造的 别名 而已,这个类被定义在文件vendor/laravel/framework/src/Illuminate/Support/Facades/Route.php

    我们打开文件一看……诶?怎么只有这么简单的一段代码呢?

    1. php namespace Illuminate\Support\Facades;

    2. /**

    3. * @see \Illuminate\Routing\Router

    4. */

    5. class Route extends Facade {

    6. /**

    7. * Get the registered name of the component.

    8. *

    9. * @return string

    10. */

    11. protected static function getFacadeAccessor()

    12. {

    13. return 'router';

    14. }

    15. }

    其实仔细看,会发现这个类继承了一个叫做 Facade 的类,到这里谜底差不多要解开了。

    上述简单的定义中,我们看到了 getFacadeAccessor 方法返回了一个 route,这是什么意思呢?事实上,这个值被一个 ServiceProvider 注册过,大家应该知道注册了个什么,当然是那个真正的路由类!

    <p>有人会问,Facade 是怎么实现的。我并不想说得太细,一个是我懒,另一个原因就是,自己发现一些东西更容易理解,并不容易忘记。很多细节我已经说了,建议大家自行去研究。</p>
    
    ログイン後にコピー

    至此,我们已经讲的差不多了。

    和平!我们该总结总结了!

    无论如何,世界和平了。

    这里要总结的内容就是,其实很多事情并不复杂,怕的是复杂的理论内容。我觉得很多东西一旦想通也就那么回事儿。很多人觉得 laravel 这不好那不好、这里难哪里难,我只能说,laravel 的确不是一流和优秀的框架,说 laravel 是一流、优秀的框架的人,不是 laravel 的粉丝那么就是跟风炒作。Laravel 最大的特点和优秀之处就是使用了很多 php 比较新(实际上并不新)的概念和技术(也就一堆语法糖)而已。因此 laravel 的确符合一个适宜学习的框架。Laravel 的构思的确和其他框架有很大不同,这也要求学习他的人必须熟练 php,并 基础扎实!如果你觉得学 laravel 框架十分困难,那么原因只有一个:你 php 基础不好。

    另外,善于利用命名空间和面向对象的诸多特性,去追寻一些东西,你会发现,原来这一切这么容易。

     

     

     

    www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/1098071.html技術記事未使用のコード、依存関係の注入などを見て IOC コンテナを分析し、未使用のコードを見て IOC コンテナを理解する /* * * スーパー パワーを持つスーパーマン インスタンスを生成して IOC コンテナを理解する*/ // スーパー パワーモジュールインターフェース ...
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 Apr 05, 2025 am 12:04 AM

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

セッションのハイジャックはどのように機能し、どのようにPHPでそれを軽減できますか? セッションのハイジャックはどのように機能し、どのようにPHPでそれを軽減できますか? Apr 06, 2025 am 12:02 AM

セッションハイジャックは、次の手順で達成できます。1。セッションIDを取得します。2。セッションIDを使用します。3。セッションをアクティブに保ちます。 PHPでのセッションハイジャックを防ぐための方法には次のものが含まれます。1。セッション_regenerate_id()関数を使用して、セッションIDを再生します。2。データベースを介してストアセッションデータを3。

確固たる原則と、それらがPHP開発にどのように適用されるかを説明してください。 確固たる原則と、それらがPHP開発にどのように適用されるかを説明してください。 Apr 03, 2025 am 12:04 AM

PHP開発における固体原理の適用には、次のものが含まれます。1。単一責任原則(SRP):各クラスは1つの機能のみを担当します。 2。オープンおよびクローズ原理(OCP):変更は、変更ではなく拡張によって達成されます。 3。Lischの代替原則(LSP):サブクラスは、プログラムの精度に影響を与えることなく、基本クラスを置き換えることができます。 4。インターフェイス分離原理(ISP):依存関係や未使用の方法を避けるために、細粒インターフェイスを使用します。 5。依存関係の反転原理(DIP):高レベルのモジュールと低レベルのモジュールは抽象化に依存し、依存関係噴射を通じて実装されます。

システムの再起動後にUnixSocketの権限を自動的に設定する方法は? システムの再起動後にUnixSocketの権限を自動的に設定する方法は? Mar 31, 2025 pm 11:54 PM

システムが再起動した後、UnixSocketの権限を自動的に設定する方法。システムが再起動するたびに、UnixSocketの許可を変更するために次のコマンドを実行する必要があります:sudo ...

phpstormでCLIモードをデバッグする方法は? phpstormでCLIモードをデバッグする方法は? Apr 01, 2025 pm 02:57 PM

phpstormでCLIモードをデバッグする方法は? PHPStormで開発するときは、PHPをコマンドラインインターフェイス(CLI)モードでデバッグする必要がある場合があります。

PHPでの後期静的結合を説明します(静的::)。 PHPでの後期静的結合を説明します(静的::)。 Apr 03, 2025 am 12:04 AM

静的結合(静的::) PHPで後期静的結合(LSB)を実装し、クラスを定義するのではなく、静的コンテキストで呼び出しクラスを参照できるようにします。 1)解析プロセスは実行時に実行されます。2)継承関係のコールクラスを検索します。3)パフォーマンスオーバーヘッドをもたらす可能性があります。

フレームワークセキュリティ機能:脆弱性から保護します。 フレームワークセキュリティ機能:脆弱性から保護します。 Mar 28, 2025 pm 05:11 PM

記事では、入力検証、認証、定期的な更新など、脆弱性から保護するためのフレームワークの重要なセキュリティ機能について説明します。

See all articles