默认情况下,将一个全局变量传递给类的所有方法

时间:2012-11-03 09:15:28

标签: php oop mysqli

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


      }


   }

3 个答案:

答案 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();
  }
}