简体   繁体   English

PHP中的全局变量

[英]Global variable in php

I have a class userdb in which I am declaring a function that returns the connection to the database: 我有一个类userdb ,其中声明了一个返回数据库连接的函数:

return $con = new PDO("mysql:host=$host;dbname=$db", $user, $pass);

I have various functions, even across other classes, where I have to access $con (eg to pass a query or to fetch data), but I can't access this variable. 我有各种功能,即使在其他类中也必须访问$con (例如,传递查询或获取数据),但是我无法访问此变量。

Is there a better way to define and use a database class? 有没有更好的方法来定义和使用数据库类? Remember that I have other classes where I need to access the userdb class. 记住,我还有其他需要访问userdb类的类。

I would advise you to use the Singleton Pattern for this: 我建议您为此使用Singleton模式

In your userdb class, declare a static property $scon : 在您的userdb类中,声明一个静态属性$scon

private static $scon;

and assuming the function you mention above is named createConnection() , you should create the folowing static method: 并假设您上面提到的函数名为createConnection() ,则应创建以下静态方法:

public static function connect() {
    if (empty(self::$scon)) {
         $instance = new userdb();
         self::$scon = $indtance->createConnection(); 
    }
    return self::$scon; 
}

With this, you will be able to access your userdb connection with: 这样,您将可以通过以下方式访问userdb连接:

userdb::connect();

Also since this is a singleton, it will only connect once, and use that connection until the end of the script. 同样,由于这是一个单例,因此它将仅连接一次,并使用该连接直到脚本结束。

Note (on dependency injection): Since @KevinM1 mentioned Dependency Injection , I must add that it is also a possible, and far superior solution. 注意(关于依赖关系注入):由于@ KevinM1提到了依赖关系注入 ,我必须补充一点,它也是一种可能的,而且非常优越的解决方案。 It requires you to create a setConnection() method (or an Abstract ancestor) for all your classes using a database connection, and during the instatiation of these classes you may use a Factory to add the required connection to the object. 它要求您使用数据库连接为所有类创建setConnection()方法(或抽象祖先),并且在这些类的实例化过程中,可以使用Factory将所需的连接添加到对象。 This should be wrapped inside some class loader , which is avare of your model structure. 这应该包装在一些类加载器中该类加载器可用于您的模型结构。

See, peace of cake, but for small and fast developement I would stick with the Singleton ;) 看,平安无事,但是为了小而快速的发展,我会坚持使用Singleton;)

If it's in a class, store the instance in a property: 如果在类中,则将实例存储在属性中:

class userDB
{

   public $dbCon = false;//because you want to access the instance 
   //from outside the class, I have made the property public

    function connect()
   {

      $con = new PDO("mysql:host=$host;dbname=$db", $user, $pass);

      $this->dbCon = $con;

   }


}

TO access it outside of the class: 要在课程之外访问它:

$useDBInstance->dbCon;

return $this->con 

从班级返回这种方式并以此方式调用。

$this->classObject->con->prepare();

Well, $con will already be an object, as it's instantiating a new PDO object. 好吧,$ con已经成为一个对象,因为它正在实例化一个新的PDO对象。 Unless you're trying to add functionality to your PDO object, wrapping it is pointless. 除非您尝试向PDO对象添加功能,否则包装它是没有意义的。

That said, the best way to share your userdb/PDO object (depending on whether or not you stick with the wrapper) with other objects is to use Dependency Injection . 也就是说,与其他对象共享userdb / PDO对象(取决于您是否坚持使用包装器)的最佳方法是使用Dependency Injection That's a fancy term for passing your db to whatever object needs it. 这是将您的数据库传递给任何需要它的对象的幻想术语。 Since objects are defaultly passed by reference in PHP, if you create your db object first, all objects that receive it as a constructor/method argument will be using that same single instance. 由于默认情况下,对象是通过PHP在引用中传递的,因此,如果您首先创建db对象,则将其作为构造函数/方法参数接收的所有对象都将使用同一实例。

EDIT: Link to Dependency Injection implementation 编辑: 链接到依赖注入实现

EDIT2: Clarification on DI in small projects - EDIT2:澄清小型项目中的DI-

The normal DI pattern generally requires a special object called a DI Container. 正常的DI模式通常需要一个称为DI容器的特殊对象。 This is a special use object that automatically injects the dependency into the object that needs it. 这是一个特殊用途的对象,它自动将依赖项注入需要它的对象中。 For small projects, it's overkill. 对于小型项目,这太过分了。 The simple, low complexity version of DI is simply: DI的简单,低复杂度版本很简单:

class SomeClass {
    protected $db;

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

class SomeClass2 {
    public function SomeMethod($db) {
        // do something with the db
    }
}

$db = new PDO(/* connection string */);

$obj = new SomeClass($db, /* other constructor args */);

// or

$obj2 = new SomeClass2(/* constructor args */);
$obj2->someMethod($db, /* method args */);

The magic is that since objects are passed by reference by default in PHP, $obj and $obj2 are using the same db connection. 魔术在于,由于默认情况下在PHP中对象是通过引用传递的,因此$ obj和$ obj2使用相同的数据库连接。

The whole idea is to not blow apart scope or encapsulation by having a static method, and to ensure that classes and their methods are up front about what they require in order to work. 整个想法是不要通过使用静态方法来破坏范围或封装,并确保类及其方法预先了解它们所需要的内容才能正常工作。

Singletons do the exact opposite. 单例则相反。 They're accessed through static methods, which bypass scope, and since they're invoked and not passed, they never show up in method signatures, so anyone not familiar with the code won't be aware of that hidden requirement. 它们是通过静态方法访问的,这些方法绕过了作用域,并且由于它们是被调用而不是通过传递的,因此它们永远不会出现在方法签名中,因此任何不熟悉代码的人都不会意识到这个隐藏的要求。 Even Erich Gamma, one of the people who helped codify the Singleton Pattern has regrets about it : 甚至帮助整理Singleton模式的人之一Erich Gamma对此也感到遗憾

I'm in favor of dropping Singleton. 我赞成放弃辛格尔顿。 Its use is almost always a design smell. 它的使用几乎总是一种设计气味。

In PHP, where there's no concept of shared memory, and where scripts execute once per request, the only reason to want to use a singleton is to have easy access to a single resource. 在PHP中,没有共享内存的概念,每个请求只执行一次脚本,因此,使用单例的唯一原因是可以轻松访问单个资源。 Since objects are passed by reference, a single instance can be shared with multiple objects naturally. 由于对象是通过引用传递的,因此单个实​​例可以自然地与多个对象共享。 From there, it's about good design and delegation. 从那里开始,它是关于良好的设计和委托的。

Checkout my video tutorial + code for an alternative to global PHP variables . 查看我的视频教程+代码 ,以替代全局PHP变量

You're doing it wrong there. 您在那做错了。 You need to use a static variable if you plan to create your connection in a function and store it there. 如果打算在函数中创建连接并将其存储在其中,则需要使用静态变量。 Otherwise you'll keep connecting on every function call. 否则,您将在每次函数调用时保持连接。 My tutorial explains this very concept of static variables within regular functions. 我的教程解释了常规函数中静态变量的概念。

If it's not clear enough, let me know and I'll try to answer your questions. 如果不够清楚,请告诉我,我会尽力回答您的问题。

Here's some code to accompany this: 这是一些与此相关的代码:

/**
* Arguments are none or [$db, [$user, [$pass[, $host]]]].
*
* @return PDO
*/
function PdoDb(){
    static $con = null; // I'm explicit :)
    // Every time you pass Arguments you reconnect
    if(func_num_args()){
        $args = array_pad(func_get_args(), 4, null);
        list($db, $user, $pass, $host) = $args;
        if(empty($user)) $user = 'root';
        if(empty($host)) $host = 'localhost';
        $con = new PDO("mysql:host={$host};dbname={$db}", $user, $pass);
    }
    if(empty($con)){
        trigger_error('Provide arguments to connect first.', E_USER_ERROR);
        return null;
    }
    return $con;
}

// First run (provide arguments to connect)
PdoDb($db, $user, $pass, $host);
PdoDb($db); // Works if you connect root@localhost with no password

// From here on (it returns PDO)
PdoDb()->DoStuffOfPdo();

Once connected it stays that way. 连接后,它将保持这种状态。 But you can reconnect at will to by providing arguments. 但是您可以通过提供参数来随意重新连接。

use singlton class implimentation 使用singlton类的实现

class connectdb
{
    protected static $_instance = NULL;


    private function __construct()
    {
    }

    public function getinstance()
    {
     if (null === self::$_instance) {
            self::$_instance = new self();
        }

        return self::$_instance;
    }
    public function connect()
    {
     $this->connection =new PDO("mysql:host=$host;dbname=$db", $user, $pass);


    }

}

for using a variable within a class function or independent function you need to place a global keyword 为了在类函数或独立函数中使用变量,您需要放置一个全局关键字

$conn=mysql_connect(); 
   function test(){
      global $conn;
   }

now $conn will be available within the scope of test function, and it will be available everywhere when defined at the top of the script. 现在$conn将在test函数的范围内可用,并且在脚本顶部定义后将在任何地方可用。 For class also you need to do the same thing, make a object of a class and declare it as global within a function 对于类,您还需要做同样的事情,创建一个类的对象,并将其声明为函数中的全局对象

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM