PHP面向对象数据库连接

8

我刚开始学习面向对象编程的概念,并编写了这个带有函数的类。

它可以正常工作,但我想知道我是否做得正确...

以下是我的代码:

class Database{
    const DB_HOSTNAME = 'localhost';
    const DB_USERNAME = 'root';
    const DB_PASSWORD = 'password';
    const DB_NAME = 'shop';
    protected $_db_connect;
    protected $_sql;
    protected $_result;
    protected $_row;

    function db_connect(){
        $this->_db_connect = mysql_connect(self::DB_HOSTNAME,self::DB_USERNAME,self::DB_PASSWORD) or die(mysql_error());
    }

    function slect_db(){
        mysql_select_db(self::DB_NAME) or die(mysql_error());
    }

    function sql(){
        $this->_sql = 'SELECT * FROM users';
    }

    function query(){
        $this->_result = mysql_query($this->_sql);
    }

    function fetch_array(){
        while($this->_row = mysql_fetch_array($this->_result)){
            $username = $this->_row['user_USERNAME'];

            echo "<ul>";
                echo "<li>".$username."</li>";
            echo "</ul>";
        }
    }

    function db_close(){
        mysql_close($this->_db_connect);
    }
}

$database = new Database();
$database->db_connect();
$database->slect_db();
$database->sql();
$database->query();
$database->fetch_array();
$database->db_close();

18
请勿在新代码中使用mysql_*函数。它们已不再维护,并已正式弃用。看到粉色框了吗?学习prepared statements,并使用PDOMySQLi-这篇文章将帮助您做出选择。如果选择PDO,这是一个好的教程 - h2ooooooo
1
在创建数据库访问时,始终使用单例设计模式以获得更好的性能。 - Yehia Awad
1
我认为这不适合良好的面向对象设计。请考虑,您编写的类并不特别通用,因为您的数据库连接详细信息只是硬编码常量。此外,此类唯一可以执行的SQL语句是“SELECT * FROM users”。这是您的意图吗?我会考虑使用其他包含特定SQL的类扩展此类,或使SQL函数接受SQL查询字符串。此外,您的数据库类不应该执行视图呈现(在fetch_array中)。http://en.wikipedia.org/wiki/SOLID_(object-oriented_design) - Drumbeg
5
这样的问题更适合发布到Code Review Stack Exchange网站上进行讨论。 - Gerald Schneider
6个回答

14
请使用PDO或MySQLi,因为它们更安全,而mysql_*函数已被弃用,如上所述。我提供了一些使用PDO的通用代码来帮助您进行新的尝试。如评论中所述,如果您正在寻求面向对象的设计,确实不应该输出数据,而是在执行查询后返回提取的行,然后使用类似于foreach循环的东西来显示数据。以这种方式编写数据库类还可以确保多个数据库连接不会同时打开!请注意,此代码仅供您参考,在生产环境或任何实时应用之前应进行测试。
config.php:
<?php
    //Enter your database connection details here.
    $host = 'localhost'; //HOST NAME.
    $db_name = 'databasename'; //Database Name
    $db_username = 'root'; //Database Username
    $db_password = ''; //Database Password

    try
    {
        $pdo = new PDO('mysql:host='. $host .';dbname='.$db_name, $db_username, $db_password);
    }
    catch (PDOException $e)
    {
        exit('Error Connecting To DataBase');
    }
?>

数据库类:

<?php
    class database
    {
        function __construct($pdo)
        {
            $this->pdo = $pdo;
        }

        function getData()
        {
            $query = $this->pdo->prepare('SELECT * FROM database');
            $query->execute();
            return $query->fetchAll();
        }
    }
?>

index.php:

<?php
    require_once 'config.php';
    require_once 'database.class.php';
    $db = new database($pdo);
    $rows = $db->getData();
?>

5
使用自动加载和依赖注入容器可以改善与数据库的连接方式。以下是使用Auryn连接到数据库的方法,确保只有一个连接处于打开状态,并且无需在应用程序中手动引入文件。
本文仅介绍PDO和Auryn。还有其他依赖注入容器,特别是mysqli扩展连接数据库,但本文内容可帮助您使用其他容器。 数据库类 拥有一个数据库类是多余的。PDO类已经提供了查询数据库所需的所有方法。拥有数据库类会重复这些功能并限制您的操作(或让您创建许多函数),例如,在特定方法中根据需要使用多个不同的获取样式。 依赖注入 如果你还没有阅读过关于依赖注入的文章,建议先阅读。重点是当一个类需要访问数据库时,它不应该自己构造\PDO对象,而应该由其他地方构造并传递给它。
class Mapper {
    private $pdo;
    public function __construct(\PDO $pdo) {
        $this->pdo = $pdo;
    }
    public function createFromId($id) {
        $stmt = $this->pdo->prepare("SELECT name FROM foo WHERE id=:id");
        $stmt->execute([
            ":id" => $id,
        ]);
        return $stmt->fetchObject();
    }
}

请注意,我直接传递了\PDO对象,而不是包装类。这样,我总是可以访问它的所有功能,而不仅仅是用户定义函数的子集。
依赖注入容器有助于构建您的类,为它们提供所需的对象,并为您提供如何实际构建这些对象的极大灵活性。在这里,我只关注通过使用Auryn来配置和共享\PDO对象。
我假设您已经安装了所需的Auryn类,更简单的方法是使用composer。这超出了本答案的范围,有多个资源可用于学习如何使用它。
  • Create the injector

    $injector = new \Auryn\Injector();
    
  • Define the \PDO class parameters

    $injector->define("PDO", [
        ":dsn" => "mysql:host=localhost;charset=utf8;dbname=dbname",
        ":username" => "user",
        ":passwd" => "passwd",
        ":options" => [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false,
        ],
    ]);
    

    You can either write the configuration parameters directly here, or get them from a config file. I like having a config.ini file and using parse_ini_file() to get my configuration options, as I can easily switch databases by editing a config file.

  • Share the \PDO object

    $injector->share("PDO");
    

    This part is really important. This lines makes the injector give the same \PDO object every time it is tasked with constructing a class that needs a connection. Note that the order of the lines is not important, you can share the class before defining it, only make sure to create you database needing classes after writing both those lines.

  • Create your objects

    $mapper = $injector->make("Mapper");
    

    That's it. The injector will create your mapper object, creating the \PDO object if it haven't already been, passing the existing instance if it has.

自动加载

假设您已经使用了Composer,您可以使用其优秀的自动加载器。否则,您也可以自己编写自动加载器

重点在于停止在代码中到处使用require(),特别是如果您在单一职责兼容的类系统中拥有复杂的类层次结构。

总结

通过这个设置,您现在可以在类中使用\PDO对象,同时确保每个请求只有一个实例,无需在各处引用文件,并且不使用单例反模式。


1
简单易懂的解释 - Linus

-1
$database = new Connection();
class Connection
{
 function __construct()
 {
    switch($_SERVER['DOCUMENT_ROOT'])
    {
        case 'path':
            $this->host = 'hostname';
            $this->user = 'username';
            $this->passwd = 'password';
            $this->database = 'dbname';
            break;
        default :
            $this->host = 'localhost';
            $this->user = 'root';
            $this->passwd = 'root';
            $this->database = 'dbname';
            break;
    }
    $this->clink = @mysql_connect($this->host,$this->user,$this->passwd);
    @mysql_select_db($this->database,$this->clink);         
 }
}

-3
class Database{
    var $last_query; //Saved result of the last query made
    var $last_result; //Results of the last query made
    var $func_call; //A textual description of the last query/get_row/get_var call
    var $link; //database link
    var $lastquery; //last query
    var $result; //query result

    // Connect to MySQL database
    function database() {
        $this->link=mysql_connect(DB_HOST, DB_USER, DB_PASS) or die('Server connexion not possible.');
        //Set All Charsets to UTF8
        mysql_query("SET character_set_results=utf8 , character_set_client=utf8 , character_set_connection=utf8 , character_set_database=utf8 , character_set_server=utf8");
        mysql_select_db(DB_NAME) or die('Database connection not possible.');
    }
    /** Query the database.
      * @param $query The query.
      * @return The result of the query into $lastquery, to use with fetchNextObject().
      */
    function query( $query ){
        $this->lastquery=$query;
        $this->result=@mysql_query( $query, $this->link );
        return $this->result;
    }
    /** Do the same as query() but do not return nor store result.
      * Should be used for INSERT, UPDATE, DELETE...
      * @param $query The query.
      * @param $debug If true, it output the query and the resulting table.
      */
    function execute($query)
    {
      @mysql_query($query);
    }
    /** Convenient method for mysql_fetch_object().
      * @param $result The ressource returned by query().
      * @return An ARRAY representing a data row.
      */
    function fetchArray($result){
    if ($result == NULL)
        $result = $this->result;
    if ($result == NULL || mysql_num_rows($result) < 1)
        return NULL;
    else
        return mysql_fetch_assoc($result);
    }

    /** Close the connecion with the database server.
      * It's usually unneeded since PHP do it automatically at script end.
      */
    function close()
    {
      mysql_close($this->link);
    }
    /** Get the number of rows of a query.
      * @param $result The ressource returned by query(). If NULL, the last result returned by query() will be used.
      * @return The number of rows of the query (0 or more).
      */
    function numRows($result = NULL)
    {
      if ($result == NULL)
        return @mysql_num_rows($this->result);
      else
        return mysql_num_rows($result);
    }
}

-3
$objConn = new mysqlconnect(); $Conn = $objConn->setobjConnect("localhost","root","P@ssw0rd");

3
您应该稍微扩展一下您的回答,仅粘贴原始代码而没有任何解释对提问者和社区都没有帮助。如果您需要指导,请参考帮助中心上的“如何撰写好答案”指南。http://stackoverflow.com/help/how-to-answer - MacK

-6
![<?php
class mysqlconnect{
private $server=null;private $user=null;private $password=null;private $objConnect=null;
function setobjConnect($s,$u,$p){
$this->server = $s;
$this->user = $u;
$this->password = $p;
return $this->objConnect = mysql_connect($this->server,$this->user,$this->password);
}
}
$objConn = new mysqlconnect();
$Conn = $objConn->setobjConnect("localhost","root","P@ssw0rd");
if($Conn)
    {
        echo "Database Connect";
    }
    else
    {
        echo "Database Connect Failed.";
    }
mysql_close($Conn); 

?>]

1


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接