laravel核心

laravel服务提供者与门面的使用

2018-09-03  本文已影响3人  云龙789

推荐网站https://www.codecasts.com/
具体哪个视频我忘了,视频是收费的

<?php

namespace App;
class Billing{
    public function test()
    {
        return 'test';
    }
}
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class BillingProvider extends ServiceProvider
{
   
    public function boot()
    {
        //
    }

   // 此处我们绑定Billing 函数
    public function register()
    {
        $this->app->bind('billing',function (){
            return new \App\Billing();
        });
// 框架中很多时候,都会使用 Billing::class 作为 bind()的第一个参数,比如最常用的 Request ,
// 此处我们为了直观演示,使用一个不一样的别名。
    }
}

//    $res = app('billing')->test();
//    $res = app()['billing']->test();
    $res = app()->make('billing')->test();
    dd($res);
<?php
namespace App;
use Illuminate\Support\Facades\Facade;

class Bill extends Facade {
    protected static function getFacadeAccessor()
    {
        return 'billing'; // TODO: Change the autogenerated stub
    }
}

dd(Bill::test())

Facade 工作原理

Facade 基类使用了 __callStatic() 魔术方法,直到对象从容器中被解析出来后,才会进行调用。比如以上的例子,

   public static function __callStatic($method, $args)
    {
       // $instance 得到的其实是 BillingProvider中register方法里绑定的 new \App\Billing() 实例
        $instance = static::getFacadeRoot();

        if (! $instance) {
            throw new RuntimeException('A facade root has not been set.');
        }

        return $instance->$method(...$args);
    }

    public static function getFacadeRoot()
    {
        return static::resolveFacadeInstance(static::getFacadeAccessor());
    }

/**
     * Get the registered name of the component.
     *
     * @return string
     *
     * @throws \RuntimeException
     */
    protected static function getFacadeAccessor()
    {
        throw new RuntimeException('Facade does not implement getFacadeAccessor method.');
    }
注意,因为我们在实例的类中直接重写了方法,所以执行的将会是以下代码
 protected static function getFacadeAccessor()
    {
        return 'billing';
    }
     protected static function resolveFacadeInstance($name)
    {
        if (is_object($name)) {
            return $name;
        }

        if (isset(static::$resolvedInstance[$name])) {
            return static::$resolvedInstance[$name];
        }

        return static::$resolvedInstance[$name] = static::$app[$name];
    }
 /**
     * Resolve the facade root instance from the container.
     *
     * @param  string|object  $name
     * @return mixed
     */
    protected static function resolveFacadeInstance($name)
    {
        if (is_object($name)) {
            return $name;
        }

        if (isset(static::$resolvedInstance[$name])) {
            return static::$resolvedInstance[$name];
        }

        return static::$resolvedInstance[$name] = static::$app[$name];
    }
/**
     * The resolved object instances.
     *
     * @var array
     */
    protected static $resolvedInstance;

if (! function_exists('app')) {
    /**
     * Get the available container instance.
     *
     * @param  string  $abstract
     * @param  array   $parameters
     * @return mixed|\Illuminate\Foundation\Application
     */
    function app($abstract = null, array $parameters = [])
    {
        if (is_null($abstract)) {
            return Container::getInstance();
        }

        return Container::getInstance()->make($abstract, $parameters);
    }
}

 public function make($abstract, array $parameters = [])
    {
        return $this->resolve($abstract, $parameters);
    }

  protected function resolve($abstract, $parameters = [])
    {
        $abstract = $this->getAlias($abstract);

       ....

        return $object;
    }


所以app()的第一个参数其实是抽象类

还有一种实现实时 Facade 的简单方式,就是直接在将要实现的类的原命名空间前,加上Facades,直接使用手册里的例子吧

<?php

namespace App;

use Facades\App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;

class Podcast extends Model
{
    /**
     * 发布 Podcast.
     *
     * @return void
     */
    public function publish()
    {
        $this->update(['publishing' => now()]);

        Publisher::publish($this);
    }
}

推荐laravel空类继承总是继承SPL的原因

上一篇 下一篇

猜你喜欢

热点阅读