我确实在app\Libs下编写了一个简单的接口。我在composer.json中注册了名称空间
"autoload": {
"classmap": [
"database/seeds",
"database/factories",
"app/Libs"
],DomoticControllerInterface.php (名为" controller“,因为这是一个用于多域设置的控制器,而不是”;“)
namespace App\Libs;
interface DomoticControllerInterface
{
/**
* Get the current temperature.
*/
public function getCurrentTemperature();
/**
* Get the current status of general heating (ON/OFF)
*/
public function getCurrentStatusOfGeneralHeating();
}以及实现它的类Domoticz.php。
<?php
/**
* Domoticz instance.
*
* @see www.domoticz.com
*/
namespace App\Libs;
class Domoticz implements DomoticControllerInterface
{
public function getCurrentTemperature()
{
// TODO: Implement getCurrentTemperature() method.
return "27.4";
}
public function getCurrentStatusOfGeneralHeating()
{
// TODO: Implement getCurrentStatusOfGeneralHeating() method.
}
}我写了一个HeaterService.php (模型?提供者?)在app下\Libs
<?php
/**
* Heater Service Class.
* This class perform work on Heater
*
* @since 3.0.0
* @author sineverba
*/
namespace App\Libs;
/**
* Class HeaterService
* @package App\Libs
*/
class HeaterService
{
/**
* The domotic controller.
*
* @var object
*/
private $domotic_controller;
public function __construct($domotic_controller)
{
$this->setDomoticController($domotic_controller);
}
/**
* Get the current temperature
*
* @return string the current temperature
*/
public function getCurrentTemperature()
{
return $this->getDomoticController()->getCurrentTemperature();
}
/**
* Set the domotic controller.
*
* @param object the domotic controller to use
* @since 1.0.0
* @author sineverba
*/
private function setDomoticController($domoticController)
{
$this->domotic_controller = $domoticController;
}
/**
* Get the istance of domotic controller
*
* @return object the domotic controller
* @since 3.0.0
* @author sineverba
*/
private function getDomoticController()
{
return $this->domotic_controller;
}
}最后,在我的BaseController.php下的app\Http\控制器
<?php
/**
* Base Controller that redirect to right controller/model,
* based on the URL params.
*
* @author sineverba
* @since 1.0.0
*/
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class BaseController extends Controller
{
//
/**
* Get the param from the URL and redirect to right controller.
*
*/
public function getTheScriptFromUrl(Request $request)
{
$domotic_controller = env("DOMOTIC_CONTROLLER", "Domoticz");
if ($domotic_controller=="Domoticz") {
$dom_controller = new \App\Libs\Domoticz();
}
$heater = new \App\Libs\HeaterService($dom_controller);
echo $heater->getCurrentTemperature();
}
}它起作用了。我得到了27.4硬编码。
但是,这是正确的模式吗?
另一个问题是,我会在HeaterService.php构造函数中使用类型提示,但不知道如何做。
最后,我的应用程序工作(暂时),没有绑定。有可能吗?
非常感谢
发布于 2019-01-21 19:20:47
这里有几件事不对。所以让我们一次只吃一个。
首先,如果要在app命名空间中添加类,则不需要自动加载该类。它应该已经装好了。
"autoload": {
"psr-4": {
"App\\": "app/"
}
}服务容器的一个非常强大的特性是它能够将接口绑定到给定的实现。
在OOP中,您经常会听到短语“代码到接口”,这就是这里发生的情况。
考虑到这一点,让我们创建一个HeaterServiceProvider。它的职责是将我们的依赖项注册到容器中,以便我们以后可以使用它。
<?php
namespace App\Libs;
use Illuminate\Support\ServiceProvider;
class HeaterServiceProvider extends ServiceProvider
{
/**
* Register bindings in the container.
*
* @return void
*/
public function register()
{
$this->app->bind(
'App\Libs\DomoticControllerInterface',
'App\Libs\Domoticz
);
}
}..。然后,您将在config/app.php的提供者数组中注册该服务提供者。
'providers' => [
//
//
App\Libs\HeaterServiceProvider::class
]这将将绑定注册到应用程序的容器中。只要您需要解析App\Libs\DomoticControllerInterface,就会返回App\Libs\Domoticz的一个实例。
因此,要使用它,只需在方法中键入提示接口,如:
<?php
/**
* Base Controller that redirect to right controller/model,
* based on the URL params.
*
* @author sineverba
* @since 1.0.0
*/
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Libs\DomoticControllerInterface;
class BaseController extends Controller
{
//
/**
* Get the param from the URL and redirect to right controller.
*
*/
public function getTheScriptFromUrl(DomoticControllerInterface $heater, Request $request)
{
// Laravel will automatically resolve an instance of
// App\Libs\Domoticz here, so you could just do the following
echo $heater->getCurrentTemperature();
}
}在您的特殊情况下,通过在getTheScriptFromUrl()中“调整”您的实现,您实际上是在“对实现进行编码”,而不是接口。
如果您实际上不打算从容器中解决依赖关系,那么您也就违背了将东西绑定到容器的目的。
您的实现将来可能会发生变化。如果您将代码编码到一个接口,那么如果您的实现发生了更改,唯一需要做的事情就是将新的实现绑定到容器中,并且您的应用程序应该是好的。
而且,如果使用依赖项注入,那么执行测试就容易多了。您可以在测试环境中轻松地交换/模拟这些实现。
我建议您深入了解服务容器文档。您还可以查看这篇文章。作者在解释Laravel的服务容器方面做得很好。
此外,查看服务提供商的文档也会有所帮助。
编辑:基于我们在评论中的讨论,下面是如何在场景中这样做的。
<?php
namespace App\Libs;
use Illuminate\Support\ServiceProvider;
class HeaterServiceProvider extends ServiceProvider
{
/**
* Register bindings in the container.
*
* @return void
*/
public function register()
{
$implementation = 'Homeassistant'; // You could be pulling this from anywhere
$this->app->bind(
'App\Libs\DomoticControllerInterface',
"App\Libs\{$implementation}"
);
}
} 关键是,实际上不需要在任何地方创建实现的实例,因为您已经将其绑定到控制器中。
就我们的具体情况而言,如下:
<?php
/**
* Base Controller that redirect to right controller/model,
* based on the URL params.
*
* @author sineverba
* @since 1.0.0
*/
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Libs\DomoticControllerInterface;
class BaseController extends Controller
{
//
/**
* Get the param from the URL and redirect to right controller.
*
*/
public function getTheScriptFromUrl(DomoticControllerInterface $heater, Request $request)
{
// Laravel will automatically resolve an instance of
// App\Libs\Homeassistant here, so you could just do the following
echo $heater->getCurrentTemperature();
}
}我希望这是有意义的:)
https://stackoverflow.com/questions/54296357
复制相似问题