Php 自定义mysqli准备函数

Php 自定义mysqli准备函数,php,class,mysqli,prepared-statement,bindparam,Php,Class,Mysqli,Prepared Statement,Bindparam,我现在正在做我自己的第一个数据库类,目前我正在做prepare函数 此函数的作用是接收SQL查询,然后接收包含语句变量的数组。我在将参数绑定到语句时遇到问题 这就是函数现在的样子 public function prepare($query, $var) { $types = ''; foreach($var as $a) { $type = gettype($a); switch($type) { case 'intege

我现在正在做我自己的第一个数据库类,目前我正在做prepare函数

此函数的作用是接收SQL查询,然后接收包含语句变量的数组。我在将参数绑定到语句时遇到问题

这就是函数现在的样子

public function prepare($query, $var) {
    $types = '';
    foreach($var as $a) {
        $type = gettype($a);
        switch($type) {
            case 'integer':
                $types .= 'i';
                break;

            case 'string':
                $types .= 's';
                break;

            default:
                exit('Invalid type: ' . $a .' ' . $type . '(' . count($a) . ')');
                break;
        }
    }

    $stmt = self::$connection->prepare($query);
    $stmt->bind_param($types, $var); // How do I do here??
    $stmt->execute();
    $result = $stmt->get_result();
    while($row = $result->fetch_assoc()) {
        print_r($row);
    }
}

一切都按我所希望的那样工作(我知道这个函数可以做一些修饰,但它做了它需要做的事情)。我已经评论了我在想该怎么做时遇到的问题$var是一个数组,如果我能正确地回忆起这些变量,就需要用逗号分开传递。这就是我不懂的地方。

您自己的数据库类的想法非常棒。
这里很少有人分享它,出于某种原因,他们更喜欢在代码中使用原始api调用。
因此,您又向前迈进了一大步。
然而,以下是一些反对意见:

  • 如果要使用本机准备的语句,请不要将mysqli用于自己的第一个数据库类。
    改用PDO。这会帮你省去很多头疼的事
  • 尽管此功能对您来说工作正常,但它没有多大意义:
    • 开关($type)
      代码块无效。Mysql可以将每个标量值理解为一个字符串,因此您可以毫无问题地将每个值绑定为
      s
    • 大多数来自客户端的整数都有字符串类型
    • 有一些合法类型,如
      float
      NULL
      或可以返回字符串的对象。所以,自动化在这里不起作用。如果要区分不同的类型,则必须实现类型提示占位符
    • 永远不要在脚本中使用
      exit
      <代码>抛出新异常('将错误消息放在这里')
  • 这实际上不是一个prepare函数,因为它也会执行。所以,给它一个更通用的名字
  • 但是现在谈谈你的问题
    这是使用mysqli的直接结果。处理事先准备好的陈述是一场噩梦。不仅是绑定,还包括检索数据(因为
    get\u result()
    并不适用于任何地方,在本地创建应用程序后,您会发现它在共享主机上不起作用)。你可以让自己有一个想法,就是为了这个目的——绑定变量的动态数量

    因此,请尽可能远离mysqli。
    有了PDO,你的函数就这么简单了

    public function query($query, $var=array())
    {
        $stmt = self::$connection->prepare($query);
        $stmt->execute($var);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    // and then used
    $data = $db->("SELECT 1");
    print_r($data);
    
    你可以从中获得一些想法。
    请随意询问有关数据库类的任何问题-这是一件很棒的事情,我很高兴您这样做

    回答评论中的问题

    让你知道,你不是网站的唯一用户。还有一些无辜的游客。与您不同的是,他们不需要任何错误消息,他们会因为一些奇怪的行为和缺乏熟悉的控件而感到害怕

    带有错误消息的exit()会做很多坏事

    • 抛出一条错误消息,向潜在攻击者透露一些系统内部信息
    • 用奇怪的信息吓唬无辜的用户。“那是什么?谁是无效的?是我的错还是什么?或者可能是病毒?最好离开这个网站”——他们认为
    • 在中间杀死脚本,因此可能会导致损坏的设计(或根本没有设计)显示
    • 无法恢复地删除脚本。而抛出的异常可以被捕获并优雅地处理
    当连接到PDO时,不需要在这里抛出任何东西,因为PDO已经抛出了异常。所以,摆脱
    试试。。。捕捉
    ,只留下一行:

    self::$connection = new PDO($dsn, $user, $pass); 
    
    然后创建一个自定义项以在两种模式下工作:

    • 在开发服务器上,让它在屏幕上抛出消息
    • 在实时服务器上,让它记录错误,同时向用户显示一般错误页面
    使用try。。。仅当您不希望整个脚本死亡时捕获-即仅处理可恢复问题

    顺便说一下,PDO默认情况下不会在connect上引发异常。您必须手动设置它:

    $opt = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION );
    self::$connection = new PDO($dsn, $user, $pass, $opt); 
    

    提示:你设置的通用标记越多,你的问题就越吸引注意。它目前只有七个视图,这都要归功于您选择的复杂标记
    php
    总是一个不错的选择。我知道PDO比Mysqli好得多,但我一直懒得切换到PDO,我想我现在就开始吧!为什么我不应该使用exit()?抛出异常和使用exit()有什么区别?这是怎么回事?我也应该在这里抛出异常吗?尝试{self::$connection=new PDO($dsn,$user,$pass);}catch(PDO异常$e){exit('connection failed:'。$e->getMessage();}