Factory 前面的 Facade 实现 class Laravel 5.4
Implementation of Facade in front of Factory class Laravel 5.4
对于某些上下文 - 今天早些时候我正在努力弄清楚如何实现类似于 Cache 的外观 - 我可以在其中设置提供程序(如 disk()),但在未提供时也有一个通用的回退提供程序.
现在,我的基本基础架构可以正常工作,但我认为我的实现很糟糕。调用 default() 或 provider() 就很糟糕。但是,我缺少一个概念或一些东西来填补这里的空白。
这是我所做的。
// 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()...
我知道 facade 是静态的 class,但是是否可以将其设置为我可以像这样进行调用的方式?
SMS::send($args);
// When I want to use another gateway
SMS::provider('nexmo')->send($args);
您可以在您的短信工厂class中使用__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 class 不应该有静态方法,因为可以通过 facade 访问静态方法。
对于某些上下文 - 今天早些时候我正在努力弄清楚如何实现类似于 Cache 的外观 - 我可以在其中设置提供程序(如 disk()),但在未提供时也有一个通用的回退提供程序.
现在,我的基本基础架构可以正常工作,但我认为我的实现很糟糕。调用 default() 或 provider() 就很糟糕。但是,我缺少一个概念或一些东西来填补这里的空白。
这是我所做的。
// 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()...
我知道 facade 是静态的 class,但是是否可以将其设置为我可以像这样进行调用的方式?
SMS::send($args);
// When I want to use another gateway
SMS::provider('nexmo')->send($args);
您可以在您的短信工厂class中使用__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 class 不应该有静态方法,因为可以通过 facade 访问静态方法。