Laravel思维导图之Laravel核心概念

澳门新葡亰娱乐在线 3

Laravel 中的使用

定义一个服务提供器:

use IlluminateSupportServiceProvider;

class FooServiceProvider extends ServiceProvider {

    public function register()
    {
        $this->app->bind('foo', function()
        {
            return new Foo;
        });
    }

}

这个代码也不难理解,就是申明一个服务提供器,这个服务提供器有一个 register的方法。这个方法实现了我们上面讲到的依赖注入。

当我们执行下面代码:

App::register('FooServiceProvider');

我们就完成一个注入了。但是这个还是得手动写,所以怎么让 Laravel
自己来做这事儿呢?

我们只要在 app/config/app.php 中的 providers 数组里面增加一行:

'providers' => [
    …
       ‘FooServiceProvider’,
],

这样我们就可以使用 App::make(‘foo’) 来实例化一个类了。

你不禁要问了,这么写也太难看了吧?莫慌,有办法。

服务容器是 Laravel 的核心,是一个 IoC
容器,是管理类依赖和运行依赖注入的有力工具。

Laravel 中的使用

我们使用的大部分核心类都是基于门面模式实现的。例如:

$value = Cache::get('key');

这些静态调用实际上调用的并不是静态方法,而是通过 PHP 的魔术方法__callStatic() 讲请求转到了相应的方法上。

那么如何讲我们前面写的服务提供器也这样使用呢?方法很简单,只要这么写:

use IlluminateSupportFacadesFacade;

class Foo extends Facade {

    protected static function getFacadeAccessor() { return ‘foo’; }

}

这样我们就可以通过 Foo::test() 来调用我们之前真正的 FooBar 类的方法了。

如何从服务容器解析出对象?

绑定后可以从服务容器中解析出对象才能够使用。解析方法包括:

  • 通过 make 方法,接收一个你想要解析的类或者接口
  • 通过数组方式从容器中解析对象
  • 自动注入

控制反转(Inversion of Control)

Laravel核心概念

别名(Alias)

有时候我们可能将 Facade 放在我们扩展库中,它有比较深的命名空间,如:LibraryMyClassFoo。这样导致使用起来并不方便。Laravel
可以用别名来替换掉这么长的名字。

我们只要在 app/config/app.php 中 aliases 下增加一行即可:

'aliases' => [
    …
    'Foo' => ‘LibraryMyClassFoo’,
],

这样它的使用就由 LibraryMyClassFoo::test() 变成 Foo::test() 了。

自动注入实例

下面的例子中,在控制器的构造函数中对应用程序定义的 Repository
使用类型提示。这样 Repository 实例会被自动解析并注入到类中:

<?php

namespace AppHttpControllers;

use AppUsersRepository as UserRepository;

class UserController extends Controller
{
    /**
     * user repository 实例。
     */
    protected $users;

    /**
     * 控制器构造方法。
     *
     * @param  UserRepository  $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }

    /**
     * 显示指定 ID 的用户信息。
     *
     * @param  int  $id
     * @return Response
     */
    public function show($id)
    {
        //
    }
}

Laravel 中的使用

注入一个类:

App::bind('foo', function($app)
{
    return new FooBar;
});

这个例子的意思是创建一个别名为 foo 的类,使用时实际实例化的是 FooBar

使用这个类的方法是:

$value = App::make('foo');

$value 实际上是 FooBar 对象。

如果希望使用单例模式来实例化类,那么使用:

App::singleton('foo', function()
{
    return new FooBar;
});

澳门新葡亰娱乐在线,这样的话每次实例化后的都是同一个对象。

注入类的更多例子可以看 Laravel 官网

你可能会疑问上面的代码应该写在哪儿呢?答案是你希望他们在哪儿运行就写在哪儿。0
—— 0 知道写哪儿还用来看这种基础文章么!

0x00 服务容器

Laravel 的核心就是一个 IoC
容器,该容器提供了整个框架中需要的一系列服务。

IoC(Inversion Of
Control)控制反转
,是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。IoC
容器会根据类的依赖需求,自动在注册、绑定的一堆实例中搜寻符合的依赖需求,并自动注入到构造函数参数中去。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。这就是依赖注入(Dependency
Injection,
DI)
。依赖注入实质上是指:类的依赖通过构造器或在某些情况下通过「setter」方法进行「注入」。

澳门新葡亰娱乐在线 1

Laravel服务容器

总结

所以有了控制反转(Inversion of
Control)和门面模式(Facade),实际还有服务提供器(Service
Providers)和别名(Alias),我们创建自己的类库和扩展 Laravel
都会方便很多。

这里总结一下创建自己类库的方法:

  1. 在 app/library/MyFoo 下创建类 MyFoo.php
  2. 在 app/library/MyFoo/providers 下创建 MyFooServiceProvider.php
  3. 在 app/library/MyFoo/facades 下创建 MyFooFacade.php
  4. 在 app/config/app.php 中添加 providers 和 aliases

如何实现与服务容器的绑定?

几乎所有服务容器的绑定都是在服务提供者中进行的。在服务提供者内部,可以通过
$this->app 来访问容器的实例。

绑定的方式包括:

  • 简单绑定
  • 绑定一个单例
  • 绑定实例
  • 绑定接口到实现
  • 情境绑定
  • 绑定包括原始数据在内的初始数据
  • 标记

其中,标记能够针对某种类别的所有做绑定。

服务提供器 (Service Providers)

为了让依赖注入的代码不至于写乱,Laravel 搞了一个 服务提供器(Service
Provider)的东西,它将这些依赖聚集在了一块,统一申明和管理,让依赖变得更加容易维护。

服务提供者则提供服务并绑定服务至服务容器。是所有 Laravel
应用程序引导启动的中心所在。

这两个概念对于 Laravel
的使用者来说应该并不陌生,尤其是当你希望扩展或者替换 Laravel
核心库的时候,理解和合理使用它们可以极大提升 Laravel
的战斗力。这里以创建一个自己的 ServiceProvider 为例理解 Inversion of
Control 和 Facade 在 Laravel 中的应用。

0x01 服务提供者

Laravel 中,包括应用程序,以及所有的 Laravel
核心服务,都是通过服务提供者引导启动的。所谓的「引导启动」指的是注册事务,包括注册服务容器绑定,事件监听器,中间件,甚至路由。

澳门新葡亰娱乐在线 2

Laravel服务提供者

所有服务提供者都需要继承 IlluminateSupportServiceProvider
类。大多数服务提供者都包含 register 和 boot 方法。register
方法中,只能将事务绑定到 服务容器。不应该在 register
方法中尝试注册任何事件监听器,路由或者任何其他功能。可以为服务提供者的
boot 方法设置类型提示。服务容器会自动注入需要的任何依赖。boot
方法将在所有其他服务提供者均已注册之后调用。

所有服务提供者都在 config/app.php
配置文件中注册。可以选择推迟服务提供者的注册,直到真正需要注册绑定时,这样可以提供应用程序的性能。

什么是 IoC

控制反转(Inversion of
Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency
Injection,简称DI),还有一种方式叫“依赖查找”(Dependency
Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。
— 维基百科

简单说来,就是一个类把自己的的控制权交给另外一个对象,类间的依赖由这个对象去解决。依赖注入属于依赖的显示申明,而依赖查找则是通过查找来解决依赖。

Facades 工作原理

在 Laravel 应用中,一个 facade
就是一个提供访问容器中对象的类。其中核心的部件就是 Facade 类。不管是
Laravel 自带的 Facades ,还是用户自定义的 Facades ,都继承自
IlluminateSupportFacadesFacade 类。

Facade 基类使用 __callStatic() 魔术方法在你的 Facades
中延迟调用容器中对应对象的方法,在下面的例子中,调用了 Laravel
的缓存系统。在代码里,我们可能认为是 Cache 类中的静态方法 get 被调用了:

<?php
namespace AppHttpControllers;

use IlluminateSupportFacadesCache;
use AppHttpControllersController;

class UserController extends Controller
{
    /**
     * 显示给定用户的大体信息。
     *
     * @param  int  $id
     * @return Response
     */
    public function showProfile($id)
    {
        $user = Cache::get('user:'.$id);

        return view('profile', ['user' => $user]);
    }
}

注意在代码的最上面,我们导入的是 Cache facade 。这个 facade
其实是我们获取底层 IlluminateContractsCacheFactory
接口实现的一个代理。我们通过这个 facade 调用的任何方法,都会被传递到
Laravel 缓存服务的底层实例中。

如果我们看一下 IlluminateSupportFacadesCache
这个类,你会发现类中根本没有 get 这个静态方法:

class Cache extends Facade
{
    /**
     * 获取组件在容器中注册的名称。
     *
     * @return string
     */
    protected static function getFacadeAccessor() { return 'cache'; }
}

其实,Cache facade 是继承了 Facade 基类,并且定义了 getFacadeAccessor()
方法。这个方法的作用是返回服务容器中对应名字的绑定内容。当用户调用 Cache
facade 中的任何静态方法时, Laravel 会解析到服务容器中绑定的键值为 cache
实例对象,并调用这个对象对应的方法(在这个例子中就是 get 方法)。

门面模式(Facade)

为了让 Laravel 中的核心类使用起来更加方便,Laravel实现了门面模式。

外觀模式(Facade
pattern),是軟件工程中常用的一種軟件設計模式,它為子系統中的一組接口提供一個統一的高層接口,使得子系統更容易使用。
— 维基百科

澳门新葡亰娱乐在线 3

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章

网站地图xml地图