Implementation of Facade in front of Factory class Laravel 5.4

For some context – earlier today I was struggling to figure out how to implement a facade similar to Cache – where I could set a provider (like disk()), but also have a generic fall back provider when not supplied.

Now, I got the basic infrastructure working, but I think my implementation is nasty. Having call default() or provider() just stinks. However, there is a concept or something I’m missing to fill in the gaps here.

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

Here is what I’ve done.

// FactoriesSMSFactory.php

namespace AppFactories;

use AppIError;


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' => 'AppSMSGlobalSMSGlobal',
];

// ProvidersSMSServiceProvider.php

namespace AppProviders;

use IlluminateSupportServiceProvider;


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', 'AppFactoriesSMSFactory');
    }
}

// FacadesSMS.php

namespace AppFacades;

use IlluminateSupportFacadesFacade;

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


// app.php

AppProvidersSMSServiceProvider::class,

# and in aliases

'SMS' => AppFacadesSMS::class,


// Controllers/TestController.php


namespace AppHttpControllersTestController;

use AppHttpControllersController;
use IlluminateHttpRequest;

use AppFacadesSMS;


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

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

What is really bothering me is having to always use default()…

I understand that the facade acts as a static class, but is it possible to set it up in such a way that I could make calls like this?

SMS::send($args);

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

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You can use the __call method in your SMS Factory class, and it must be changed accordingly:

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

The SMSFactory class should not have static methods as the static methods can be accessed through facade.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x