假设我创建了一个全局变量global $ db3; ($ db3实际上是另一个类的一个保留对象).而不是将这个全局变量逐个传递给每个方法,我想默认将这个变量传递给一个类的所有方法.
我的第一个数据库类是
class dtb{
public $connection;
public function __construct(){
$this->connection=mysqli_connect('localhost','root','','new5');
}
}
$db3=new dtb();
Run Code Online (Sandbox Code Playgroud)
第二类是
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)
}
}
Run Code Online (Sandbox Code Playgroud)
Mad*_*iha 10
强烈建议不要使用全局变量.它会妨碍您的应用的可读性和可维护性,并可能导致您失去理智.
将变量传递给类的构造函数.通过访问它可用于所有其他方法$this->db
.
class A {
private $db;
public function __construct($db) {
$this->db = $db;
}
public function someFunction() {
$this->db->doSomething();
}
/*
* Etc
*/
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以通过以下方式调用它:
$db3 = new dtb;
$a = new A($db3);
$a->someFunction();
Run Code Online (Sandbox Code Playgroud)
someFunction()
将有权访问$db3
实例,因为它被传递给构造函数并保存为对象字段.
您的代码示例中有一些与您在问题中要求的内容相关的问题,因此我想强调一下.
最明显的问题是您不传递数据库连接对象.而是将它包装到类型中dtb
,以便稍后在其他类型内部进行解包,例如在user
:
function login() {
...
$results = mysqli_query($this->db->connection,"select * from user");
^--^--- unwrapping
...
Run Code Online (Sandbox Code Playgroud)
相反,user
类型应该只有连接.它不需要知道dtb
包装:
function login() {
...
$results = mysqli_query($this->connection, "select * from user");
^--- one thing, not one thing and another
...
Run Code Online (Sandbox Code Playgroud)
接下来,您没有使用mysqli
扩展的OO接口.您的示例代码很好地证明了这会使您的代码变得不必要地复杂化.让我们以mysqli的方式做到这一点:
function login() {
...
$results = $this->connection->query("select * from user");
...
Run Code Online (Sandbox Code Playgroud)
如您所见,您可以在不使用mysqli_*
特定功能的情况下使用连接,只需使用query
对象的方法即可.
所以现在这个单行代码已经非常本地了.该$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;");
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,User
在构造函数方法中初始化__construct
了Mysqli
连接.然后可以使用该连接,$this->connection
因为它已被分配给该私有变量.
您现在可以放心,一旦实例化了类,连接将保持不变.如果您需要并行打开与另一个数据库的连接,这也很有用.无论您需要创建多少个Mysqli连接,您的代码都将继续有效.
所以现在用于:
$connection = new Mysqli('localhost','root','','new5');
$user = new User($connection);
$user->login();
Run Code Online (Sandbox Code Playgroud)
就是这样.当然,在创建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;");
}
Run Code Online (Sandbox Code Playgroud)
例如,如果您有一组通用的类,它们的属性名称不同,则公共基类可以包含实现该类的代码,而从中扩展的类只需要为其指定参数.
但是,正如所写,有许多不同的方法将类映射到数据库连接.你有时根本不想要映射它们.做什么最适合你,玩一下.如果你总是在构造函数中初始化并且阻止使用全局变量(以及全局变量的静态类变量),那么你将保持灵活性并且实际上可以更好地发挥作用.
请记住:每个人都在用水烹饪,背后没有任何魔力.