Loading [MathJax]/jax/output/CommonHTML/config.js
社区首页 >问答首页 >创建一个databaseDo()函数来挂钩PDO查询

创建一个databaseDo()函数来挂钩PDO查询
EN

Stack Overflow用户
提问于 2012-09-15 02:40:25
回答 2查看 166关注 0票数 5

因此,我开始使用this tutorial作为PDO的简介。到目前为止,我只处理过基本的mysql_*类型查询。

我注意到,在整个教程中,connect -> do action -> disconnect模式都是重复的,只有do action部分会发生变化。

在现实世界中,通过创建一个可以传递查询的函数来消除重复是不是一个好主意?

例如:

用于处理查询的函数:

代码语言:javascript
代码运行次数:0
复制
<?php
function databaseDo($action) {
    $db_hostname = 'localhost';
    $db_username = 'root';
    $db_password = 'root';

    try {
        // Establish DB connection
        $dbh = new PDO("mysql:host=$hostname;dbname=mysql", 
                $db_username, $db_password);
        echo 'Connected to database';

        // Do something
        $action($dbh);        // <- here goes whatever action we wish to perform

        // Close connection
        $dbh = null;
    } 
    catch(PDOException $e) {
        echo $e->getMessage();
    }
?>

然后,假设我想要执行PDO教程的第一个示例中的操作,我会这样设置它:

代码语言:javascript
代码运行次数:0
复制
<?php
// Define action
$insert = function($dbh) {
    $query = "INSERT INTO animals(animal_type, animal_name)
                VALUES ('kiwi', 'troy')";
    $exec = $dbh->exec($query);
    echo $exec; 
};

// Perform action
databaseDo($insert);
?>

$dbh的范围

我使用$dbh作为参数。这是将变量传递给这样的函数而不使其成为全局变量的正确方式吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-09-15 03:18:03

是的,这是一个很好的想法,一个建议是创建一个使用单例模式的数据库助手类。就像这样

代码语言:javascript
代码运行次数:0
复制
abstract class DB
   {

    protected static $instance;

    protected $db;

    protected static $host = 'host';
    protected static $user = 'user';
    protected static $pass = 'pass';
    protected static $database;

    public static function getInstance()
    {
        if (!isset(self::$instance)) self::$instance = new static();

        return self::$instance;
    }

    public static function doStatement($statement, array $parameters)
    {

         $handler = self::sql()->prepare($statement);
         $handler->closeCursor();
         $handler->execute($parameters);
         return $handler;
    }
    protected function __construct()
    {
        $this->db = new PDO(sprintf('mysql:host=%s;dbname=%s', static::$host, static::$database), static::$user, static::$pass);
        $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

    }

    public static function db()
    {
        return static::getInstance()->db;
    }
}

class Main extends DB
{
    protected static $database = 'db';
}

使用它

代码语言:javascript
代码运行次数:0
复制
$db = Main::getInstance();
$results = $db::doStatement('SELECT * FROM table WHERE id = :id', array(':id' => 5));

现在这只是非常基本的,还需要添加更多(异常处理,更多/更好的助手方法等),但我已经在许多项目中使用了类似的东西。

票数 4
EN

Stack Overflow用户

发布于 2012-09-15 04:39:02

虽然避免重复(DRY)是一个应该始终考虑到您的编码决策的原则,但它应该在不违反另一个重要原则的情况下实现,即关注点分离(SoC,另请参阅SRP)。您的示例databaseDo($action)有两个用途:(1)实例化一个数据库连接,(2)执行一个查询。

现在,你可能会说,‘是的!这正是我想要的!一举两得!’,你这样说的理由是可以理解的。然而,混合职责可能会变得有问题,因为当您必须更改处理一个职责的方式时,您很可能也必须更改处理另一个职责的方式。

想象一下,在将来的某个时刻,您需要支持两个数据库连接,而不是只支持一个。假设两个数据库中的一个支持表上的事务,而另一个不支持。您的databaseDo()函数首先必须协商连接到哪个数据库,然后,为了安全地执行“do”操作,将需要一些事务支持测试。它看起来像这样:

代码语言:javascript
代码运行次数:0
复制
$context = 'production'; // but it could equally be 'development'

function databaseDo($action) {
  $db_hostname = ($context == 'production') ? 'http://remotehost.com' : 'localhost';
  $db_username = ($context == 'production') ? 'apache' : 'root';
  $pass = ($context == 'production') ? 'productionpassword' : 'developmentpassword';

  try {
    $dbh = new PDO("mysql:host=$db_hostname;dbname=mysql", $db_username, $db_password);
    echo 'Connected to database';

    if($context == 'production') {
      // ... some complicated logic to determine whether the production db 
      // will support your query, then execute it if so, exit if not ... 
    }

    if($context == 'development') {
      // ... some more complicated logic for testing and querying the 
      // development db ...
    }

    $dbh = null;
  } catch(PDOException $e) {
    echo $e->getMessage();
  }
}

处理一个职责的额外需求将增加处理第二个职责的复杂性,并且此功能将变得越来越难以维护。

在这种情况下,更好的DRY方法是在一个组件中处理数据库连接管理,例如在上下文感知的单例类实例中(一种常见的方法),而在另一个组件中处理查询处理。因此,您的查询函数不一定要因为数据库连接处理的更改而更改。您提到的教程包含instructions for creating and using such a singleton instance

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12434093

复制
相关文章
[php][零散代码]php日期计算
[php][零散代码]php日期计算 <?php $startData = "2020-01-1"; $stopData = "2020-01-31"; $s = new \DateTime(
landv
2020/04/25
2.6K0
PHP-包含文件
5、包含文件相当于把包含文件中的代码拷贝到主文件中执行,魔术常量除外,魔术常量获取的是所在文件的信息。
cwl_java
2020/03/26
1.3K0
php日期处理代码
<?php echo "<pre>"; echo date("Y-m-d",strtotime("now")), "\n"; echo "<pre>"; echo date("Y-m-d",strto
用户7108768
2021/09/22
5K0
PHP 日期相关函数
设置时区 date_default_timezone_get(); date_default_timezone_set('PRC'); 时间戳 time(); 得到指定时间的时间戳 mktime( [$hour, $min, $sec, $mon, $day, $year]); 将英文文本的日期或时间转换成时间戳 strtotime($time [, $now]); strtotime('+1 day'); 微秒 microtime( [$get_as_float]); microtime(true)
康怀帅
2018/02/28
1.9K0
php文件包含日志getshell
好久之前,看到过一篇文章,是利用文件包含漏洞,包含的日志文件进行的getshell,看到文章后就感觉,思路不错,不禁反思,为什么当时碰到文件包含的时候没有想着用这些方法来测试,今天就特地写一篇来记(水)录(文)一下,内容很少,看着就当图一乐
Elapse
2021/03/03
2K0
php文件包含日志getshell
文件包含、PHP伪协议
当使用include()函数包含文件时,只有代码执行到 include() 函数时才将文件包含进来,发生错误时只给出一个警告,继续向下执行。
字节脉搏实验室
2020/12/21
2.7K0
文件包含、PHP伪协议
【说站】php包含字符
strpos函数返回boolean值。strpos的执行速度比其他函数快。另外,strpos有参数指定的判断位置,但默认为空。意思是判断整个字符串。缺点是对中文的支持不好。
很酷的站长
2022/11/23
1.5K0
【说站】php包含字符
php获取农历日期节日
$c = new DayService(); $today=$c->convertSolarToLunar(date('Y'),date('m'),date('d')); $time ="农
IT工作者
2022/03/01
8K0
PHP 文件包含漏洞姿势总结
文件包含漏洞的产生原因是在通过 PHP 的函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。
信安之路
2018/08/08
4.2K0
PHP 文件包含漏洞姿势总结
PHP 实现公历日期与农历日期的互转换
PHP 实现公历日期与农历日期的互转换 前言:  今天根据客户的需求对时间进行了转换,就是客户要求增加农历日期的显示,在网上抄袭了一段,稍微修改了一下运行成功了,不难的,改动的很少的.
用户2323866
2021/07/07
5.5K0
strftime 中文 python格式化日期包含中文 出错
想用python获取当前时期, 格式是2018年1月1日,结果出现上面错误, 处理方法
ClearSeve
2022/02/11
1.2K0
strftime 中文 python格式化日期包含中文 出错
PHP远程文件包含(RFI)并绕过远程URL包含限制
本文我们讲如何绕过远程URL包含限制。在PHP开发环境php.ini配置文里”allow_url_fopen、allow_url_include“均为“off”的情况下,不允许PHP加载远程HTTP或FTP的url进行远程文件包含时。我们依旧可以使用SMB,来加载执行远程文件。
Ms08067安全实验室
2021/04/07
2.8K0
PHP远程文件包含(RFI)并绕过远程URL包含限制
PHP- 日期和时间函数
date(): 获取当前日期和时间 date()函数用于获取当前日期和时间,返回值为一个格式化的日期字符串。
堕落飞鸟
2023/04/26
2K0
php案例:创建日期时间目录
贵哥的编程之路
2023/10/16
1840
php案例:创建日期时间目录
解决后台返回的Timestamp日期数据里包含T
在response entity 的timestamp字段的get方法上添加注解JsonFormat,如:   @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") public Timestamp getUpdateTime() { return updateTime; }
qubianzhong
2018/09/19
1.7K0
PowerQuery 如何获取起止日期内包含的月份?
今天在群里看到一个问题,如何获取起始日期和结束日期之间包含的所有月份,业务逻辑见下图:
披头
2020/05/13
2.3K0
有趣!你会检查单元格是否包含日期吗?
大家知道,Excel将日期存储为数字,只是显示的是日期格式,例如,Excel单元格中显示的是2022年5月10日,但实际上存储的是数字44691。
fanjy
2022/06/04
1.8K0
有趣!你会检查单元格是否包含日期吗?
PHP中的日期相关函数(三)
之前我们已经介绍过了 PHP 的一些相关的日期操作对象,今天我们就来学习剩下的那些面向过程的使用方式。当然,如果是和 DateTime 类中相似的方法我们就不再进行介绍了。另外,Date() 和 time() 这两个非常常用的函数也不会进行介绍,因为大家都已经用滥了,所以我们也就不浪费宝贵的学习资源了。
硬核项目经理
2021/03/16
1.9K0
点击加载更多

相似问题

这是有状态web服务/wcf服务吗?

23

这是托管WCF服务的正确方式吗?

30

如何向WCF服务库添加服务。这是正确的吗?

10

这是WCF服务应用程序的有效使用吗?

36

是否拒绝对Wcf服务的调用?这是web配置的问题吗?

20
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文