Как использовать $wpdb->insert для вставки нескольких строк

2 сент. 2011 г., 08:38:38
Просмотры: 13.8K
Голосов: 1

Как использовать $wpdb->insert для вставки нескольких строк. Вот мой код:

for($i=0; $i<=$urlCount; $i++) {
   $stat = $wpdb->insert(
        'WP_URLS',
        array(
            'POSTID' => $post->ID,
            'URL' =>   $_POST['url'.$i]
        )
    );
}

Этот код работает только для первой вставки (т.е. когда $i = 0, когда значение равно url_0). Иногда количество URL может быть больше 100, а иногда равно нулю. Поэтому вместо написания кода 100 раз, я просто хочу иметь простой цикл, который будет работать для любого количества записей. Вот почему я выбрал цикл.

Спасибо за помощь.

Структура таблицы:

CREATE TABLE WP_URLS (
   POSTID BIGINT NOT NULL,
   URL VARCHAR(254)
);
5
Комментарии

Какова структура вашей таблицы? Я не вижу проблем в вашем коде.

Ján Bočínec Ján Bočínec
2 сент. 2011 г. 09:52:01

Возможно, стоит использовать $wpdb->prepare() из соображений безопасности. См. Codex.

kaiser kaiser
2 сент. 2011 г. 16:26:29

CREATE TABLE WP_URLS ( POSTID BIGINT NOT NULL, URL VARCHAR(254) ); @johnnyPea

Albin Joseph Albin Joseph
3 сент. 2011 г. 07:27:24

@kaiser $wpdb->insert() экранирует данные согласно документации. Нужно ли нам всё равно использовать $wpdb->prepare()?

Albin Joseph Albin Joseph
3 сент. 2011 г. 07:34:35

@Albin Joseph Вы правы. Я только что посмотрел ядро, и обе функции insert и replace используют функцию prepare.

kaiser kaiser
4 сент. 2011 г. 00:52:17
Все ответы на вопрос 2
2

Полагаю, проблема довольно простая. Вы не показали весь код, но я предполагаю, что проблема в том, что вы сохраняете вставку по какой-то неизвестной причине как string в переменную с именем $stat. Каждый раз, когда вы заполняете переменную новым запросом, вы перезаписываете её. Вместо этого вам следует использовать $stat .= $wpdb->insert( ...и т.д... ), чтобы дополнять строку. Не забудьте установить переменную в пустую строку перед циклом, чтобы можно было дополнять: $stat = ''.


Другой — на мой взгляд, лучший — способ заключается в использовании массива. Причина: так легче отлаживать код. И, пожалуйста, прочтите комментарий в коде.

$stats = array();
for( $i = 0; $i <= $urlCount; $i++ ) 
{
    $stats[] = array(
        'POSTID' => $post->ID,
        // вы действительно получаете **ВСЕ** свои URL как "url1", "url2" и т.д.
        // через форму, отправленную методом $_POST?
        'URL' =>   filter_var(
            $_POST["url{$i}"], 
            FILTER_VALIDATE_URL, 
            FILTER_FLAG_SCHEME_REQUIRED
        )
    );
}

foreach ( $stats as $stat )
    $wpdb->insert( 'WP_URLS', $stat );
4 сент. 2011 г. 00:55:36
Комментарии

Я просто хотел проверить, успешно ли прошла вставка, и для этого сохранил $stat. Только чтобы вывести значение.

Albin Joseph Albin Joseph
5 сент. 2011 г. 09:44:24

Спасибо за более правильный способ. Я вывел $_POST, и там есть значения для url1, url2 и т.д.

Albin Joseph Albin Joseph
5 сент. 2011 г. 09:47:03
2

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

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

<?php
 
    
    /**
     * Метод для вставки нескольких строк в указанную таблицу
     * 
     *  Пример использования: 
     *
     *  $insert_arrays = array();
     *  foreach($assets as $asset) {
     *
     *  $insert_arrays[] = array(
     *  'type' => "multiple_row_insert",
     *  'status' => 1,
     *  'name'=>$asset,
     *  'added_date' => current_time( 'mysql' ),
     *  'last_update' => current_time( 'mysql' ));
     *
     *  }
     *
     *  wp_insert_rows($insert_arrays);
     *
     *
     * @param array $row_arrays
     * @param string $wp_table_name
     * @return false|int
     *
     * @author  Ugur Mirza ZEYREK
     * @source http://stackoverflow.com/a/12374838/1194797
     */
     
    function wp_insert_rows($row_arrays = array(), $wp_table_name) {
        global $wpdb;
        $wp_table_name = esc_sql($wp_table_name);
        // Создаем массивы для реальных значений и плейсхолдеров
        $place_holders = [];
        $row = implode(', ', array_keys($row_arrays));
        $values = array_values($row_arrays);

        foreach (array_values($row_arrays) as $key => $param) {
        
            if(is_numeric($param)) {
                if($key == 0){
                    array_push($place_holders, " '%d'");
                } else {
                    array_push($place_holders, ", '%d'");
                }
                
            } else {
                if($key == 0){
                    array_push($place_holders, " '%s'");
                } else {
                    array_push($place_holders, ", '%s'");
                }
            }
        }

        $params = implode('', $place_holders);
    
        $query = "INSERT INTO {$wp_table_name} (" . $row . ") VALUES (" . $params . ")";

        if($wpdb->query($wpdb->prepare($query, $values))){
            return true;
        } else {
            return false;
        }
    }

Источник: https://github.com/mirzazeyrek/wp-multiple-insert

20 нояб. 2015 г. 14:16:58
Комментарии

Я бы предложил поменять порядок аргументов и поставить неявно требуемый аргумент первым: $table_name. Также в большинстве случаев можно напрямую использовать $wpdb->table_name. Кроме того, с точки зрения читаемости, возможно, стоит разместить INSERT INTO {$wp_table_name} ( после цикла foreach, чтобы было понятно, что происходит в каком порядке (цикл, строки запроса, построение массива VALUES, затем присваивание и вставка. Что касается аргументов prinft: Существует больше, чем просто string/int. Также могут возникнуть проблемы с нестандартными строками и режимом SQL strict.

kaiser kaiser
15 янв. 2016 г. 11:37:19

Я совершенно уверен, что конкатенация строк в цикле foreach с разделителем ,/запятая не сработает. Это приведёт к двойным запятым в начале строки. Тем не менее, +1 за ссылку.

kaiser kaiser
15 янв. 2016 г. 11:40:39