WordPress как на ладони
wordpress jino

add_query_arg() WP 1.5

Добавляет указанные параметры GET запроса в текущий или указанный URL.

Функция позволяет удобно создавать URL, добавляя в него новые параметры запроса: ?var=val&var_2=val_2.

Если в значении параметра указать false: array('key'=>false), то функция удалит указанный параметр запроса из УРЛ.

Если пропустить второй и третий параметры, функция будет использовать вместо них значения глобального массива $_SERVER['REQUEST_URI'].

 Важно! Функция не использует esc_url(), т.е. не очищает результат. Поэтому, если вы не указываете в функции в какой УРЛ нужно добавить данные, то функция использует $_SERVER['REQUEST_URI'], поэтому перед выводом обязательно нужно очищайте УРЛ с помощью esc_url(). Нужно это, для защиты от XSS атак, т.к. любой пользователь может дописать в УРЛ произвольный параметр запроса, который затем будет выведен в HTML самой страницы.

Используется в: get_edit_term_link(), remove_query_arg().
✈ 1 раз = 0.000057с = очень быстро | 50000 раз = 0.12с = очень быстро PHP 7.1.5, WP 4.8.2

Хуков нет.

Возвращает

Строку, новый URL с параметрами запроса.

Использование

add_query_arg( $param1, $param2, $old_query_or_uri );

Шаблон использования

$new_url = add_query_arg( array('key1'=>'value1', 'key2'=>'value2' ), $uri );
$param1(строка/массив/логический) (обязательный)
Новый ключ или ассоциативный массив новых параметров запроса: array( ключ => значение ).
По умолчанию: нет
$param2(строка/массив/логический)
Новое значение параметра (если в первом параметре была указана строка - ключ). Или URL в который нужно добавить параметры, если в первом значении указан массив. По умолчанию, используется текущий УРЛ ($_SERVER[REQUEST_URI]).
По умолчанию: нет
$old_query_or_uri(строка/массив)
Старый запрос или URL.
По умолчанию: $_SERVER[REQUEST_URI]

Примеры

#1. Добавляем параметры в текущий УРЛ страницы

Предположим мы находимся на странице http://example.com/client/?s=word, тогда:

echo esc_url( add_query_arg( 'foo', 'bar' ) );
// вернет: /client/?s=word&foo=bar

$arr_params = array( 'foo' => 'bar', 'baz' => 'tiny' );
echo esc_url( add_query_arg( $arr_params ) );
// вернет: /client/?s=word&foo=bar&baz=tiny

Важно! В таком коде, когда не указан конкретный УРЛ куда добавляются параметры, нужно обязательно использовать <a href="/function/esc_url">esc_url()</a> перед выводом результата на экран. Потому что параметры запроса могут быть добавлены пользователем произвольно.

#2. Добавляем параметры в указанный УРЛ

Если нужно обработать не тот УРЛ на котором мы находимся сейчас, а любой другой, то нужно указать его в третьем или втором параметре, см. оба примера.

echo add_query_arg( 'hello', 'world', 'http://blog.example.com/2009/04/16/' );

echo add_query_arg( array('hello' => 'world'), 'http://blog.example.com/2009/04/16/' );

// оба примера вернут: http://blog.example.com/2009/04/16/?hello=world

Здесь нет нужды использовать esc_url(), как в примере выше, потому что мы знаем к какому УРЛ добавляются параметры и он не может быть изменен пользователем.

#3. Добавим параметры к УРЛу поста 9

Получим УРЛ функцией get_permalink():

echo add_query_arg( 'hello', 'there', get_permalink(9) );

// получим: http://ссылка_на_пост_9?hello=there

#4. Удалим параметр запроса из URL:

$url = 'http://example.com/asd?key=val&key_1=val_1';
echo esc_url( add_query_arg( array('key'=>false), $url ) );
// http://example.com/asd?key_1=val_1

Код add query arg: wp-includes/functions.php WP 4.8.2

<?php
function add_query_arg() {
	$args = func_get_args();
	if ( is_array( $args[0] ) ) {
		if ( count( $args ) < 2 || false === $args[1] )
			$uri = $_SERVER['REQUEST_URI'];
		else
			$uri = $args[1];
	} else {
		if ( count( $args ) < 3 || false === $args[2] )
			$uri = $_SERVER['REQUEST_URI'];
		else
			$uri = $args[2];
	}

	if ( $frag = strstr( $uri, '#' ) )
		$uri = substr( $uri, 0, -strlen( $frag ) );
	else
		$frag = '';

	if ( 0 === stripos( $uri, 'http://' ) ) {
		$protocol = 'http://';
		$uri = substr( $uri, 7 );
	} elseif ( 0 === stripos( $uri, 'https://' ) ) {
		$protocol = 'https://';
		$uri = substr( $uri, 8 );
	} else {
		$protocol = '';
	}

	if ( strpos( $uri, '?' ) !== false ) {
		list( $base, $query ) = explode( '?', $uri, 2 );
		$base .= '?';
	} elseif ( $protocol || strpos( $uri, '=' ) === false ) {
		$base = $uri . '?';
		$query = '';
	} else {
		$base = '';
		$query = $uri;
	}

	wp_parse_str( $query, $qs );
	$qs = urlencode_deep( $qs ); // this re-URL-encodes things that were already in the query string
	if ( is_array( $args[0] ) ) {
		foreach ( $args[0] as $k => $v ) {
			$qs[ $k ] = $v;
		}
	} else {
		$qs[ $args[0] ] = $args[1];
	}

	foreach ( $qs as $k => $v ) {
		if ( $v === false )
			unset( $qs[$k] );
	}

	$ret = build_query( $qs );
	$ret = trim( $ret, '?' );
	$ret = preg_replace( '#=(&|$)#', '$1', $ret );
	$ret = $protocol . $base . $ret . $frag;
	$ret = rtrim( $ret, '?' );
	return $ret;
}

Cвязанные функции

Из раздела: Основной запрос

add_query_arg 12 комментариев
Полезные 1 Все
  • Jude

    Спасибо, очень полезная информация, что называется как раз вовремя smile)

    1
    Ответить3.9 года назад #
  • lincaseidhe21 cайт: ardeya.ru

    Кама, помоги, срочно надо...
    Как обрабатывать get запрос в шаблоне? то есть например у меня страница(адрес http://mysite.ru/page15/) с шаблоном my_template.php...
    если я сделаю так:

    echo add_query_arg( array('hello' => 'world'), 'http://mysite.ru/page15/' );
    //получил ссылку http://mysite.ru/page15/?hello=world

    обрабатывать запрос мне нужно в шаблоне my_template.php?

    $hello = $_GET['hello'];
    //и дальше обрабатывать что мне нужно в цикле?
    if( $hello == 'hello' ) {
    //Тут будет new WP_Query
    }
    Ответить1.7 года назад #
    • Kama4464

      В целом да, только проверяем значение:

      $hello = $_GET['hello'];
      // и дальше обрабатывать что мне нужно в цикле?
      if( $hello == 'world' ) {
      	//Тут будет new WP_Query
      }

      И имей ввиду - не выводи этот запрос без очистки, туда юзер что угодно может передать, осторожно с ним, всегда проверяй. Если на экран его выводишь чисти с помощью функций esc_*.

      Ответить1.7 года назад #
      • lincaseidhe21 cайт: ardeya.ru

        на экран выводить не буду. тут только дата передается. в общем я тут накидал скрипт, посмотри, может что-нибудь полезное подскажешь...
        проверяю регуляркой preg_match(). пока потестирую, но вроде работает как надо) и левого ничего в запрос не подставишь...

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

        и еще вопрос, параметры get нельзя под чпу сделать?

        Ответить1.7 года назад #
        • Kama4464

          Можно, вот эту функцию используйте, там есть пример: add_rewrite_rule()

          Ответить1.7 года назад #
        • lincaseidhe21 cайт: ardeya.ru

          Все допиливал свою афишу. в предыдущем коде много косяков, поэтому его я удалю. вот новый код. Если увидите косяки - говорите)

          <ul class="afisha">
          		<?php    /* Меню */
          				$counts = array( '0','1','2','3','4','5','6','7'); //устанавливаем количество дней, которые будем выводить. 0 - сегодня, 1 - завтра и т.д.
          
          				$blogtime = current_time('mysql'); // вернет: 2005-08-05 10:41:13
          				list( $year, $month, $day, $hour, $minute, $second ) = preg_split( '([^0-9])', $blogtime );
          
          				$segodnya = $year . $month . $day;
          				$zavtra = date('Ymd', mktime(0,0,0, $month, $day+1, $year));
          
          				if( $_GET['date'] )
          					$filter = preg_match( '/^\d{8,8}$/', $_GET['date'] );
          
          				if( $filter === 1 ) 
          					$date = $_GET['date'];
          				elseif( $filter === 0 )
          					echo 'Хакер что ли?';
          				else
          					$date = $segodnya;
          
          				$onetoplay = 1; //костыль для первой ссылки "Сегодня"
          
          				foreach( $counts as $count ) {
          
          					$nextday = date( 'd', mktime( 0, 0, 0, $month, $day+$count, $year ) );
          					$month_count = date( 'm', mktime( 0, 0, 0,$month, $day+$count, $year ) );
          
          					$future = $year . $month_count . $nextday;
          
          					if( $future == $_GET['date'] ) {
          							$active = 'active';
          					} elseif( empty( $_GET['date'] ) ) {
          						if( $onetoplay == 1 ) {
          							$active = 'active';
          						} else {
          							$active = NULL;
          						}
          					} else {
          						$active = NULL;
          					}
          
          					if( $future == $segodnya )
          						$name = 'Сегодня';
          					elseif( $zavtra == $future )
          						$name = 'Завтра';
          					else
          						$name = date( 'l', mktime( 0, 0, 0, $month_count, $nextday, $year ) ); 
          
          					$weekend = NULL;
          
          					//переводим на русский
          					if( $name == 'Saturday' ) { $name = 'Суббота'; $weekend = ' weekend'; }
          					elseif( $name == 'Sunday' ) { $name = 'Воскресенье'; $weekend = ' weekend'; }
          					elseif( $name == 'Monday' ) { $name = 'Понедельник'; }
          					elseif( $name == 'Tuesday' ) { $name = 'Вторник'; }
          					elseif( $name == 'Wednesday' ) { $name = 'Среда'; }
          					elseif( $name == 'Thursday' ) { $name = 'Четверг'; }
          					elseif( $name == 'Friday' ) { $name = 'Пятница'; }
          
          					echo '<li class="'. $active . $weekend . '"><a href="' . add_query_arg( array('date' => $future), 'http://tobolsk-gid.ru/афиша-тобольск/' ) . '" title="' . $nextday .  '.' . $month_count . '.' . $year . '">' . $name . '</a></li>' ;
          					$onetoplay = 0;
          				}
          		?>
          		</ul>
          		<div class="clear"></div>
          		<div class="sep"></div>
          		<?php    /* выведем посты */
          
          				$query = new WP_Query(array(    'post_type' => 'afisha',
          																	'posts_per_page' => '20',
          																//  'meta_value' => $date,
          																	'orderby' => 'rand',
          																	'meta_query' => array(
          																		'relation' => 'OR',
          																			array(
          																			'relation' => 'OR',
          																				array(
          																				'key' => 'date_1',
          																				'value' => $date,
          																				),
          																				array(
          																				'key' => 'date_2',
          																				'value' => $date,
          																				),
          																				array(
          																				'key' => 'date_3',
          																				'value' => $date,
          																				),
          																			),
          																			array(
          																			'relation' => 'AND',
          																				array(
          																					'key' => 'long_date_first',
          																					'value' => $date,
          																					'compare' => '<=',
          																				),
          																				array(
          																					'key' => 'long_date_second',
          																					'value' => $date,
          																					'compare' => '>=',
          																				),
          																			),
          																		),
          
          																	) );
          
          			if( $query->have_posts() ) {
          				while( $query->have_posts() ) { $query->the_post();
          
          					$post_meta_price = get_post_meta( get_the_ID(), 'price', true );
          					$post_meta_time = get_post_meta( get_the_ID(), 'time', true ); ?>
          
          							<div class="company-single">
          
          							<?php $cur_terms = get_the_terms( $post->ID, 'cat_afisha' );
          
          								foreach( $cur_terms as $cur_term ) {
          									echo '<a class="afisha-term" href="'. get_term_link( (int)$cur_term->term_id, $cur_term->taxonomy ) . '">' . $cur_term->name . '</a>';
          								}
          							?>
          								<center>
          								<?php if(has_post_thumbnail()) { the_post_thumbnail( 'catalog', 'class=catalog_logo' ); } else echo '<img width="310" height="175" src="' . get_template_directory_uri() . '/images/no-img.png" class="catalog_logo wp-post-image" alt="Нет изображения">'; ?>
          								</center>
          							</div>
          							<div class="company-single">
          								<?php    $post_meta_date = get_post_meta( get_the_ID(), 'date_1', true ); //строка содержит несколько дат через пробел
          											$post_meta_price = get_post_meta( get_the_ID(), 'price', true );
          											$post_meta_time = get_post_meta( get_the_ID(), 'time', true );
          											$post_meta_info = get_post_meta( get_the_ID(), 'info', true );
          
          											echo '<a href="' . get_the_permalink() . '" title="Подробней о ' . get_the_title() . '"><h2>' . get_the_title() . '</h2></a>';
          											echo excerpt_post( 100 );
          											if($post_meta_time || $post_meta_price) {
          											echo '<p class="catalog_info">';
          											if($post_meta_time) echo "<strong>Время:</strong> $post_meta_time<br />";
          											if($post_meta_price) echo "<strong>Цена:</strong> $post_meta_price";
          
          											//echo '<a href="' . get_the_permalink() . '"><strong>Узнать подробней о ' . get_the_title() . '</strong></a>';
          											echo '</p>';
          											}
          							echo '</div>';
          							echo '<div class="clear"></div><div class="sep"></div><div class="afisha-one-block"></div>';
          				}
          			} else {
          				echo 'Нет анонсов. Если вы знаете о мероприятии в этот день, можете написать администратору... <a href="http://tobolsk-gid.ru/написать-администратору/">Ссылка</a>';
          			}
          		?>
          Ответить1.6 года назад #
  • mupic @

    Написал подобие функции, вот только моя попроще будет и полегче smile

    Функция позволяет добавлять, обновлять и удалять GET параметры по заданным "настройкам". Удалять можно не только по ключи но и по значению.

    add_query_arg($args, 'https://www.google.ru/search?sourceid=chrome-psyapi2&ion=1&espv=2&ie=UTF-8&q=123&oq=123&aqs=chrome');

    1раз -> 0.00013303756713867 сек; 50000раз -> 6.3507151603699 сек.

    change_query('https://www.google.ru/search?sourceid=chrome-psyapi2&ion=1&espv=2&ie=UTF-8&q=123&oq=123&aqs=chrome', $args);

    1раз -> 0.000034093856811523 сек; 50000раз -> 1.2332780361176 сек.

    /*
    $args = array(
    	'remove' => array( //Удаляем:
    		'value'=>array( //По значению
    			$value //[string]
    		),
    		//or 'value'=> $value
    		'name'=>array( //По имени
    			$name //[string]
    		)
    		//or 'name'=> $name
    	),
    	'update' => array( //Обновляем значение или вставляем новое
    		'name' => 'new_value' //[string]
    	)
    );
    */
    function change_query($url, $args = array()){
    	$parse_url = parse_url($url);
    	$query = array();
    	if(isset($parse_url['query']) && $parse_url['query'])
    		parse_str($parse_url['query'], $query);
    
    	foreach($args as $make => $arg){
    
    		switch($make){
    			case 'remove':
    
    				foreach($arg as $remake => $arr){
    					if(empty($arr)) continue;
    
    					$arr = (array) $arr; //Если строка, то преобразуем в массив
    
    					switch($remake){
    						case 'value':
    							$query = array_diff($query, $arr);
    						break;
    						case 'name':
    							foreach($arr as $array_name){
    								unset($query[$array_name]);
    							}
    						break;
    					}
    				}
    
    			break;
    			case 'update':
    				$arg = array_diff($arg, array(null)); //Удаляем пустые значения
    				if(empty( $arg )) continue;
    				$query = array_merge($query, $arg);
    			break;
    		}
    
    	}
    
    	if((!isset($parse_url['query']) || !$parse_url['query']) && !$query) //Ничего не делали 
    		return $url;
    	if(!$query) //Нечего подставить в запрос
    		return $parse_url['scheme'].'://'.$parse_url['host'].$parse_url['path'];
    
    	return $parse_url['scheme'].'://'.$parse_url['host'].$parse_url['path'].'?'.http_build_query($query);
    }

    Сравнение функций при удалении параметров:

    remove_query_arg($args, 'https://www.google.ru/search?sourceid=chrome-psyapi2&ion=1&espv=2&ie=UTF-8&q=123&oq=123&aqs=chrome');

    1раз -> 0.00022101402282715 сек; 50000раз -> 12.368366003036 сек.

    change_query('https://www.google.ru/search?sourceid=chrome-psyapi2&ion=1&espv=2&ie=UTF-8&q=123&oq=123&aqs=chrome', $args);

    1раз -> 0.000031948089599609 сек; 50000раз -> 1.2445659637451 сек.

    Ответитьгод назад #
    • Kama4464

      В вашей функции не учтены некоторые моменты и передача параметров на мой взгляд менее удобная. Зачем эти remove, update? В разы удобнее указывать null для параметра, чтобы его удалить... Ну и если уж делаете быстрый аналог, то делайте аналог, а то получился свой велосипед. В общем, я не понял зачем это надо, только если хочется попрактиковаться в программировании...

      На таких скоростях экономить толку нет... Ну максимум за генерацию 1000 раз вызовите вы эту функцию (да и то это почти нереально) при этом сэкономите 0,005 секунды, а некоторые моменты при этом не учтены из за которых потом баги ловить можно, ну и менее удобно получилось по-моему... Оно того стоит? unknw

      Ответитьгод назад #
      • mupic @

        Написал я ее потому что не пришло в голову найти готовую функцию на wp. pardon
        Ну, а с указанием параметров действительно намудрил, малость не удобно.

        В разы удобнее указывать null для параметра, чтобы его удалить...

        Ну для ссылок вида "site.ru/profile?edit" думаю будет не очень удобно, хотя и у моей функции это тоже не учтено. smile

        Не учел в этой функции работу с массивами.
        А есть еще очевидные недочеты?

        Ответитьгод назад #
        • Kama4464

          Ну для ссылок вида "site.ru/profile?edit" думаю будет не очень удобно

          Хм, что удобнее может быть?

          echo add_query_arg( 'edit', null, 'site.ru/profile?edit' ); //> site.ru/profile
          // есть альтернатива
          echo add_query_arg( array('edit'=>null), 'site.ru/profile?edit' ); //> site.ru/profile

          Там много недочетов:

          • экранированные слэши не удаляются, если туда всякие $_GET, $_POST напрямую передаются;
          • части URL не кодируются (urlencode). Иногда может быть нужно;
          • такие URL останутся как есть:

            site.ru/profile?edit=
            site.ru/profile?
            site.ru/profile?=

            а они должны быть чистыми и выдавать всегда один результат... Чтобы потом можно было присоединять параметры. Особенно часто такие баги в JS мешают...

          • если не указан протокол, то ссылка ломается - отдаем site.ru/profile получаем ://site.ru/profile

          • Всегда нужно указывать $url. А очень часто нужно просто брать текущий и что-то с ним делать - REQUEST_URI

            echo esc_html( add_query_arg( array('edit'=>null) ) );
          Ответитьгод назад #
          • mupic @

            части URL не кодируются (urlencode)

            http_build_query - автоматически кодирует значения.

            Переписал функцию, функция осталась (незначительно) быстрее и легче чем add_query_arg и remove_query_arg:

            $args = array(
            	'id'=>array(11), //Обновляем [string] or [array]
            	'just_key'=>false, //Удаляем false или пустая строка 
            	'</div>', //Удаляем по значению
            	'edit'=>null, //Оставляем только параметр (мне так нужно было)
            );
            change_query($args, 'site.ru\/?id=\11&a=</div>&just_key='); // 'site.ru/?id[0]=11&edit'

            1раз = 0.0000669с = очень быстро;

            /*
            $args = array(
            	'name'=>'new_value', //Обновляем [string] or [array]
            	'name'=>false, //Удаляем false или пустая строка
            	'old_value', //Удаляем по значению
            	'edit'=>null, //Оставляем только параметр
            );
            */
            function ms_change_query($args = array(), $url = ''){
            	if(!$url)
            		$url = $_SERVER['REQUEST_URI'];
            	$url = stripslashes(htmlspecialchars_decode($url));
            	$parse_url = parse_url($url);
            	$query = array();
            	if(isset($parse_url['query']) && $parse_url['query'])
            		parse_str($parse_url['query'], $query);
            
            	if($args)
            		foreach($args as $key => $value){
            
            			switch(true){
            				case $value === false: //Удилить
            					unset($query[$key]);
            				break;
            
            				case is_numeric($key): //Удалить по значению
            					$value = (array) $value; //Если строка, то преобразуем в массив
            					$query = array_diff($query, $value);
            				break;
            
            				case $value === null: //Оставляем пустым
            					$query[$key] = '';
            				break;
            
            				case true: //Обновляем
            					if(!empty($value)){
            						$query[$key] = $value;
            					}else{
            						unset($query[$key]);
            					}
            				break;
            			}
            
            		}
            
            	$http = $parse_url['scheme']? $parse_url['scheme'].'://' : '';
            
            	if(!$query) //Нечего подставить в запрос
            		return $http.$parse_url['host'].$parse_url['path'];
            
            	return $http.$parse_url['host'].$parse_url['path'].'?'.preg_replace('/=(&|$)/', '$1', http_build_query($query));
            }
            1
            Ответитьгод назад #
            • Kama4464

              Вот этот вариант уже более-менее как по мне, правда еще протестировать его можно. good

              Ответитьгод назад #

Здравствуйте, !

Ваш комментарий