如何使用数组

时间:2017-10-03 15:53:33

标签: php mysql arrays pdo

我在找到更新现有记录时如何正确设置准备好的PDO SQL语句时迷失了方法。

我的数组传递给我的方法是这样的:

array(9) { ["catName"]=> string(10) "Kato Marks" ["age"]=> string(2) "40" ["gender"]=> string(6) "Female" ["createTime"]=> string(19) "2017-10-03 03:55:39" ["coloring"]=> string(5) "Black" ["hairLength"]=> string(5) "Short" ["currentMood"]=> string(5) "rowdy" ["weight"]=> string(2) "17" ["hasCatittude"]=> string(1) "0" }

with key是数据库表列,值是我想要更新的数据库值

到目前为止,我有以下内容:

public function updateRow($data, $catID)
{
    $db = self::getConnection();

    try
    {
        $stmt = $db->prepare("UPDATE users SET " . implode('= ', array_keys($data).  array_values($data)). " WHERE id='{$catID}'");

        foreach($data as $key => $value) {
            $stmt->bindValue($key, $value, PDO::PARAM_STR);
        }
        $stmt->execute();
    } catch (\PDOException $e) {
        return 'Adding new record failed' . $e->getMessage();
    }

}

但是当我将语句print_r到屏幕时,我得到以下内容:

PDOStatement Object ( [queryString] => UPDATE users SET WHERE id='108' )

我无法弄清楚如何正确编写准备好的语句,我动态地将表名设置为数组键等,任何帮助都将非常感谢。

2 个答案:

答案 0 :(得分:1)

重新评估方法

从您的评论中,此函数属于Database类。不可否认,此类可以在任何表上使用,以根据任何条件更新任何行。但是,查看函数签名,我们可以看到它应该接受$catId参数,这意味着它将在非常特定的表上使用,使用特定列过滤行。

你可以通过简单地重命名函数和参数来更好地代表它实际在做什么,但仍然无法解决我认为问题的核心:对象有太多的责任。

根据Single Responsibility Principle,一个班级"应该有一个,只有一个,有理由被改变"。在这种情况下,如果将一列添加到User表中,或者需要将另一列添加到WHERE子句中,则只应影响User类(或实体)虽然Database类不需要任何更改。

建议

为了简单起见,让我们设想一个fridge数据库,其中有一个名为fruits的表(我知道,非常富有想象力)。

create table fruits (
    id int not null auto_increment,
    name varchar(20),
    color varchar(20),
    weight int,
    order int, /* order of appearance, say, for a list */
    PRIMARY KEY (id)
);

这个表的php表示可能看起来有点像

class Fruit {
    private $id;
    private $name;
    private $color;
    private $weight;
    private $order;

    public function __construct($id, $name, $color, $weight) {
        $this->id = $id;
        $this->name = $name;
        $this->color = $color;
        $this->weight = $weight;
        $this->order = $order;
    }
}

很好,现在我们有一个表,以及一个可用于表示该表记录的对象。现在我们可以添加一个FruitTable类,它将充当Fruit和数据库本身之间的媒介。

class FruitTable {
    private $columns = ['id', 'name', 'color', 'weight', 'order'];
    private $table = 'fridge.fruits';
    private $conn;

    public function __construct($connection) {
        $this->conn = $connection
    }

    public function findOneById($id) {
        /**
         * Query the DB and hydrate a Fruit instance
         */

        return $fruit;
    }
}

现在想象一下,我们需要能够根据水果的颜色更改order Fruit字段(我知道,这是我们正在努力的一些非常奇怪的业务) 。没问题,我们可以向FruitTable添加一个函数来进行更新。

public function updateOrderByColor($newOrder, $color) {
    /* assume proper validation */
    $query = $this->conn->prepare("UPDATE fruits SET order = :newOrder WHERE color = :color");
    $query->bindParam(':newOrder', $newOrder);
    $query->bindParam(':color', $color);

    $query->execute();
}

这是一个非常简单的例子,但它表明,与简单的Database类相比,可以获得多大的灵活性。如果需要添加列,或者条件发生更改,则代码中只有一个位置需要跳入并乱用。如果查询出现问题,那么只有一个地方可以查找该错误。

这个例子并不完美,FruitTable可能不应该直接负责处理数据库连接。您可以查看DoctrineEloquent如何处理查询构建器,以及它们如何设法将每个类与其余类进行封装。

答案 1 :(得分:0)

你需要将你的功能更新为这样的东西。首先将构建列数组,并使用','进行内嵌。循环然后绑定你的变量,然后绑定你的$ catID。

R = 36

# if the P value is three or greater 
if p >= 3:
    # it causes the circle to subtract p3 from 36 
    R -= p

# but if P is not equal to three or more 
else:
    # then I want for the code to say I do not want it to subtract p from 36.
    pass

a.circle(b * (R, -i * 36))   # attention, i is not defined