【问题标题】:How does this PHP know which array key/values to use?这个 PHP 如何知道要使用哪些数组键/值?
【发布时间】:2010-01-18 02:37:33
【问题描述】:

以下是其他人编写的 PHP 数据库类的一部分,我已经删除了大约 80% 的代码,所有与我的问题无关的代码都已删除,只剩下允许我测试这个类的数量,而无需实际上击中了一个真实的数据库。

这个类有几个方法可以让你设置一个键和值,然后使用数组将它变成一个 mysql UPDATE 和 INSERT sql 查询。我试图弄清楚如何 100% 使用此代码,以便我可以在我自己的应用程序中使用它的此功能进行更新和插入。

基本上从我收集到的你做这样的事情......

// assign some key/values to insert into DB
$db->assign('name', 'dfgd');
$db->assign('age', 87);
$db->assign('sex', 'female');
$db->assign('user_id', 4556);

// Do  the insert
$db->insert('testing2');

现在我感到困惑的是,我可以在页面上一遍又一遍地运行这样的代码,它总是会使用正确的键/值数组集。上面你可以看到我使用了 assign() 方法 4 次,然后调用了 insert() 方法来创建这个

INSERT INTO test (name, age, sex, user_id) VALUES (jason davis, 26, male, 5345)

现在,如果我在同一页面上运行另一个这样的集合...

// assign some key/values to insert into DB
$db->assign('name', 'dfgd');
$db->assign('age', 87);
$db->assign('sex', 'female');
$db->assign('user_id', 4556);

// Do  the insert
$db->insert('testing2');

然后它会创建这个......

INSERT INTO testing2 (name, age, sex, user_id) VALUES (dfgd, 87, female, 4556)

那么它如何不将 2 组 4 组合在一起,所以不是在第二次插入时插入 8 条记录,而是用新的集合完全替换第一组 4 值。这很棒,我想要什么,但我不明白它是怎么发生的?这也可以改进吗?

下面是一个完整的类和我的演示代码,它可以在不需要连接到 mysql 的情况下运行,它将打印以筛选它构建的 SQL。

下面代码中的public函数reset()在什么地方需要用到,还是不需要?

<?php 
class DB{
    public $fields;

    public function assign($field, $value){
        $this->fields[$field] = ($value)==""?("'".$value."'"):$value;
    }

    public function assign_str($field, $value){
        $this->fields[$field] = "'".addslashes($value)."'";
    }

    public function reset(){
        $this->fields = array();
    }

    public function insert($table){
        $f = "";
        $v = "";
        reset($this->fields);
        foreach($this->fields as $field=>$value){
            $f.= ($f!=""?", ":"").$field;
            $v.= ($v!=""?", ":"").$value;
        }
        $sql = "INSERT INTO ".$table." (".$f.") VALUES (".$v.")";
        //print SQL to screen for testing
        echo $sql;
        //$this->query($sql);
        return $this->insert_id();
    }

    public function update($table, $where){
        $f = "";
        reset($this->fields);
        foreach($this->fields as $field=>$value){
            $f.= ($f!=""?", ":"").$field." = ".$value;
        }
        $sql = "UPDATE ".$table." SET ".$f." ".$where;
        echo $sql;
        //$this->query($sql);
    }

    public function query($_query){
        $this->query = $_query;
        $this->result = @mysql_query($_query, $this->link_id) or die( $_query."<p>".mysql_error($this->link_id) );
        return $this->result;
    }

    public function insert_id(){
        return @mysql_insert_id($this->link_id);
    }
}


// start new DB object
$db = new DB;

// assign some key/values to insert into DB
$db->assign('name', 'jason davis');
$db->assign('age', 26);
$db->assign('sex', 'male');
$db->assign('user_id', 5345);

// Do  the insert
$db->insert('test');


echo '<hr />';

// assign some key/values to insert into DB
$db->assign('name', 'dfgd');
$db->assign('age', 87);
$db->assign('sex', 'female');
$db->assign('user_id', 4556);

// Do  the insert
$db->insert('testing2');


echo '<hr />';

// assign some key/values to UPDATE the DB
$db->assign('name', 'jason davis');
$db->assign('age', 26);
$db->assign('sex', 'male');
$db->assign('user_id', 5345);

// DO the DB UPDATE
$db->update('blogs', 'WHERE user_id = 23');

?>

【问题讨论】:

  • 在很多人继续争论这个问题的“意义”之前,你可能想现在就接受一个答案,哈哈。
  • 我的代表正好是 7,777。至少低了 1,111。
  • 由于function reset()修改了$this-&gt;fields,所以可以不带参数调用,只需$this-&gt;reset()即可。但是,您上面的数据库抽象缺乏价值卫生并且容易受到 sql 注入的影响。请参阅下面关于使用 AdoDB 库以获得更好的安全性和安心的建议:)

标签: php class arrays


【解决方案1】:

关联数组中的键是唯一的;分配新值会删除旧值。

【讨论】:

  • 你错了一半。键被替换,但这不是类应该如何工作的(仔细检查代码和示例)。
  • 它一直分配给$this-&gt;fields[$field]。我说的怎么解释不通?
  • 他的问题是“这个 PHP 如何知道要使用哪个数组键/值”。这将是该问题的正确答案。
  • @Chacha102:这将是问题标题的正确答案,(un?)幸运的是,这不是我们需要注意的全部。
【解决方案2】:

如果你仍然打开另一个数据库抽象库,我想建议你使用AdoDB。它可以连接到多个数据库,因此如果您决定稍后切换数据库,您的代码将保持不变。它具有在插入/更新之前清理数据的内置功能。

对于你上面的代码,当你使用AdoDB的时候,你会这样写:

$adodb =& ADONewConnection($dsn);
$data['name'] = 'dfgd';
$data['age'] = 87;
$data['sex'] = 'female';
$data['user_id'] = 4556;

// Do  the insert
$result = $adodb->AutoExecute($table_name, $data, 'INSERT');

//If update, must have one of the key, such as id column
$result = $adodb->AutoExecute($table_name, $data, 'UPDATE', "id=$id");

您可以从网站上阅读文档,也可以在可以下载的 zip 文件中阅读。我总是在我的所有项目中使用这个库,即使我更喜欢它构建在 CodeIgniter 数据库库中。

【讨论】:

    【解决方案3】:

    insert()update() 应该(最初)在执行时将 $this-&gt;fields 属性设置回一个空数组,但是您以某种方式(错误地)删除了该代码?

    将您的代码更新为:

        public function insert($table){
            $f = "";
            $v = "";
            foreach($this->fields as $field=>$value){
                $f.= ($f!=""?", ":"").$field;
                $v.= ($v!=""?", ":"").$value;
            }
            $sql = "INSERT INTO ".$table." (".$f.") VALUES (".$v.")";
            $this->reset();
            //print SQL to screen for testing
            echo $sql;
            //$this->query($sql);
            return $this->insert_id();
        }
    
        public function update($table, $where){
            $f = "";
            foreach($this->fields as $field=>$value){
                $f.= ($f!=""?", ":"").$field." = ".$value;
            }
            $sql = "UPDATE ".$table." SET ".$f." ".$where;
            $this->reset();
            echo $sql;
            //$this->query($sql);
        }
    

    【讨论】:

    • 问题不在于该类不起作用,而是它确实起作用,即使有这个明显的“错误”。
    【解决方案4】:

    好的,我们得出结论,我之前的回答是对的:


    因为您使用名称键,所以它用新键替换旧键。

    $db->assign('user_id', "1");
    

    基本上是这样的:

    $this->fields['user_id] = (1)==""?("'1'"):1;
    

    当你必须再做一次时,它会取代它

    $this->fields['user_id'] = (2)==""?("'2'"):2;
    

    尝试进行分配,然后仅再次分配 user_id,其余数据将保持不变。


    为了解决这个问题,我们会在查询后调用$this-&gt;reset() 函数。

    public function query($_query){
            $this->query = $_query;
            $this->result = @mysql_query($_query, $this->link_id) or die( $_query."<p>".mysql_error($this->link_id) );
            $this->reset();
            return $this->result;
        }
    

    或者您可以在单独的 insertupdate 函数中调用它:

    public function insert($table){
        // .... stuff
        $this->query($sql);
        $this->reset();
        return $this->insert_id();
    }
    

    另一种可能性是最初的程序员没有很好地向你传达他的意图。他可能希望您在每次查询后致电$db-&gt;reset()

    【讨论】:

    • -1: reset — 将数组的内部指针设置为其第一个元素。应该是$this-&gt;reset();
    • @Alix 正确,它在真实环境中不起作用。但是,我(作为一个固执的程序员)必须争辩说,我对正在发生的现象的解释是正确的,这使得它看起来好像不能将旧领域与新领域混在一起。
    • 是的,所有的表名和字段都是组成的,我只是想看看这个类是如何构建 SQL 部分的,在生产中我可能会在一些页面上运行许多不同的更新和插入集他们很可能都有不同的键/值
    • @jasondavis 您应该能够简单地使用我或@alix 创建的修复程序。
    • @jasondavis 这可能是程序员的初衷,让您在每次查询后调用重置。为什么该功能也是公开的,这是有道理的。
    猜你喜欢
    • 1970-01-01
    • 2022-12-03
    • 1970-01-01
    • 2020-10-24
    • 2015-12-15
    • 2012-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多