在PHP中为PDO查询创建容器函数

在PHP中为PDO查询创建容器函数,php,mysql,function,pdo,simplify,Php,Mysql,Function,Pdo,Simplify,因为我发现PDO执行非常难以记忆,而且我会回顾以前的项目或其他网站,只是为了记住如何从数据库中选择行,所以我决定尝试创建自己的函数,其中包含PDO执行,并插入所需的数据。虽然看起来比实际情况简单得多 到目前为止,我已经成功地创建了一个connect函数,但是现在当我要创建一个select函数时,我遇到了多种原因。 首先,可以传递到函数中的参数数量可能会不断变化,其次,我无法确定应该传递给函数什么以及传递的顺序 到目前为止,函数看起来是这样的。为了让我保持清醒,我在其中添加了“id”部分,这样我可

因为我发现PDO执行非常难以记忆,而且我会回顾以前的项目或其他网站,只是为了记住如何从数据库中选择行,所以我决定尝试创建自己的函数,其中包含PDO执行,并插入所需的数据。虽然看起来比实际情况简单得多

到目前为止,我已经成功地创建了一个connect函数,但是现在当我要创建一个select函数时,我遇到了多种原因。
首先,可以传递到函数中的参数数量可能会不断变化,其次,我无法确定应该传递给函数什么以及传递的顺序

到目前为止,函数看起来是这样的。为了让我保持清醒,我在其中添加了“id”部分,这样我可以看到在最终结果中我需要完成什么,并在我确定如何完成时被相应的变量替换

到目前为止,我已经确定函数需要做的是

  • 连接到数据库(使用另一个函数生成$conn变量,已完成)
  • 选择表格
  • 指定列
  • 提供匹配的输入
  • 允许使用可能的参数,例如
    按“id”描述排序
最后,我需要创建一个函数来插入、更新和删除数据库中的行

或者,有没有比函数更好的方法来实现这一点

如果有人能帮助我实现简化PDO执行的雄心壮志,我将不胜感激。提前谢谢

。并发现自己在回顾以前的项目或其他 网站只是为了记住如何从数据库中选择行

仅供参考,我们都这么做

PDOAPI有一个问题,现在有两个问题。我最好也是最强烈的建议是:如果您想要一个更简单/不同的数据库API,不要使用自己的数据库API。搜索一个看起来不错的ORM或DBAL,并使用它代替PDO


其他人已经为你做了这项工作。使用他们的工作,而不是专注于你的应用程序所独有的任何令人敬畏的东西。聪明地工作,不要努力等等。

哼。。。IMHO我认为您不应该尝试在函数中包装PDO,因为它们已经在方法中“包装”了。事实上,从面向对象到过程似乎是倒退(或者至少是朝着错误的方向迈出了一步)。PDO是一个很好的库,它有很多方法和特性,如果将它们封装在简单的可重用函数中,那么这些方法和特性肯定会丢失

其中一个功能是BeginTransaction/Rollback(请参阅更多)

无论如何,从OOP的角度来看,您可以通过添加一些简单的方法来修饰PDO对象本身

下面是一个基于函数的示例

注意:此代码未经测试

class MyPdo
{
    public function __construct($conn)
    {
        $this->conn = $conn;
    }
    

    public function pdo()
    {
        return $this->conn;
    }

    public function selectAllById($table, $id = null)
    {
        $query = 'SELECT * FROM :table';
        $params = array('table'=>$table);
        if (!is_null($id)) {
            $query .= ' WHERE id = :id';
            $params['id'] = $id;
        }
        $r = $this->conn->prepare($query)
                  ->execute($params)
                  ->fetchAll();
        //More stuff here to manipulate $r (results)
        return $r;
    }

    public function __call($name, $params)
    {
        call_user_func_array(array($this->conn, $name), $params);
    }
}
注意:此代码未经测试

class MyPdo
{
    public function __construct($conn)
    {
        $this->conn = $conn;
    }
    

    public function pdo()
    {
        return $this->conn;
    }

    public function selectAllById($table, $id = null)
    {
        $query = 'SELECT * FROM :table';
        $params = array('table'=>$table);
        if (!is_null($id)) {
            $query .= ' WHERE id = :id';
            $params['id'] = $id;
        }
        $r = $this->conn->prepare($query)
                  ->execute($params)
                  ->fetchAll();
        //More stuff here to manipulate $r (results)
        return $r;
    }

    public function __call($name, $params)
    {
        call_user_func_array(array($this->conn, $name), $params);
    }
}

奥姆 另一个选项是使用,它可以让您直接与模型/实体交互,而无需费心创建/销毁连接、插入/删除等。。。Doctrine2或spreep是PHP的好选择


然而,ORM比直接使用PDO要复杂得多。

编写包装器,应该从连接数据库的表单开始,所有可能的方法都可以包装。将连接传递给查询方法看起来不太好

一个非常粗略的例子是下面的代码,我强烈不建议这种混合,但它会给你方向

您应该从构造函数或从构造函数中调用的另一个方法建立连接,您可以使用以下方法:

public function __construct($driver = NULL, $dbname = NULL, $host = NULL, $user = NULL, $pass = NULL, $port = NULL) {
        $driver     = $driver   ?: $this->_driver;
        $dbname     = $dbname   ?: $this->_dbname;
        $host       = $host     ?: $this->_host;
        $user       = $user     ?: $this->_user;
        $pass       = $pass     ?: $this->_password;
        $port       = $port     ?: $this->_port;
        try {
            $this->_dbh  = new PDO("$driver:host=$host;port=$port;dbname=$dbname", $user, $pass);
            $this->_dbh->exec("set names utf8");
        } catch(PDOException $e) {
            echo    $e->getMessage();  
        }
    }
因此,您可以在实例化包装器时传递连接凭据,也可以使用默认凭据

现在,您可以创建一个只接收查询的方法。编写整个查询比传递表和列更合适。它不会形成一个完整的ORM,但只会使代码更难阅读

在我第一次处理PDO时,我希望一切都是动态的,所以我实现了,后来我意识到是不成熟的编码风格,但让我们展示一下

public function query($sql, $unset = null) {
    $sth = $this->_dbh->prepare($sql);

    if($unset != null) {
        if(is_array($unset)) {
            foreach ($unset as $val) {
                unset($_REQUEST[$val]);
            }
        }
        unset($_REQUEST[$unset]);
    }

    foreach ($_REQUEST as $key => $value) { 
         if(is_int($value)) {
             $param = PDO::PARAM_INT;
         } elseif(is_bool($value)) {
             $param = PDO::PARAM_BOOL;
         } elseif(is_null($value)) {
             $param = PDO::PARAM_NULL;
         } elseif(is_string($value)) {
             $param = PDO::PARAM_STR;
         } else {
             $param = FALSE;   
         }
         $sth->bindValue(":$key", $value, $param);
    }

    $sth->execute();
    $result = $sth->fetchAll();

    return $result;

}
那么这些意大利面条都有什么作用呢

首先,我想我希望所有的post值都作为参数发送,所以如果我有

input name='user'
input name='password'
我可以做
$res=$db->查询(“从username=:user和password=:password的用户中选择id”)

还有塔达!我已经获取了这个查询的结果,$res现在是一个包含结果的数组

后来我发现,如果我有

input name='user'
input name='password'
input name='age'
在相同的表单中,但是查询仍然使用
:user
:password
并且我提交表单,被调用的查询将在绑定参数中提供不匹配,因为foreach与$\u请求数组将绑定3个参数,但在查询中我使用2个

因此,我在方法的开头设置了代码,在这里我可以提供要排除的内容。调用方法,如
$res=$db->query(“从username=:user和password=:password的用户中选择id”,“age”)给了我这样做的可能性

它起作用了,但还是不行

最好有一个
query()
方法来接收两件事:

  • 带有参数名称的SQL字符串
  • 参数为数组
因此,您可以对bindValue使用
foreach()
逻辑,但不能在超全局数组上使用,而是在传递的数组上使用

然后,您可以包装fetch方法

public function fetch($res, $mode = null)
您不应该直接从查询返回fetch,因为它可能是UPDATE、INSERT或DELETE

只需将$res变量传递给
fetch()
方法,以及类似PDO::fetch_ASSOC的模式。可以在fetch ASSOC的位置使用默认值,如果传递其他内容,则使用默认值

不要像我开始时那样抽象。它会让你最近填补裂缝。

首先,我不知道你从哪里得到10行 是您需要的所有代码,并且
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = ?');
$stmt->execute(array($id));
$result = $stmt->fetchAll();