您好我是Laravel的新手,我试图掌握在我的开发中创建和使用服务提供商和合同的概念。我正在读这篇文章
How to Create a Service Provider in Laravel 5.1
它谈到了它们是如何被创造和使用的,但我仍然很难掌握它的想法。
文章提到这有希望有人可以更深入地讨论这个
那么为什么还要签订合同呢?好吧,Laravel的一个令人惊奇的功能是你可以输入提示合同,服务提供者将返回你绑定的任何具体类的实例。
他们也提到了这个
好的,现在我们需要创建服务提供者,它将绑定契约和具体类。
这个绑定是什么?它是如何从上到下工作的?什么是做绑定的重点?
仅针对服务的依赖注入?
答案 0 :(得分:3)
实际上,contarcts是接口,如果开发人员使用以下接口,接口基本上会迫使开发人员实现某些方法:
interface SomeInterface {
public function SomeMethod();
}
class SomeClass implements SomeInterface {
public function SomeMethod()
{
// Code ...
}
}
这是PHP OOP的核心功能,这样可以确保,如果某个类是某个接口的类型,那么该具体类肯定已经实现了该接口中声明的必需方法。因此,类SomeClass
正在使用(实现)SomeInterface
,因此根据规则,类必须实现SomeInterface
接口中声明的方法,否则PHP
将抛出错误。可能不够清楚,但无论如何,请阅读PHP
文档(上面给出的链接)。
因此,接口仅用于声明方法标头/签名,但不用于实现方法,并且接口不能使用new SomeInterface()
进行实例化。
另一方面,实现接口的类绑定到该接口以实现接口,因此它必须实现接口中声明的方法,因此任何实现接口的类都可以被视为该接口的类型。例如,SomeClass
实现了SomeInterface
接口,因此以下情况属实:
$instance = new SomeClass;
echo $instance instanceof SomeInterface; // 1 as true
if($instance instanceof SomeInterface) {
echo 'SomeClass is the type of SomeInterface';
}
因此,您可能知道可以使用类作为类型键入对象,例如:
class UserController extends Controller {
public function __construct(SomeClass $SomeClassInstance)
{
$this->$someClass = $SomeClassInstance;
}
}
在这种情况下,Laravel
框架能够在初始化UserController
类时自动注入依赖项('SomeClass'),这在Laravel ServiceContainer
的帮助下发生在场景后面然后使用PHP Reflection Class来读取类型并创建一个实例并在运行时注入它。
现在,当您使用具体类(例如SomeClass
)作为依赖项时,容器类可以自动注入依赖项而无需任何用户交互,因为它可以读取(逆向工程)构造函数UserController
类的方法,可以确定该依赖项的类型,并且可以轻松注入依赖项,但如果使用接口键入提示,则Laravel框架会像往常一样读取类型并尝试创建该类型的实例在这里它失败了。为什么,因为接口不是可实现的,并且需要一些信息来制作UserController
实例。所以,让我们使用SomeInterfrace
作为依赖项来编写前面的示例:
class UserController extends Controller {
public function __construct(SomeInterface $SomeClassInstance)
{
$this->$someClass = $SomeClassInstance;
}
}
现在,显而易见的是,Laravel
将无法创建UserController
类的实例,因为它具有依赖关系,这是一个接口,并且它不能创建接口的内容,所以在此在这种情况下,您需要使用服务提供者类将类与接口绑定在一起,或者换句话说,您需要告诉Laravel
框架,当它看到该接口时应该注入哪个类,这是一个简单的maping interface vs class
,但没有别的。为此,使用服务提供程序是一个不错的选择,因为框架运行每个可用的服务提供程序,并在框架的启动过程中运行register
和boot
方法。这是服务提供商的典型示例:
class UserServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(SomeINterface::class, SomeClass::class);
}
}
因此,现在Service Container
将能够通过从容器本身读取映射key => value
来注入依赖关系。它会知道,它应该在看到SomeClass
接口时注入SomeInterface
类。就是这样。
好吧,我已经发表了use
和评论,但希望你有这个主意。阅读文档(源代码)以及掌握它的时间。
答案 1 :(得分:1)
创建界面
interface CarInterface {
public function start();
public function gas();
public function brake();
}
这告诉我们的代码我们可以拥有我们想要的任何类型的汽车,只要它实现了start()gas()和brake()方法。这是界面的API或合同。
创建一个实现接口的类
这也很容易。我们所要做的就是像往常一样创建一个类,但是我们需要确保将implements关键字添加到我们的定义中:
class Subaru implements CarInterface {
public function start() {
echo 'Starts great';
}
public function gas() {
echo 'Hit the gas and let the all wheel drive grip those back roads!';
}
public function brake() {
echo 'Wow these Brembo brakes are powerful';
}
}
开始使用您的界面!
我们设置了CarInterace,我们有一个实现它的类,我们将来会证明我们的应用程序,并确保我们也可以测试可测试性,因为我们可以轻松地将实例交换进我们的应用程序。让我们测试一下这只小狗:
Route::get('/', function()
{
dd(App::make('CarInterface'));
});
哎呀,有一个错误! Illuminate Container BindingResolutionException目标[CarInterface]不可实例化。好吧,我们做了一个嘘声。看起来我们无法直接实例化一个接口。哦,是的!我们需要先绑定它!
绑定您的界面
我们可以轻松地将我们的界面绑定到应用程序,例如添加
App::bind('CarInterface', 'Subaru');
Route::get('/', function()
{
$car = App::make('CarInterface');
$car->start();
$car->gas();
$car->brake();
});
// Starts great
// Hit the gas and let the all wheel drive grip those back roads!
// Wow these Brembo brakes are powerful
中的更多内容
我觉得这本书对你来说是一个很好的资源
TAYLOR OTWELL - LARAVEL,从APPRENTICE到ARTISAN
简而言之,绑定将链接(也许这不是正确的术语,但我希望你明白我的意思)你的具体类的接口,
答案 2 :(得分:0)
我发现一些Laravel术语令人困惑。对我而言,服务提供商并不是对其功能的直观描述。
此外,对于仅由一两个人完成的小型项目而言,合同的整体想法似乎毫无意义。 Laravel假设一切都将变得庞大而复杂,并由多人开发。
我得到了OOP背后的哲学,但在某些时候试图将事情分开并向后弯曲而不重复任何事情都太过分了,使得代码更难以理解。
另外一个laravel让我烦恼的地方就是这个想法,它希望程序员把自己想象成艺术家。所以他们使用这些花哨的名字,如雄辩和照明以及工匠。这对新开发者来说是一种令人生畏的话。这违背了试图简化事情的想法。如果他们真的想优先考虑简化而不是将自己视为网络艺术家,那么可能从术语开始。
它不像绘画那样艺术。如果你在某个地方找到油漆点,它就不会破坏这幅画。如果你忘记了代码中的分号,整个事情就会崩溃。如果你想把它称为艺术品,那就称它为机器人艺术品,因为你的语法必须机器人和精确。