2017-04-04 20 views
0

일부 컨텍스트에서는 이전처럼 캐시와 비슷한 외관을 구현하는 방법을 알아 내려고 노력했지만 (disk()와 같은) 공급자를 설정할 수 있었지만, 제공되지 않을 경우 일반 폴백 공급자.Factory 클래스 앞에 Facade 구현 Laravel 5.4

이제 기본 인프라가 작동하지만, 구현이 불쾌하다고 생각합니다. 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, 
     ]); 
    } 
} 

...

나는 외관의 정적 클래스 역할을하지만이 가능 같은 방법으로 그것을 설정하는 것을 이해 내가 이렇게 전화 할 수 있다고?

SMS::send($args); 

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

제공자 클래스에서 다른 제공자로 변경할 수있는 방법이 있습니까? –

+0

서비스 프로 바이더는 팩토리를 바인드합니다. 그래서 현재 sms.php 설정 파일에 'new-gateway'가 정의되어 있다면 SMS :: provider ('new-gateway')로 게이트웨이를 전환 할 수 있습니다. 그 부분은 모두 작동합니다 – Trent

답변

1

당신은 당신의 SMS 공장 클래스의 __call 방법을 사용할 수 있으며, 그에 따라 변경해야합니다 : 정적 방법은 외관을 통해 액세스 할 수 있습니다대로 SMSFactory 클래스는 정적 메서드가 없어야

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); 
    } 
} 

.

+0

마법 방법은 정적으로 facade를 호출 할 수 있음을 의미합니다. 그러면 새 인스턴스를 생성 한 다음 해당 인스턴스에서 명령을 실행합니다. 이 코드를 코드에 넣으면 정의되지 않은 메서드 인 SMSFactory :: send()가 호출됩니다. 컨트롤러에서 SMS를 실행합니다 :: send ('Testing'); – Trent

+0

메소드가 존재하지 않을 때 call_user_func_array에 주목했습니다. 함수 이름을 인스턴스로 전달하지 않아서 [$ default, $ name], $ arguments -로 변경되었지만 여전히 문제가 해결되지 않았습니다. – Trent

+0

OK - 이 함수는 심지어 호출되지 않습니다. (PHP7) ... – Trent