【问题标题】:How to connect to MySQL using PDO using PHP function [closed]如何使用 PHP 函数使用 PDO 连接到 MySQL [关闭]
【发布时间】:2019-12-24 22:21:04
【问题描述】:

我正在使用这种方法将我的 MySQL 数据库连接到 SELECT、INSERT、UPDATE 和 DELETE 数据。这是cnn() 函数:

function cnn() {
    static $pdo;
    if(!isset($pdo)) {
        $settings = [
            PDO::ATTR_TIMEOUT => 30,
            PDO::ATTR_PERSISTENT => false,
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
        ];
        try {
            # settings
            $config['db']['host'] = 'example.com';
            $config['db']['name'] = 'db';
            $config['db']['user'] = 'username';
            $config['db']['pass'] = '****************';
            $pdo = new PDO('mysql:host='.$config['db']['host'].';dbname='.$config['db']['name'], $config['db']['user'], $config['db']['pass'], $settings);
            return $pdo;
        } catch(PDOException $e) {
            http_response_code(503);
            echo $e->getCode().': '.$e->getMessage();
        }
    } else {
        return $pdo;
    }
}

然后我可以这样做,以便在每次我在同一个请求上需要它时重复使用同一个 pdo 对象。

第一次查询

$sql = 'INSERT INTO user (name, lastname) VALUES (:name, :lastname)';
$stmt = cnn()->prepare($sql);
$stmt->bindValue(':name', "John", PDO::PARAM_STR);
$stmt->bindValue(':name', "Wayne", PDO::PARAM_STR);
$stmt->execute();

第二次查询

$sql = 'SELECT * FROM user WHERE id_user = :id_user';
$stmt = cnn()->prepare($sql);
$stmt->bindValue(':id_user', 4641, PDO::PARAM_INT);
$stmt->execute();
$user = $stmt->fetch();

我想知道使用这种方法是否会出现任何性能问题。谢谢。

【问题讨论】:

  • 看起来不错,因为连接只会运行一次。但我不确定你为什么使用二维数组作为“配置”,因为它是一个局部变量
  • “看起来不错” @HTMHell 不,这不是很好,请注意 static $pdo.... 后面的代码应该是 if(!isset(self::$pdo)) { , self::$pdo = new PDO('mysql:host='.) , return self::$pdo; 或::..之前的类名。
  • 这个问题属于codereview.stackexchange.com
  • @RaymondNijland 这显然是一个类之外的函数,正如您在他的示例中看到的那样。大家可以看看这个question的答案,了解static的不同用途。
  • @HTMHell 感谢我并不真正需要的解释,因为我知道 PHP 中的静态或 OOP 编程是如何工作的,相信我,我对静态关键字的评论是一般评论...... “这显然是一个类之外的函数,正如你在他的示例中看到的那样” 是的,我同意我应该在评论中说,当使用类时,你也可以在 @987654338 之前使用 Classname 而不是 self @

标签: php mysql pdo


【解决方案1】:

1)

作为referenced by HTMHell,您的$config 数组在这里是本地的,我认为应该在使用后将其删除,这样密码变量就不会在以后的get_defined_vars() 调用或类似的交叉引用中泄漏。

2)

对我来说,将你的函数放在一个类中似乎更合乎逻辑。从__construct 运行cnn() 函数。将这个函数封装在一个完整的类中有很多积极的方面。

3)

不要不将任何变量设置为static,除非在将cnn() 函数放入类的上下文中有specific requirement。

4)

正确使用您的try{ ... } catch { ... } 块,不要将其他代码包装在抛出异常的try 块中except 代码。

    // settings
    $config['db']['host'] = 'example.com';
    $config['db']['name'] = 'db';
    $config['db']['user'] = 'username';
    $config['db']['pass'] = '****************';
    try {
        $pdo = new PDO('mysql:host='.$config['db']['host'].';dbname='.$config['db']['name'], $config['db']['user'], $config['db']['pass'], $settings);
    } catch(PDOException $e) {
        /***
         * Do you really need this, here?  
         * //http_response_code(503);
         **/
        echo $e->getCode().': '.$e->getMessage();
    }
    return $pdo;

5)

永远不要将错误直接输出到屏幕上

错误should be logged,因此只有服务器人员和开发人员而不是普通公众可以看到它们。这也意味着您有一个错误日志,而不是任何发生的单个临时实例。

echo $e->getCode().': '.$e->getMessage(); 应该是:

error_log($e->getCode().': '.$e->getMessage());

或类似的。保持一致;总是返回一个 PDO 对象而不是 echo 输出。

6)

删除您的最终else 包装器,它只是杂乱无章。

if(!isset($pdo)) {
     ...
} 
return $pdo; 

同时删除try { ... } 块内的return $pdo;。不要重复自己。

7)

Properly document your code:

/***
 * For generating or asserting a PDO Database Object.
 * @return Returns the PDO object 
 ***/
 function cnn() {

回答您实际提出的问题:

我想知道使用这种方法是否会出现任何性能问题。

这个问题太笼统了,可以自己用timer testings或者其他方法(详见链接)在你的系统上确定是特别高效还是低效,或者你选择给它什么SQL。 ..

【讨论】:

  • self::$pdo 在函数中是完全错误的。在开发过程中,在屏幕上显示错误相当方便。想想吧。全局静态包装器不受欢迎是有原因的
  • @YourCommonSense 我认为在开发过程中将错误放在屏幕上是非常不明智的,它开创了一个不好的先例,并且意味着报告的错误总是暂时的,并且有被转移到实时站点的风险。
  • 我认为让每个小功能决定将其错误消息指向何处是非常不明智的。调试模式只要通过单个配置选项打开和关闭就没有问题。
  • 告诉操作人员不要理会他们的例外情况,这绝不是“远远超出”您愿意编写的任何深度。零错误日志和零回显实际上更好
  • 关于错误报告,要么重新抛出异常,要么完全摆脱 try-catch。它在这里没有真正的用途。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-21
  • 2013-02-14
  • 1970-01-01
  • 2023-04-01
  • 2021-02-25
  • 2013-07-19
相关资源
最近更新 更多