在多个php文件中正确使用mysql数据库的方法

3

大家好,我正在思考在mysql数据库中对多个表进行查询的最佳方法。我是否应该为每个不同的.php页面创建一个新的mysqli对象($mysqli = new mysqli("localhost", "root", "root", "db");)?

还是有一种方式可以在我的网站中所有php文件上重用这个对象?有什么建议吗?

4个回答

2
我的建议是采用面向对象编程的方法。我会创建一个脚本,其中包含一个数据库连接类和该类中的一个方法来检查连接是否存在,如果存在,则返回连接对象。您可以在需要访问数据库的页面上引用该db类脚本 [ include_once(); ] 。然后,只需实例化db对象,触发“if-exists”方法,如果它返回true,则利用对象内部的现有连接即可。
您还可以考虑使用持久连接到数据库。

Persistent connections

但是,老实说,为了长期运行和应用程序的可扩展性,最好自己处理数据库连接管理,而不是保持连接处于打开状态。这是我如何构建该类的示例: 注意:@alex提醒,在显示所有警告的环境中(例如error_reporting(E_WARNING);),不应将mysql_error()输出到页面。
class dbconn {
protected $database;

function __construct(){
    $this->connect();
}

protected function connect() {
    $this->database = mysql_connect('host', 'user', 'pass')  or die("<p>Error connecting to the database<br /><strong>" . mysql_error() ."</strong></p>" );
    mysql_select_db('databasename') or die("<p>Error selecting the database<br />" . mysql_error() . "</strong></p>");
}

function __destruct(){
    mysql_close($this->database);
}

function db(){
     if (!isset($this->database)) { 
        $this->connect(); 
     }
     return $this->database;
  }

  }

2
这是我见过的最出色的数据库连接类。 - Infotekka
@alex - 好的,你对于die()函数不太优雅确实有道理,因此可以进行修改。但即使是连接失败时mysql_error()函数也不会丢失连接字符串数据,它只会给出行号和连接失败状态。你能准确地指出什么情况下mysql_error()函数会泄露敏感数据吗? - a.stgeorge
如果display_errors设置为false,则在错误时不应该回显任何内容,这在生产服务器上是必须的。并且,应该将该信息记录下来,而不是通过添加@前缀或类似方式默默忽略它,因为可能还涉及其他(意外的)错误,例如Fatal error: Call to undefined function mysql_connect。我曾经在PHP/Oracle中遇到过这种情况 - 在迁移到新服务器后,花了一些时间才找出为什么看不到输出和没有错误记录。但由于用户/密码是由用户输入的,所以必须保留该@前缀... - binaryLV
如果我要创建终极的DB包装器,我会忘记display_errors并且不会使用die。所采取的行动不应该取决于display_errors的值 - 它只是一个配置值,指定是否打印错误消息 - 对于开发来说不可替代,对于生产来说致命。而die不是一个好的结果,因为它不是dbconn应该决定用户是否应该看到错误消息或执行脚本是否应该静默停止。使用dbconn类的代码必须决定它。 - binaryLV
@a.stgeorge,那个受保护的$dbc是对象属性,而不是类属性。对于新对象,它的值最初为NULL - binaryLV
显示剩余10条评论

1

你需要为每个页面创建连接,因为每个 PHP 脚本的生命周期都是请求的时间。

但是,你可以将连接代码放在一个文件中,然后从所有页面中 include 它。


@NullUserException 你说得对。但是我认为我应该保持简单,因为楼主似乎没有太多经验。 - alex
@astgeorge 我认为对问题的解释与我的不同。 - alex
@binary 只有在你使用完连接后未关闭时,创建连接才会变得昂贵。 - a.stgeorge
1
@alex,虽然它声称资源会自动释放,但是我曾经在过去遇到过一些奇怪的问题(关于DB资源的错误消息),当时我没有使用mysql_free_result()。这些问题并不是在每个使用DB的地方都出现,而是在某些特定的地方。添加了mysql_free_result()之后,这些问题就消失了。 - binaryLV
1
@a.stgeorge,连接池的工作原理是这样的 - 它保存了打开的连接数量;当您请求连接时,它会给您打开的连接或创建新连接;当您释放连接时,它会存储到池中,以便在另一个请求中使用。因此,如果每秒有50个连接请求,每个连接被“保留”20毫秒,那么只需要1个连接池连接就足以满足每个连接请求。 - binaryLV
显示剩余16条评论

0
你可以创建一个 connect.php 文件,验证它被你的应用程序包含,并创建一个数据库连接。
然后,在你的应用程序初始化或任何需要连接的独立脚本的开头包含该文件 =)

-1

这取决于网站的结构。如果您有:

<a herf='login.php'>login</a>
<a herf='register.php'>register</a>
<a herf='about.php'>about</a>

...然后你需要在每个PHP文件中连接,例如在login.phpregister.phpabout.php中。为了使它更容易,我会创建一个包含用户名/密码的config.php文件,或者像Shad说的那样


你可能也有一个包含以下内容的index.php文件:

if ( !isset($_GET['module']) ) {
    $_GET['module'] = 'about';
}
switch ( $_GET['module'] ) {
    default:
    case 'about':
        include 'about.php';
        break;
    case 'login':
        include 'login.php';
        break;
    case 'register':
        include 'register.php';
        break;
}

还有HTML代码:

<a herf='?module=login'>login</a>
<a herf='?module=register'>register</a>
<a herf='?module=about'>about</a>

在这种情况下,您可以在index.php中连接,然后将连接传递给所有其他相关文件。

对我来说,第二种方法似乎更常见,即更直观、更方便,这也是我经常使用的。

我相信,在某些情况下,使用持久连接并在需要时保留/释放连接(无论是为事务还是单个查询)可能是值得的(从性能角度考虑)。例如,我现在正在使用的简单系统需要70ms-100ms才能生成,而执行SQL查询只需要40ms-50ms。如果采用“单一连接”方法,这意味着连接在大约50%的时间内被浪费,而使用持久连接的“保留/释放连接”方法则不会有这样的问题。

还有一件事——我建议您创建一些包装器,即一些DBConnection类,它在构造函数中连接到数据库,并具有像select()(返回数据数组)、selectValue()(返回单个值,例如$db->selectValue('select count(*) from user')将返回(int)$numberOfUsers)、一些插入和更新的exec()等方法。


说实话,我不确定你的代码片段想要展示什么。 - a.stgeorge
这会是一个被踩的原因吗?你到底不理解什么? - binaryLV
我没有给你点踩,只是说我不理解。问题是关于在每个页面加载时创建数据库连接,但在你的代码片段中,你并没有展示任何关于数据库连接的内容,只是一个用于包含可能有或没有连接的不同页面的开关。 - a.stgeorge
@a.stgeorge,我真的不明白作者所说的拥有许多PHP文件的含义。例如,我目前在我的系统中有大约100个PHP文件,其中15个需要直接访问数据库。作者可能与我有类似的结构(在这种情况下,只需要一个地方连接到DB,例如公共的 index.php 文件),或者像我给出的第一个代码片段那样(在这种情况下,他需要一种从代码中的许多地方创建连接的方法,因为可能没有通用的初始化脚本)。 - binaryLV
不管你投赞成票还是反对票都没关系,我只是不明白为什么我会被踩票了 ;) - binaryLV
显示剩余2条评论

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