R
R
Ramm2016-12-22 13:50:45
PHP
Ramm, 2016-12-22 13:50:45

How to put similar entities into one abstract class?

There is a service for sending SMS messages. When sending messages through its API, the provider parameter is indicated (from which provider the messages will be sent), as you understand, each provider has its own API, the corresponding methods are named differently for everyone (for example, somewhere / send / sms ,, somewhere /sendsms or /send, etc., /balance or /getbalance, etc.)
For each provider, there is a separate class with its methods, so the question is how to do something like a single class with methods (sendSms (), getBalance(), etc.) through which the provider class will be selected. I hope I wrote clearly :)

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Arman, 2016-12-22
@rammtw

Quick option

class Sms
{
    protected static $instances = [];

    public static function getInstance($id = 'default')
    {
        $map = [
            'first' => 'FirstSmsHandler',
            'second' => 'SecondSmsHandler',

            'default' => 'FirstSmsHandler',
        ];

        if (!isset(self::$instances[$id])) {
            if (!isset($map[$id])) {
                throw new \Exception(sprintf('Unknown hadler `%s`', $id));
            }

            $handler = new $map[$id];

            self::$instances[$id] = new self($handler);
        }

        return self::$instances[$id];
    }

    protected $handler;

    public function __construct(SmsHandler $handler)
    {
        $this->setHandler($handler)
    }

    public function setHandler(SmsHandler $handler)
    {
        return $this->handler = $handler;
    }

    public function changeHandlerByName($handlerName)
    {
        $map = [
            'first' => 'FirstSmsHandler',
            'second' => 'SecondSmsHandler',

            'default' => 'FirstSmsHandler',
        ];

        if (!isset($map[$handlerName])) {
            throw new \Exception(sprintf('Unknown handler `%s`', $handlerName));
        }

        $handler = new $map[$handlerName];

        $this->setHandler($handler);

        return $this;
    }

    public function __call($name, $arguments)
    {
        return call_user_func_array([$this->handler, $name], $arguments);
    }
}

$sms = new Sms(new FirstSmsHandler());
$sms->changeHandlerByName($_POST['provider']);

$sms = Sms::getInstance($_POST['provider']);

$sms->getBalance();

You can also read how Laravel implements contracts, service containers and service providers. There, through the config, we simply change the container and are already working with another class. Read.

M
Maxim, 2016-12-22
@khrisanfov

You need to create an interface with sendSms() and getBalance() methods, then implement it for each provider. The number of classes will correspond to the number of providers, all will have one common interface.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question