首页 > 解决方案 > 在 Laravel 中构建“基于驱动程序”的模型

问题描述

我正在尝试构建一个雄辩的模型“平台”,它可以以与基于驱动程序的组件相同的方式实现某些逻辑。

一点通用背景:我有一个名为 Platforms 的 laravel 模型,它有一些通用方法。但是根据确切的“平台”,我想构建一些仅适用于该特定平台的自定义方法。它可能类似于连接方法或类似方法。

所以我的方法是像基于驱动程序的组件那样做,这扩展了Illuminate\Support\Manager因为我需要某种方法的合同。当我加载特定的“平台”时,我希望这些方法可以访问。

我知道我可以在模型本身中编写每个方法,或者包含每个平台的句柄方法。最后,我将拥有大约 10 个平台,大约 5 个自定义方法,所以它会很快变得丑陋。

我不希望将其构建为组件,因为我需要与其他模型的关系。

另一种解释方式可能是这样的:假设您有一群用户可以从应用程序接收短信通知,然后用户可以选择必须使用的短信“提供者”。(例如 Nexmo)这将是一个class SMSProvider extends model 具有某些方法的方法,例如send 您可以这样做$user->SMSProvider->send()

此发送方法必须特定于特定的提供者,就像在文档中一样:https ://laravel.com/docs/6.x/notifications#sms-notifications

你能给我一些关于我应该以哪种方式查看或编码的指示吗?

标签: laraveleloquent

解决方案


做答案我将不得不对解决方案做出很多假设。基础已设置,您需要一个 Platform 模型,假设它具有指示提供者的类型。

/**
 * @property string type
 */
public class Platform extends Model
{
    ...
}

驱动方法主要是在外部人员应该扩展您的库时使用,并且是一种用于不同实现的管理工具。这没有错,但我觉得它比它应该的更复杂。直接的方法是将平台的类型绑定到实现。为实现创建一个接口。

public interface SMSProvider
{
    public function sendSMS(): void;
}

为了展示,一个实现。

public class TeliaSMSProvider implements SMSProvider
{
    public function sendSms(): void
    {
        // magic
    }
}

在您的应用服务提供商中,将您的类型绑定到应用程序。

$this->app->bind('telia', function ($app) {
    return new TeliaSMSProvider();
});

同样,这个绑定部分只是一种在类型和正确实例之间建立连接的简单方法,可以完成基于类型参数的驱动程序或方法调用。

现在只需从平台加载您的提供程序,并将类型作为输入。打字提示更容易使用。

public class Platform extends Model
{
    public function getProvider(): SMSProvider
    {
        return app($this->type);
    }
}

推荐阅读