1

I need to create an interface to send SMS with multiple providers.

I have create an SMSInterface which contains all the method available to send sms.
Now I have created an abstract class which implements the interfaces:

AbstractSMS.php

<?php

namespace ChristianGiupponi\LaravelSMS\Repositories;

class AbstractSMS implements SMSInterface {

    public function getBalance()
    {
        // TODO: Implement getBalance() method.
    }

    public function getName()
    {
        // TODO: Implement getName() method.
    }

    public function setApiKeys( array $keys )
    {
        // TODO: Implement setApiKeys() method.
    }

    public function to( array $numbers )
    {
        // TODO: Implement to() method.
    }

    public function from( $from )
    {
        // TODO: Implement from() method.
    }

    public function text( $text )
    {
        // TODO: Implement text() method.
    }

    public function send()
    {
        // TODO: Implement send() method.
    }
}

Now for each SMS service I have create a class which extends AbstractSMS:

Nexmo.php

<?php

namespace ChristianGiupponi\LaravelSMS\Repositories\Nexmo;

use ChristianGiupponi\LaravelSMS\Repositories\AbstractSMS;

class Nexmo extends AbstractSMS {

   public function getBalance(){
       return "22";
   }

}

I have also created a service provider to bind the interface to the class based on the config file:

<?php

namespace ChristianGiupponi\LaravelSMS\Providers;

use Illuminate\Support\ServiceProvider;

class LaravelSMSServiceProvider extends ServiceProvider {

    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        /**
         *  Publish config filea
         */
        $this->publishes( [
            __DIR__ . '/Config/sms.php' => config_path( 'sms.php' ),
        ] );
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->call( [
            $this,
            'registerSMSService'
        ] );
    }

    /**
     *  Register SMS Service
     */
    public function registerSMSService()
    {
        $supportedService = config( 'sms.supported' );
        $defaultService   = config( 'sms.default' );

        $service = ( in_array( $defaultService, $supportedService ) )
            // if the selected one is supported we can use it
            ? $defaultService
            // otherwise just use the system default
            : 'nexmo';

        $service = studly_case( $service );

        // Bind the service
        $this->app->bind( 'ChristianGiupponi\LaravelSMS\Repositories\AbstractSMS', "ChristianGiupponi\LaravelSMS\Repositories\\{$service}\\{$service}" );
    }
}

Then I have created the facade:

<?php

namespace ChristianGiupponi\LaravelSMS\Facades;

use Illuminate\Support\Facades\Facade;

class SMS extends Facade{

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor() { return 'abstractsms'; }
}

I have also register the provider and the facada in app.php.
In routes.php I added a simple call:

Route::get('saldo', function(){
    return \ChristianGiupponi\LaravelSMS\Facades\SMS::getBalance();
});

But I get:

ReflectionException in Container.php line 734: Class abstractsms does not exist

With the stack trace:

in Container.php line 734
at ReflectionClass->__construct('abstractsms') in Container.php line 734
at Container->build('abstractsms', array()) in Container.php line 629
at Container->make('abstractsms', array()) in Application.php line 697
at Application->make('abstractsms') in Container.php line 1178
at Container->offsetGet('abstractsms') in Facade.php line 151
at Facade::resolveFacadeInstance('abstractsms') in Facade.php line 120
at Facade::getFacadeRoot() in Facade.php line 207
at Facade::__callStatic('getBalance', array()) in routes.php line 19
at RouteServiceProvider->{closure}()
at call_user_func_array(object(Closure), array()) in Route.php line 158
at Route->runCallable(object(Request)) in Route.php line 137
at Route->run(object(Request)) in Router.php line 724
at Router->Illuminate\Routing\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 52
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in VerifyCsrfToken.php line 64
at VerifyCsrfToken->handle(object(Request), object(Closure))
at call_user_func_array(array(object(VerifyCsrfToken), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in ShareErrorsFromSession.php line 49
at ShareErrorsFromSession->handle(object(Request), object(Closure))
at call_user_func_array(array(object(ShareErrorsFromSession), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in StartSession.php line 62
at StartSession->handle(object(Request), object(Closure))
at call_user_func_array(array(object(StartSession), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in AddQueuedCookiesToResponse.php line 37
at AddQueuedCookiesToResponse->handle(object(Request), object(Closure))
at call_user_func_array(array(object(AddQueuedCookiesToResponse), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in EncryptCookies.php line 59
at EncryptCookies->handle(object(Request), object(Closure))
at call_user_func_array(array(object(EncryptCookies), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
at Pipeline->Illuminate\Routing\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 102
at Pipeline->then(object(Closure)) in Router.php line 726
at Router->runRouteWithinStack(object(Route), object(Request)) in Router.php line 699
at Router->dispatchToRoute(object(Request)) in Router.php line 675
at Router->dispatch(object(Request)) in Kernel.php line 246
at Kernel->Illuminate\Foundation\Http\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 52
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in CheckForMaintenanceMode.php line 44
at CheckForMaintenanceMode->handle(object(Request), object(Closure))
at call_user_func_array(array(object(CheckForMaintenanceMode), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
at Pipeline->Illuminate\Routing\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 102
at Pipeline->then(object(Closure)) in Kernel.php line 132
at Kernel->sendRequestThroughRouter(object(Request)) in Kernel.php line 99
at Kernel->handle(object(Request)) in index.php line 53

Where is the error? What am I missinig?

Christian Giupponi
  • 7,408
  • 11
  • 68
  • 113

1 Answers1

0

I think the binding in your service provider is wrong. Try with this:

public function registerSMSService()
{
    ...

    // Bind the service
    $this->app->bind( 'abstractsms', "ChristianGiupponi\LaravelSMS\Repositories\\{$service}\\{$service}" );
}

Currently you get an error from the facade because Laravel can't resolve abstractsms, but when you bind abstractsms in the provider it tells Laravel - when the facade needs abstractsms give me an isnatnce of ChristianGiupponi\LaravelSMS\Repositories\{$service}\{$service}.

thefallen
  • 9,496
  • 2
  • 34
  • 49