Проблемы приращения поля в MySQL / PHP с подготовленными операторами - PullRequest
0 голосов
/ 20 октября 2011

У меня есть следующий код, который предполагается для увеличения значения поля на 1 в подготовленном операторе PHP mysql:

function db_OP_doVote($pdo, $postid, $votetype)
{
    $prepStatement = $pdo->prepare(
        "UPDATE content_posts SET `:votetype` = `:votetype` + 1 WHERE `id` = :id"
    );

    $prepStatement->execute(array(':votetype' => $votetype, ':id' => $postid));

    echo "Success";
}

Это, однако, ничего не делает. Не возвращается ошибка о неправильном синтаксисе SQL, и сценарий выполняется до конца, но мое поле вообще не обновляется.

Значения для этого скрипта передаются через jQuery post () в этот скрипт:

//isset checking here
$postID = (int)$_POST['id'];
$voteType = $_POST['type'];

if ($voteType == "y")
{
    $trueType = "v-cool";
}
elseif ($voteType == "m")
{
    $trueType = "v-meh";
}
elseif ($voteType == "n")
{
    $trueType = "v-shit";
}
else 
{
    die();
}

$db = db_Connect();

db_OP_doVote($db, $postID, $trueType);

Который также, кажется, фильтрует значения и отправляет их в порядке. Я не могу обернуться вокруг того, в чем может быть проблема. Увеличиваемое поле является BIGINT (20).

Чего мне не хватает?

РЕДАКТИРОВАТЬ: Решена проблема.

Комментарий Н.Б. ударил по гвоздю по голове - привязка имени столбца приводит к его заключению в кавычки, что делает запрос недействительным. Спасибо!

Ответы [ 2 ]

3 голосов
/ 20 октября 2011

вы не можете использовать привязку для имен полей.

из вопроса кажется, что ваша установка неверна.

у вас должна быть другая таблица с голосами и типами голосов в качестве данных.

2 голосов
/ 20 октября 2011

Нельзя параметризировать имена столбцов с помощью PDO. То, что вы можете сделать, это иметь жестко закодированные значения (которые у вас уже есть) и соответственно построить строку SQL. Я бы также проверил это значение в реальной функции, просто чтобы быть в безопасности:

function db_OP_doVote($pdo, $postid, $votetype)
{
    if( !in_array( $votetype, array( 'v-cool', 'v-meh', 'v-shit' /*, etc. */ ), true ) )
    {
        throw new InvalidArgumentException( 'Unexpected $votetype: ' . $votetype );
        // or simply return false perhaps
    }

    $sql = '
        UPDATE content_posts
        SET `' . $votetype . '` = `' . $votetype . '` + 1
        WHERE `id` = :id
    ';

    $prepStatement = $pdo->prepare( $sql );

    $prepStatement->execute(array(':id' => $postid));

    echo "Success";
}

Однако эта стратегия предполагает, что при разработке вашей базы данных может потребоваться немного больше внимания. Теперь у вас есть то, что для каждого типа голосования у вас есть столбец. Это не очень эффективный и / или гибкий дизайн базы данных. Что произойдет, если вас попросят добавить еще один тип голосования?

Я бы предложил добавить другую таблицу, чтобы быть более гибким:

CREATE TABLE `content_post_vote` (
  `content_post_id` int(11) NOT NULL,
  `vote_type` enum('cool','meh','shit') NOT NULL, # using enum() to assure valid vote types 
  `votes` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`content_post_id`,`vote_type`)
)

Тогда ваш запрос будет выглядеть примерно так:

$sql = '
    INSERT INTO `content_post_vote` (`content_post_id`,`vote_type`,`votes`)
    VALUES( :id, :votetype, 1 )
    ON DUPLICATE KEY UPDATE `votes` = `votes` + 1
';

Для этого нужно вставить голосование, если для определенного первичного ключа еще нет записи (content_post_id, vote_type), а затем обновить запись голосом, если запись уже существует.

Затем, чтобы запросить в базе данных, сколько голосов определенного типа набрал конкретный content_post, вы делаете это:

 $sql = '
     SELECT `votes` # or perhaps more columns
     FROM `content_post_vote`
     WHERE `content_post_id` = :id AND 
           `vote_type` = :votetype
 ';
...