对不起,如果帖子的标题不清楚,我会尽量简单,因为我真的认为这个问题有一个简单的答案。
首先,我将添加一些代码(不是真实的的代码,只是为了测试):
型号:
class User{
public $id;
public $name;
public $age;
}
接口:
interface IData{
public function search(User $user)
}
类存储库:
class DataRepository{
protected $db;
public $conn;
public $data;
// Passing the interface DB to the constructor
public function __construct(DB $db)
{
$this->db = $db;
}
public function search(User $user){
$query = " SELECT * FROM test_db WHERE id_user = ". $user->id . " and name = '%" . $user->name . "%'";
$this->conn = $this->db->connection();
$this->data = $this->conn->query($query);
$dataList = [];
foreach ($this->data as $row)
{
$dataList [] = (object)array(
"name" => $row["name"],
"age" => $row["age"],
);
}
return $dataList;
}
}
控制器:
class UserController{
public $Idata;
// Passing the interface IData to the constructor
function __construct(IData $Idata) {
$this->Idata = $Idata;
}
// Function to search the user and return an array with the data
function printData(){
$Mdata = new User();
$Mdata->id = 5;
$Mdata->name = "Carl";
$Mdata->age = 39;
$result = $this->Idata->search($Mdata);
return $result;
}
}
浏览次数:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test Page</title>
</head>
<body>
<?php
// We create an instance of UserController
$UserData = new UserController();
// Print the data
echo "<pre>";
print_r($UserData);
echo "</pre>"
?>
</body>
</html>
所以我试图学习使用MVC的存储库模式,将DB层与控制器分离并封装,一切看起来都很棒,直到我需要在主控制器(UserController)上使用IData接口时,我认为我出现了错误$UserData = new UserController() -> returns an error: Expected 1 arguments. Found 0
.
我知道这个错误的含义,它需要一个参数(接口),但是在视图端示例化接口感觉很奇怪,因为稍后会将其作为参数传递给构造器。
我试着:
<?php
$IData = new IData();
$UserData = new UserController($IData);
echo "<pre>";
print_r($UserData);
echo "</pre>"
?>
它返回以下错误:Fatal error: Uncaught Error: Cannot instantiate interface IData
。
我的主要问题是,有没有办法只在UserController的构造函数上使用接口,而不必在视图上定义它?
如果不可能(肯定会有),我该怎么办?(我不能使用关键字implemante
,因为我试图使用存储库模式,从构造函数进行依赖注入)
1条答案
按热度按时间up9lanfz1#
这更多的是一个如何在PHP中完成依赖注入的问题。
前置条件
首先,您应该通过声明
DataRepository
实现接口来修复代码:这是没有办法的事。PHP需要显式声明它。
先想想...
然后考虑以下几点:
UserController
依赖于IData
。DataRepository
应该实现IData
。1.您的代码应该知道,当示例化
UserController
时,它需要一个IData
实现。但可以不止一个。1.您的代码如何知道哪个
IData
用于UserController
?对于(4),你需要一种方法来声明:
IData
的类都应该有DataRepository
;或*一些需要
IData
的类,比如UserController
,应该有DataRepository
。依赖注入容器
一个简单的方法是使用依赖注入容器,如PHP-DI。它们可以灵活地声明如何实现接口依赖关系的方法。
假设您已经安装了composer的“php-di/php-di”,那么您应该让这段代码在某种公共的php /内核中运行。
如果你将
$container
变量传递给你的视图文件,你可以简单地这样做:请注意,您不需要手动创建
UserController
的依赖项。当请求UserController
时,这里的容器将搜索所有配方,以满足UserController
所需的所有依赖项。因此,视图不需要知道控制器的实现细节。更多内容
正如我之前提到的,您可能只需要将
DataRepository
作为IData
用于一些控制器。PHP-DI和其他依赖注入容器可以让您指定创建DataRepository
的方法。对于PHP-DI,您应该阅读相关文档,或了解其他更高级的用法。
PHP常用MVC框架
我想一个更常见的MVC设计可能会有视图的控制器调用。并将控制器示例化(使用容器)作为实现细节:
工艺路线:
控制器:
浏览次数:
这种设计甚至更好,因为视图不应该被要求知道任何关于控制器的信息。它应该简单地表示它所提供的数据。