【问题标题】:Implementation of Facade in front of Factory class Laravel 5.4Facade在Factory类Laravel 5.4前面的实现
【发布时间】:2017-08-29 05:46:06
【问题描述】:

在某些情况下 - 今天早些时候我一直在努力弄清楚如何实现类似于 Cache 的外观 - 我可以在其中设置一个提供程序(如 disk()),但在没有提供时也有一个通用的后备提供程序。

现在,我的基本基础架构可以正常工作,但我认为我的实现很糟糕。调用 default() 或 provider() 会很臭。但是,这里有一个概念或我缺少的东西来填补空白。

Implementing similar functionality to Cache::disk('x') in Laravel

这是我所做的。

// Factories\SMSFactory.php

namespace App\Factories;

use App\IError;


class SMSFactory
{
    public static function default()
    {
        $defaultProvider = config('sms.default_provider');
        return self::provider($defaultProvider);
    }

    public static function provider($providerId)
    {
        $providerClass = config('sms.' . $providerId);

        if (class_exists($providerClass))
        {
            return (new $providerClass);
        }

        return new class implements IError {

        };
    }

}

// sms.php (config)

return [
    /**
     * Set the default SMS provider for the application
     */
    'default_provider' => 'smsglobal',

    /**
     * Map the SMS provider to a class implementation
     */
    'smsglobal' => 'App\SMSGlobal\SMSGlobal',
];

// Providers\SMSServiceProvider.php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;


class SMSServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register the application services.
     *
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind('sms', 'App\Factories\SMSFactory');
    }
}

// Facades\SMS.php

namespace App\Facades;

use Illuminate\Support\Facades\Facade;

class SMS extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'sms';
    }
}


// app.php

App\Providers\SMSServiceProvider::class,

# and in aliases

'SMS' => App\Facades\SMS::class,


// Controllers/TestController.php


namespace App\Http\Controllers\TestController;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

use App\Facades\SMS;


class TestController extends Controller
{
    public function sendSMS($destination, $message)
    {
        $data = $request->all();

        return SMS::default()->send([
            'destination' => $destination,
            'message' => $message,
        ]);
    }
}

真正困扰我的是必须始终使用 default()...

我知道外观是一个静态类,但是否可以将其设置为我可以进行这样的调用?

SMS::send($args);

// When I want to use another gateway
SMS::provider('nexmo')->send($args);

【问题讨论】:

  • 在您的提供者类中,您有办法更改为不同的提供者吗?
  • 服务提供者绑定工厂。所以我目前可以通过 SMS::provider('new-gateway') 切换网关,只要在 sms.php 配置文件中定义了 'new-gateway'。那部分一切正常

标签: php laravel laravel-5 factory laravel-facade


【解决方案1】:

您可以在 SMS Factory 类中使​​用__call 方法,并且必须进行相应更改:

class SMSFactory
{
    public function default()
    {
        $defaultProvider = config('sms.default_provider');

        return $this->provider($defaultProvider);
    }

    public function provider($providerId)
    {
        $providerClass = config('sms.' . $providerId);

        if (class_exists($providerClass))
        {
            return (new $providerClass);
        }

        return new class implements IError {

        };
    }

    public function __call($name, $arguments)
    {
        if (!method_exists($this, $name)) {
            $object = [$this->default(), $name];
        } else {
            $object = [$this, $name];
        }

        return call_user_func_array($object, $arguments);
    }
}

SMSFactory 类不应该有静态方法,因为静态方法可以通过外观访问。

【讨论】:

  • 所以魔术方法意味着我可以对外观进行任何静态方法调用,这将尝试生成一个新实例,然后在该实例上运行命令。当我把它放到我的代码中时,它告诉我调用未定义的方法 SMSFactory::send()。从控制器我运行 SMS::send('Testing');
  • 我还注意到 call_user_func_array 当方法不存在时没有将函数名传递给实例,所以我将其更改为 [$default, $name], $arguments - 但仍然没有解决问题
  • 似乎 - 正在调用魔法方法 - 在 Facade.php 的第 221 行引发错误 - 现在要检查一下
  • 看看我更新的答案。工厂类不应该有静态方法,因为外观使用的是静态方法。我认为这个更新答案对你有用
  • 小编辑 $object = [$this->default(), $method] 一切都很好!如果您可以快速更新,那么我可以接受您的回答 - 以防其他人与之抗争。谢谢老哥!
猜你喜欢
  • 2013-06-24
  • 1970-01-01
  • 2017-10-22
  • 1970-01-01
  • 2018-05-12
  • 1970-01-01
  • 2016-07-11
  • 2018-08-11
  • 1970-01-01
相关资源
最近更新 更多