0

所以我为我的 chrome 插件(它执行一个 ajax 请求来运行这个方法)编写了这个方法,当它运行时,会file_put_contents显示一个曾经插入过的 id,但是当它insert ignore into songs到达0. artist_id我不知道为什么......有人可以帮我找到我出错的部分吗?

<?php
public function saveLyrics($artist, $title, $lyric){
    $this->db->query("insert ignore into artists (artist_name) value (:artist)", array("artist"   => $artist));
    $artist_id = (int)$this->db->insertID();
    file_put_contents(__DIR__ . "/../process/page", "artist id: $artist_id");
    //return;
    if($artist_id == 0){
        $artist_id = (int)$this->db->getOne("select artist_id from artists where artist_name = :artist", array("artist" => $artist));
    }
    if($artist_id == 0){
        return false;
    }
    $this->db->query("insert ignore into songs (artist_id, song_name) values (:aid, :title)", array("aid"    => $artist_id, "title"  => $title));
    $song_id = (int)$this->db->insertID();
    if($song_id == 0){
        $song_id = (int)$this->db->getOne("select song_id from songs where artist_id = aid and song_name = :title", array("aid"   => $artist_id, "title" => $title));
    }
}

PDO 包装器:

<?php

/** 
 * @property PDO $pdo Description
 * @property PDOStatement $sql Description
 */
class DB{

    protected $sql = null;
    protected $pdo = null;

    public function connect(){
        $this->pdo = new PDO("mysql:dbname=envne;host=xxx", "xxx", "xxx");
    }

    public function query($query, $params = array()){
        if($this->pdo === null){
            $this->connect();
        }
        $this->sql = $this->pdo->prepare($query);
        foreach($params as $key => $value){
            $this->sql->bindParam($key, $value);
        }
        $this->sql->execute();
        if(!$this->sql)
            return false;
        return true;
    }
    public function insertID(){
        return (int)$this->pdo->lastInsertId();
    }

    public function getAll($query, $params = array()){
        $this->query($query, $params);
        return $this->sql->fetchAll();
    }

    public function getOne($query, $params = array()){
        $this->query($query, $params);
        return $this->sql->fetchColumn();
    }

}

艺术家:

mysql> describe artists;
+-------------+------------------+------+-----+-------------------+----------------+
| Field       | Type             | Null | Key | Default           | Extra          |
+-------------+------------------+------+-----+-------------------+----------------+
| artist_id   | int(10) unsigned | NO   | PRI | NULL              | auto_increment |
| artist_name | char(50)         | YES  | UNI | NULL              |                |
| add_date    | timestamp        | YES  |     | CURRENT_TIMESTAMP |                |
+-------------+------------------+------+-----+-------------------+----------------+
3 rows in set (0.00 sec)

歌曲:

mysql> describe songs;
+------------+------------------+------+-----+-------------------+----------------+
| Field      | Type             | Null | Key | Default           | Extra          |
+------------+------------------+------+-----+-------------------+----------------+
| song_id    | int(10) unsigned | NO   | PRI | NULL              | auto_increment |
| artist_id  | int(11) unsigned | YES  | MUL | NULL              |                |
| album_id   | int(11)          | YES  | MUL | NULL              |                |
| song_name  | char(50)         | YES  |     | NULL              |                |
| track_id   | int(11)          | YES  |     | NULL              |                |
| date_added | timestamp        | NO   |     | CURRENT_TIMESTAMP |                |
+------------+------------------+------+-----+-------------------+----------------+
6 rows in set (0.01 sec)
4

3 回答 3

0

我只是决定将 Id 直接放入查询中,这样就可以了。

$artist_id = (int)$this->db->insertID();
$this->db->query("insert ignore into songs (artist_id, song_name) values ($artist_id, :title)", array("title"  => $title));

另一种可行的方法是使用问号

$artist_id = (int)$this->db->insertID();
$this->db->query("insert ignore into songs (artist_id, song_name) values (?, ?)", array($artist_id, $title));
于 2013-03-29T21:28:46.310 回答
0

我刚刚遇到了同样的问题:新插入的项目的 id 为 0,即使该ID字段设置为AUTO_INCRIMENT.

我找到的解决方案与您的非常相似。使用您的代码,这就是我们得到的:

$this->db->query("insert ignore into songs (artist_id, song_name) values (LAST_INSERT_ID(), :title)", array("title"  => $title));

如您所见,我将$artist_id = (int)$this->db->insertID();and替换$artist_id为 SQL function LAST_INSERT_ID()

我希望有一天这可以帮助某人:)

于 2013-09-12T23:29:20.613 回答
-1

您的占位符定义不正确:(您缺少冒号)我会这样做:

public function saveLyrics($artist, $title, $lyric){
    $this->db->query("insert ignore into artists (artist_name) value (:artist)", array(":artist"   => $artist));
    $artist_id = (int)$this->db->insertID();
    file_put_contents(__DIR__ . "/../process/page", "artist id: $artist_id");
    //return;
    if($artist_id == 0){
        $artist_id = (int)$this->db->getOne("select artist_id from artists where artist_name = :artist", array(":artist" => $artist));
        return false;
    }
    $this->db->query("insert ignore into songs (artist_id, song_name) values (:aid, :title)", array(":aid"=>$artist_id, ":title"=>$title));
    $song_id = (int)$this->db->insertID();
    if($song_id == 0){
        $song_id = (int)$this->db->getOne("select song_id from songs where artist_id = :aid and song_name = :title", array(":aid"=>$artist_id, ":title"=>$title));
    }
}

看看您的 PDO 包装器,您有以下代码:

if(!$this->sql)
    return false;

因此,您永远不会注意到实际错误。我猜这个错误是关于占位符的。(如果$this->db->query("insert ignore into songs (...在执行查询时出现错误,则 $song_id 将失败)。

改用异常并捕获错误会更好。

我还注意到:

$song_id = (int)$this->db->insertID();

会将值转换两次,首先是在上面的代码中,然后是在 PDO-Wrapper 中的实际函数 insertID() 中。也许这也是一个需要考虑的问题。

于 2013-03-30T07:34:59.963 回答