Php Laravel存储库模型中的API调用

Php Laravel存储库模型中的API调用,php,api,laravel,laravel-5,repository-pattern,Php,Api,Laravel,Laravel 5,Repository Pattern,我正在开发一个web应用程序,其中我将使用第三方API集成(支付网关、SMS供应商、mailchimp等电子邮件服务、其他外部API)。我的应用程序将具有存储库模式,该模式将具有与我的每个模型关联的存储库,我的控制器将利用存储库功能 现在,我所有的API集成都从何而来?我应该将所有API集成保存在一个存储库中吗 例如: 如果我有一个SMS提供商Valuefirst,我的Laravel存储库设计是什么样子的 我的短信接口 My ValueFirst(SMS提供商)存储库 假设我有一个服务提供者类,

我正在开发一个web应用程序,其中我将使用第三方API集成(支付网关、SMS供应商、mailchimp等电子邮件服务、其他外部API)。我的应用程序将具有存储库模式,该模式将具有与我的每个模型关联的存储库,我的控制器将利用存储库功能

现在,我所有的API集成都从何而来?我应该将所有API集成保存在一个存储库中吗

例如:

如果我有一个SMS提供商Valuefirst,我的Laravel存储库设计是什么样子的

我的短信接口 My ValueFirst(SMS提供商)存储库 假设我有一个服务提供者类,在该类中我完成了接口和存储库的绑定,那么我的控制器将是这样的

短信控制器 我的问题

  • 这是使用存储库模式进行API集成的正确方法吗
  • ValueFirst存储库中是否发生了与任何数据库活动相关的任何事件?如果我想在ValueFirst的API响应之后更新记录,我是否在存储库中进行更新
  • 如果是这样,有人能告诉我模型交互是如何从存储库中发生的吗
  • 现在,如果我需要在ValueFirst或任何其他供应商之间进行选择,这是如何实现的?如何从控制器执行此操作
  • 我将使用这个项目作为我的应用程序的框架


    请帮我做这个设计,我对Laravel/repository模式还比较陌生。努力学习。TIA:)

    我觉得你的方法很好,但我还有一些地方需要改进

    首先,我会让
    ValueFirstRepository
    类只负责管理您的SMS API,并注入一个特定的存储库类(
    SmsRepository
    ),通过eloquent(如果您不需要存储库,则仅使用模型)与DB交互

    这里重要的一点是保持在一个类中管理API的责任和在另一个类中与DB交互的责任:

    ValueFirstRepository

    class ValueFirstRepository implements ISmsProvider 
    {
        //INJECT REPOSITORY CLASS TO INTERACT WITH DB
        public function __construct(SmsRepository $smsRepo )
        {
            $this->smsRepo = $smsRepo;    
        }
    
        //this method will be called from your controller
        public function sendSMS($mobieNo,$msg)
        {
           //API CALL
            $info = this->sendSMSAPI($mobieNo,$msg);
    
           //DB CALL
            $this->smsRepo->save( $info );
    
           // Any file logs
        }
    
        //this will actually interact with the API
        protected function sendSMSAPI($mobieNo,$msg)
        {
           //API Call to ValueFirst SMS provider
        }
    
    }
    
    此解决方案的一个小变体是使用事件,在发送sms时在
    ValueFirstRepository
    类中触发事件,并对该事件做出响应,实现一些监听器,这些监听器将执行与事件相关的其他操作

    另一种替代解决方案是直接在控制器中处理步骤:

    短信控制器

    //INJECT THE DEPENDECIES IN YOUR CONTROLLER
    public function __construct(ISmsProvider $sms, SmsRepository $smsRepo )
    {
        $this->sms = $sms;
        $this->smsRepo = $smsRepo;
    }
    
    public function sendSMS()
    {
        //send SMS
        $mobileNo = '9999999999';
        $msg = 'Hello World!';
        $info= $this->sms->sendSMS($mobileNo,$msg);
    
        //use the model to save data
        this->$smsRepo->save($info); 
    } 
    
    这一次,
    SmsRepository
    的依赖关系将被注入控制器中,而不是
    ValueFirstRepository
    类,控制器的方法将稍微大一些,但这取决于您决定适合您的最佳方式

    对于最后一个问题:如果您想更改供应商提供商,您可以使用Laravel的功能通过
    bind
    方法:

    App::bind( App\ISmsProvider::class , App\ValueFirstRepository::class );
    
    这将在请求特定接口时告知laravel wich类inject。因此,在这种情况下,当请求
    ISmsProvider
    接口时,Laravel将自动注入
    ValueFirstRepository
    具体实例

    如果要更改供应商,只需将行更改为:

    App::bind( App\ISmsProvider::class , App\AnotherSMSVendorRepository::class ); 
    

    并且将注入
    另一个smsvendorpository
    类,而不是
    ValueFirstRepository

    ,感谢您的详细解释。我还想知道在这两个流程之间,服务从何而来?除了存储库,服务的界面在哪里。在上面的例子中,你能给我一个用例的概念吗?@user34305:以
    ValueFirstRepository
    类为例:我们可以将它命名为“服务”而不是“存储库”,因为它是一个用于与SMS API交互的服务类。“repository”一词更多地用于表示数据库上的抽象层。事实上,进行
    App::bind
    调用的一个好地方是为sms服务提供绑定的服务提供商classa服务也可以是一个Laravel内部服务类:一个用于handle DB连接的类,一个用于记录器等的类。。几乎任何通过数据库注册的类都是两个不同的概念:存储库是一种设计,您可以使用一个类在数据库(在我们的例子中是sms DB实体)上创建一个抽象层。服务是一个宽泛的术语,它几乎包括应用程序的任何类型的服务类。如果您想在Laravel中找到更多关于谷歌服务和存储库的搜索示例,并检查它们是如何使用的感谢Moppo回答所有查询
    //INJECT THE DEPENDECIES IN YOUR CONTROLLER
    public function __construct(ISmsProvider $sms, SmsRepository $smsRepo )
    {
        $this->sms = $sms;
        $this->smsRepo = $smsRepo;
    }
    
    public function sendSMS()
    {
        //send SMS
        $mobileNo = '9999999999';
        $msg = 'Hello World!';
        $info= $this->sms->sendSMS($mobileNo,$msg);
    
        //use the model to save data
        this->$smsRepo->save($info); 
    } 
    
    App::bind( App\ISmsProvider::class , App\ValueFirstRepository::class );
    
    App::bind( App\ISmsProvider::class , App\AnotherSMSVendorRepository::class );