假设我创建了一个全局变量global $ db3; ($ db3实际上是另一个类的一个未被保留的对象)。我不想将这个全局变量逐个传递给每个方法,我想默认将这个变量传递给一个类的所有方法。
我的第一个数据库类是
class dtb{
public $connection;
public function __construct(){
$this->connection=mysqli_connect('localhost','root','','new5');
}
}
$db3=new dtb();
第二节是
session_start();
$a = new session($db3);
class user{
public $db;
public function __construct($db)
{
$this->db = $db;
}
function login(){
//global $db3;
//$db3->show_new();
$results=mysqli_query($this->db->connection,"select * from user"); //(I want to use $db3 of another class here as resource link)
}
}
答案 0 :(得分:10)
强烈建议不要使用全局变量。它会阻碍您的应用的可读性和可维护性,并可能导致您失去理智。
<强> See this question for more details. 强>
将变量传递给类的构造函数。通过访问$this->db
可以使用所有其他方法。
class A {
private $db;
public function __construct($db) {
$this->db = $db;
}
public function someFunction() {
$this->db->doSomething();
}
/*
* Etc
*/
}
然后通过以下方式调用它:
$db3 = new dtb;
$a = new A($db3);
$a->someFunction();
someFunction()
将有权访问$db3
实例,因为它已传递给构造函数并保存为对象字段。
答案 1 :(得分:5)
您的代码示例中存在一些与您在问题中要求的内容相关的问题,因此我想强调一下。
最明显的问题是您没有传递数据库连接对象。而是将其包装到dtb
类型中,以便稍后在其他类型内部展开,例如在user
中:
function login() {
...
$results = mysqli_query($this->db->connection,"select * from user");
^--^--- unwrapping
...
相反,user
类型应该只有连接。它不需要知道dtb
包装:
function login() {
...
$results = mysqli_query($this->connection, "select * from user");
^--- one thing, not one thing and another
...
接下来,您没有使用mysqli
扩展名的OO界面。您的示例代码很好地证明了此不必要地使您的代码复杂化。让我们以mysqli的方式做到这一点:
function login() {
...
$results = $this->connection->query("select * from user");
...
如您所见,您可以在不使用特定mysqli_*
函数的情况下使用连接,只需使用对象的query
方法即可。
所以现在这个单行代码非常本地化了。对于您目前使用的非OO背景全局变量,$connection
对象需要进入user
。但是在面向对象编程中,类的代码中不应该使用全局变量。这是因为过程代码中的全局变量是类中的$this
变量。 $this
应该包含您的类中所需的所有方法 - 如果没有提供方法参数。
因此,您的多元化类在数据库连接上基于 。你想在每个班级都有它。一个类在它的构造方法中初始化。在那里你传递一切作为初始化课程所需的参数。我们来看user
示例类:
class User
{
private $connection;
public function __construct(Mysqli $connection) {
$this->connection = $connection;
}
public function login() {
$resultSet = $this->connection->query("SELECT * FROM user;");
}
}
如您所见,User
在其__construct
连接的构造方法Mysqli
中初始化。然后,该连接可以与$this->connection
一起使用,因为它已被分配给该私有变量。
您现在可以放心,一旦实例化了类,连接将保持不变。如果您需要并行打开与另一个数据库的连接,这也很有用。无论您需要创建多少个Mysqli连接,您的代码都将继续有效。
现在使用:
$connection = new Mysqli('localhost','root','','new5');
$user = new User($connection);
$user->login();
就是这样。当然,在创建Mysqli连接对象的位置和创建用户的位置之间可能存在一些代码,但您需要做的就是传递连接。
这不会在这里停止,虽然我已经接近这里的博客文章了。您可能想要做的是甚至消除每个类中连接细节的负担,而是从一个负责重复数据库交互代码的基类扩展,以便在更高级别的类中,您可以更专注于工作而不是数据库细节。有很多不同的方法可以做到这一点。从基类扩展只是其中之一。一个非常简单的例子:
class Database
{
private $connection;
public function __construct(Mysqli $connection) {
$this->connection = $connection;
}
protected function query($sql) {
return $this->connection->query($sql);
}
}
class User extends Database
{
$resultSet = $this->query("SELECT * FROM user;");
}
例如,如果您有一组通用的类,它们的属性名称不同,那么公共基类可以包含实现该类的代码,而从中扩展的类只需要为其指定参数。
但是,正如所写,有许多不同的方法将类映射到数据库连接。你有时根本不想要映射它们。做什么最适合你,玩一下。如果你总是在构造函数中初始化并且阻止使用全局变量(以及也是全局变量的静态类变量),那么你就会保持灵活性并且你可以更好地玩游戏。
请记住:每个人都在用水烹饪,背后没有魔法。
答案 2 :(得分:-2)
在构造函数中将其设置为类变量
Class a{
public __construct( $db ){
$this->db = $db;
}
function b(){
$this->db->query();
}
}