php中的全局变量

php中的全局变量,php,database,global,Php,Database,Global,我有一个类userdb,我在其中声明了一个函数,该函数返回到数据库的连接: return $con = new PDO("mysql:host=$host;dbname=$db", $user, $pass); 我有各种函数,甚至在其他类中,我必须访问$con(例如,传递查询或获取数据),但我无法访问此变量 有没有更好的方法来定义和使用数据库类?记住,我还有其他类需要访问userdb类 return $this->con 从你的班上走这边,叫它这边 $this->classOb

我有一个类
userdb
,我在其中声明了一个函数,该函数返回到数据库的连接:

return $con = new PDO("mysql:host=$host;dbname=$db", $user, $pass);
我有各种函数,甚至在其他类中,我必须访问
$con
(例如,传递查询或获取数据),但我无法访问此变量

有没有更好的方法来定义和使用数据库类?记住,我还有其他类需要访问
userdb

return $this->con 
从你的班上走这边,叫它这边

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

如果实例位于类中,请将其存储在属性中:

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;

   }


}
要在类外访问它,请执行以下操作:


$useDBInstance->dbCon

要在类函数或独立函数中使用变量,需要放置全局关键字

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

现在,
$conn
将在测试功能范围内可用,并且当在脚本顶部定义时,它将在任何地方可用。对于类,您也需要做同样的事情,为类创建一个对象,并在函数中将其声明为全局对象,$con将已经是一个对象,因为它正在实例化一个新的PDO对象。除非您试图向PDO对象添加功能,否则包装它是毫无意义的

也就是说,与其他对象共享userdb/PDO对象(取决于是否使用包装器)的最佳方法是使用依赖项注入。这是一个花哨的术语,用于将db传递给任何需要它的对象。由于对象在PHP中默认通过引用传递,如果您首先创建db对象,那么作为构造函数/方法参数接收它的所有对象都将使用同一个实例

编辑:

编辑2:澄清小型项目中的DI-

正常的DI模式通常需要一个称为DI容器的特殊对象。这是一个特殊用途的对象,它会自动将依赖项注入到需要它的对象中。对于小项目来说,这太过分了。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 */);
神奇之处在于,由于对象在PHP中默认通过引用传递,$obj和$obj2使用相同的db连接

其整体思想是不通过使用静态方法来破坏作用域或封装,并确保类及其方法预先了解它们工作所需的内容

单身人士的情况正好相反。它们是通过绕过作用域的静态方法访问的,由于它们被调用而未被传递,因此它们永远不会出现在方法签名中,因此任何不熟悉代码的人都不会意识到隐藏的需求

我赞成放弃单身。它的使用几乎总是一种设计的味道


在PHP中,没有共享内存的概念,每个请求执行一次脚本,使用单例的唯一原因是可以轻松访问单个资源。由于对象是通过引用传递的,因此单个实例可以自然地与多个对象共享。从这里开始,就是关于良好的设计和委派。

使用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);


    }

}

我建议您使用进行以下操作:

在userdb类中,声明一个静态属性
$scon

private static $scon;
假设上面提到的函数名为
createConnection()
,则应创建以下静态方法:

public static function connect() {
    if (empty(self::$scon)) {
         $instance = new userdb();
         self::$scon = $indtance->createConnection(); 
    }
    return self::$scon; 
}
通过此操作,您将能够通过以下方式访问您的userdb连接:

userdb::connect();
此外,由于这是一个单例,它将只连接一次,并使用该连接直到脚本结束

注意(关于依赖项注入):既然@KevinM1提到了依赖项注入,我必须补充一点,这也是一种可能的、远优于此的解决方案。它要求您使用数据库连接为所有类创建setConnection()方法(或抽象祖先),并且在这些类的安装过程中,您可以使用工厂向对象添加所需的连接。这应该包装在一些类加载器中,类加载器是模型结构的一部分


看,蛋糕上的和平,但对于小而快的发展,我会坚持使用Singleton;)

查看我的视频教程+代码,了解更多信息

您在那里做得不对。如果您计划在函数中创建连接并将其存储在那里,则需要使用静态变量否则,每次函数调用都会保持连接。我的教程解释了常规函数中静态变量的概念

如果还不够清楚,请告诉我,我会尽力回答你的问题

下面是一些代码:

/**
* 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();

一旦连接,它就会保持这种状态。但您可以通过提供参数随意重新连接到。

单例可能会帮助您:
global$x已成为过去。在这样的情况下完全没有必要使用它。在PHP中,“全局”永远都不是一个好办法。尤其是在范围和封装至关重要的OO环境中。还有更好的选择,没有理由在PHP中使用singleton,因为它是fire and forget nature。依赖注入是一种方法。其他人会不同意,这不是“错”。这不是最好的方法。即使这样,有些人也会说相反的话(这是完全正确的)。在这个问题上投反对票是完全没有必要的+1依赖性注入是一个非常优越的解决方案。@KevinM1:Ofc,但对于较小的项目,这是一个非常适合的解决方案。我还想添加一些延迟加载,但这不是这里的问题。我认为在引导阶段更容易利用默认的引用传递行为。一般来说,您知道何时需要提前访问db。对于较小的项目,只需实例化db对象并手动将其传递给其他需要它的对象,而不必经历实际DI容器的循环。尤戈