使用静态方法连接数据库

时间:2015-10-17 03:57:11

标签: php

目前我在这样的类中使用数据库连接:

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

如果我在另一种方法中需要它,我会像这样使用它:

public function getElementbyID() {
    $stmt = $this->db->prepare("SELECT ...

但是我如何在静态方法中使用它? 我无法使用$this->db

public static function getElementbyID() {
    $stmt =    $this->db    ->prepare("SELECT ...

如何使用SomeClass::getElementFromDB()但是在函数中仍然使用我在__construct中获得的数据库连接?

我不想像这样使用它:SomeClass::getElementFromDB($db)而且我不想创建新的数据库连接,因为我已经在$db中有一个。

或者 - 通常 - 这是怎么做到的?

谢谢!

3 个答案:

答案 0 :(得分:2)

似乎有两个主要问题导致人们在课程中包装PDO代码。

首先需要调用数据库一次并重用数据库连接。例如,您不希望在每个Model函数内调用数据库,因为它会生成太多的数据库连接,通常会有比数据库服务器允许的更多的连接。

接下来是为了防止必须将数据库连接变量(例如$conn)传递给函数。 这可以通过示例来说明,因为代码'select($ table,$ where)'优先于'select($ conn,$ table,$ where)'。

有几个微框架/类/库可以帮到您。 一些更好的包括:

  

或者 - 通常 - 这是怎么做到的?

我个人更喜欢使用程序代码(使用全局$ dbh变量来保存数据库连接),这些代码使用“几乎”普通的PDO调用。

为此,我首先构建一个db()函数来保存数据库连接:

function db($dsn=null)
{
    global $dbh;
    if( isset($dbh) ) {
        return $dbh;
    } else {
        $dbh = new PDO($dsn);
        $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
        $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
        $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        return $dbh;
    }
}

用法:

db("sqlite:articles.db");

$stmt = db()->prepare("INSERT INTO `article` (`id`,`title`,`body`) VALUES (:id, :title, :body)");
$stmt->execute([ ':id'=>$id, ':title'=>$title, ':body'=>$body ]);

或者:

$stmt = db()->prepare("SELECT * FROM `article` WHERE `id`=:id");
$stmt->execute([':id'=>542]);
$row = $stmt->fetch(PDO::FETCH_OBJ);
echo $row->id;
...

它甚至可以在允许我使用简单语法创建自己的模型函数的函数中运行:

db("sqlite:articles.db");

print_r( select_article("542") );

function select_article($id) {
    // Note that we use db() inside the function, without adding a $conn variable
    $stmt = db()->prepare("SELECT * FROM `article` WHERE `id`=:id AND published=1");
    $stmt->execute([':id'=>$id]);
    return $stmt->fetch(PDO::FETCH_ASSOC);
}

function insert($table,$data) {
    ...
    $stmt = db()->prepare("INSERT INTO `article` (`id`,`title`,`body`) VALUES (:id, :title, :body)");
    $stmt->execute([ ':id'=>$id, ':title'=>$title, ':body'=>$body ]);
}

答案 1 :(得分:1)

如果要以静态方式使用类,则必须将该类的所有属性和方法重构为静态。 这是你的课应该是的一个类模板,imho:

class Element
{
    protected static $db;

    public static function setConnection(PDO $pdo)
    {
        self::$db = $pdo;
    }

    public static function getElementByID($id)
    {
        // use self::$db to retrieve information
    }
}

// then you can use it directly without instantiate an instance
$element = Element::getElementByID($id);

基于您想要隐式或显式调用setConnection()来注入数据库连接。您可以明确地使用它:

Element::setConnection($pdo);
$element = Element::getElementByID($id)

或通过隐式调用隐藏所有设置(您可能希望通过设置单例数据库类为每个类提供Pdo实例来使用单例模式)

class Database
{
    protected static $db;

    private function __construct(){};

    public static function getPdo()
    {
        if (!$db) self::$db = new Pdo();
        return self::$db;
    }
}

class Element
{
    public static function getElementByID($id)
    {
        // all the code like above

        // call setConnection implicitly
        self::setConnection(Database::getPdo());
        // use self::$db to retrieve information
    }
}
// and just simply use
$element = Element::getElementByID($id);

每次类需要连接时,您也可以使用Database::getPdo(),因此可以多次重复使用唯一的连接。

此致

答案 2 :(得分:0)

我编写了一个简单的类,你可以添加函数,你也可以使它更好,更有效。

<?php
class Database
    {
        private $conn;
        private $handle;

        public static function __construct()
        {
        $dbhost = "localhost";
        $dbname = "pdo_test";
        $dbuser = "root";
        $dbpass = "";
        $charset = "utf8";

        /**
        * -database driver, host, db ( schema ) name and charset, as well as less frequently used port and unix_socket are going to DSN
        * -username and passwword are going to constructor
        * -al other options go to options array
        */

        $dsn = "mysql:host=$dbhost;dbname=$dbname;charset=$charset"; // DSN is a semicolon-delimited string consist of param = vale pairs.( DSN = Data Source Name )
        try
        {
            $this->conn = new PDO( $dsn, $dbuser, $dbpass, $opt );
            //echo "Database connection successful.<br />";
        }
        catch(PDOException $e)
        {
            echo "Error in database connection !!!<br />";
            echo $e->getMessage();
        }
        }

        public static function test($test)
        {
            echo "<br />".$test;
        }

        public  static function __destruct()
        {
            $this->conn = null;
            if(!$this->conn)
            {
        //  echo "<br />database disconnected !!";
            }
        }
    }

    Database::test("your query or table name and  condition according to your functions");