1

假设我创建了一个全局变量 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)


      }


   }
4

3 回答 3

10

强烈不建议使用全局变量。它会妨碍您的应用程序的可读性和可维护性,并可能导致您失去理智。

有关更多详细信息,请参阅此问题。

将变量传递给类的构造函数。所有其他方法都可以通过访问$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实例,因为它已传递给构造函数并保存为对象字段。

于 2012-11-03T09:21:36.467 回答
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对象的方法即可。

所以现在这行代码就很本地化了。该$connection对象需要进入user, 用于您迄今为止使用的非 OO 后台全局变量。但是在面向对象编程中,类的代码中不应该使用全局变量。那是因为程序代码中的全局变量是$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在它的构造方法中初始化__constructMysqli连接。然后可以使用该连接,$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;");
}

例如,如果您有一组公共类,只是其属性名称不同,则公共基类可以包含实现该目标的代码,而从它扩展的类只需要为此指定参数。

但正如所写,有许多不同的方式将类映射到数据库连接。有时您根本不想映射它们。做最适合你的事情,玩一点。如果您始终在构造函数中进行初始化并阻止使用全局变量(以及也是全局变量的静态类变量),那么您将保持灵活性并且实际上可以玩得更好。

请记住:每个人都在用水做饭,这背后没有魔法。

于 2012-11-03T16:08:41.097 回答
-2

在构造函数中将其设置为类变量

Class a{

  public __construct( $db ){
    $this->db = $db;
  }

  function b(){
    $this->db->query();
  }
}
于 2012-11-03T09:23:29.297 回答