Smarty Forum Index Smarty
The discussions here are for Smarty, a template engine for the PHP programming language.
Modifier add_url_param

 
Post new topic   Reply to topic    Smarty Forum Index -> Plugins
View previous topic :: View next topic  
Author Message
mitchenall
Smarty Pro


Joined: 27 Feb 2004
Posts: 107
Location: London, UK

PostPosted: Fri Jan 14, 2005 9:46 pm    Post subject: Modifier add_url_param Reply with quote

I wrote this simple modifier today to get me out of a problem I had with setting parameters in URLs when I was getting the URL from {$smarty.server.REQUEST_URI}. It was very useful for me so I figured I'd post it for others.


[php:1:16484b570e]<?php

/**
* Smarty add_url_param modifier plugin
* ----------------------------------------
*
* This plugin adds parameters to existing URLs and is useful
* when you want to append or update a parameter without
* knowing anything about the contents of the existing
* URL.
*
* If any of the parameters passed to the modifier
* are already contained in the URL, their values
* are updated in the URL, rather than appending another
* parameter to the end.
*
* Examples:
*
* {$smarty.server.REQUEST_URI|add_url_param:'param=test¶m2=test2'}
* {$smarty.server.REQUEST_URI|add_url_param:$paramArray}
* {$smarty.server.REQUEST_URI|add_url_param:'variable':$value}
*
*
* @author Mark Mitchenall <mark@standingwave.co.uk>
* @copyright Standingwave Ltd, 2005
*
* @param $url string URL to add the parameters to
* @param $parameter mixed Assoc. Array with param names and
* values or string contain the
* additional parameter(s)
* @param $paramValue string (optional) Parameter value when
* $parameter contains just a
* parameter name.
* @return string
*/
function smarty_modifier_add_url_param($url, $parameter, $paramValue = NULL)
{

if ($paramValue !== NULL) {

// we were passed the parameter and value as
// separate plug-in parameters, so just apply
// them to the URL.
$url = _addURLParameter ($url, $parameter, $paramValue) ;

} elseif (is_array($parameter)) {

// we were passed an assoc. array containing
// parameter names and parameter values, so
// apply them all to the URL.
foreach ($parameter as $paramName => $paramValue) {
$url = _addURLParameter ($url, $paramName, $paramValue) ;
}

} else {

// was passed a string containing at least one parameter
// so parse out those passed and apply them separately
// to the URL.

$numParams = preg_match_all('/([^=?&]+?)=([^&]*)/', $parameter, $matches, PREG_SET_ORDER) ;

foreach ($matches as $match) {
$url = _addURLParameter ($url, $match[1], $match[2]) ;
}

}

return $url ;
}

function _addURLParameter ($url, $paramName, $paramValue) {

// first check whether the parameter is already
// defined in the URL so that we can just update
// the value if that's the case.

if (preg_match('/[?&]('.$paramName.')=[^&]*/', $url)) {

// parameter is already defined in the URL, so
// replace the parameter value, rather than
// append it to the end.
$url = preg_replace('/([?&]'.$paramName.')=[^&]*/', '$1='.$paramValue, $url) ;

} else {
// can simply append to the end of the URL, once
// we know whether this is the only parameter in
// there or not.
$url .= strpos($url, '?') ? '&' : '?';
$url .= $paramName . '=' . $paramValue;

}
return $url ;
}

?>[/php:1:16484b570e]
_________________
Mark Mitchenall


Last edited by mitchenall on Sat Jan 29, 2005 11:39 am; edited 1 time in total
Back to top
View user's profile Send private message Visit poster's website
soukupl
Smarty n00b


Joined: 28 Jan 2005
Posts: 1

PostPosted: Fri Jan 28, 2005 10:26 pm    Post subject: Reply with quote

Hi,
very nice and useful modificator Smile)
But, there is one problem. What if I need to unset variable in GET?

Example:
Code:
url is: index.php?action=read&id=17&page=18


and I need only one modification of url - REMOVE the action...

I have found only one way how to do it with your modifier:
Code:
{$smarty.server.REQUEST_URI|add_url_param:'action':''}

But this will result in error (the empty url param will be duplicated in url each time it is set via your modifier Sad
So i have ask some clever people on one forum, and here is the answer...
Just add this one line at the end of the script (before return $url;)
Code:
$url = preg_replace('/(\w+=&?)(?=(\w+=))|(&?\w+=)(?=(&\w+=)*$)|(\??\w+=&?)(?=(\w+=&?)*$)/', '', $url);


This will filter all variables without value Wink But, this is not the best way Sad

So if you will have time, can you please consider adding feature to REMOVE some variable from the existing url (if it exists there)?

Thanks for the NICE modifier (it realy helps me).

Ladislav Soukup
Back to top
View user's profile Send private message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7270
Location: Lincoln Nebraska, USA

PostPosted: Fri Jan 28, 2005 10:35 pm    Post subject: Re: Modifier add_url_param Reply with quote

mitchenall wrote:

[php:1:1ed449816d]if (preg_match('/\?/', $url))[/php:1:1ed449816d]


Just a programmers note, simple tests like these are more efficiently handled without regular expressions:

[php:1:1ed449816d]if(strpos($url, '?') !== false)[/php:1:1ed449816d]

This whole segment could be shortened up with:

[php:1:1ed449816d]
$url .= strpos($url, '?') ? '&' : '?';
$url .= $paramName . '=' . $paramValue;
[/php:1:1ed449816d]
Back to top
View user's profile Send private message Visit poster's website
mitchenall
Smarty Pro


Joined: 27 Feb 2004
Posts: 107
Location: London, UK

PostPosted: Sat Jan 29, 2005 11:36 am    Post subject: Re: Modifier add_url_param Reply with quote

mohrt wrote:


This whole segment could be shortened up with:

[php:1:7b530d0727]
$url .= strpos($url, '?') ? '&' : '?';
$url .= $paramName . '=' . $paramValue;
[/php:1:7b530d0727]


Yeah.... I'd thought that too... plus the cost of using a regex function instead of the simpler string functions for this type of test. Thanks for that.
Back to top
View user's profile Send private message Visit poster's website
mitchenall
Smarty Pro


Joined: 27 Feb 2004
Posts: 107
Location: London, UK

PostPosted: Sat Jan 29, 2005 11:44 am    Post subject: Reply with quote

soukupl wrote:
Hi,
very nice and useful modificator Smile)
But, there is one problem. What if I need to unset variable in GET?

Example:
Code:
url is: index.php?action=read&id=17&page=18


and I need only one modification of url - REMOVE the action...


Thanks for the comments. I actually hadn't needed that, but I can see that it's useful. I haven't done something to remove the parameter, as that breaks the name of the plug-in. But instead I have made it so that you can make the value of the parameter an empty string.



soukupl wrote:


I have found only one way how to do it with your modifier:
Code:
{$smarty.server.REQUEST_URI|add_url_param:'action':''}

But this will result in error (the empty url param will be duplicated in url each time it is set via your modifier Sad
So i have ask some clever people on one forum, and here is the answer...
Just add this one line at the end of the script (before return $url;)
Code:
$url = preg_replace('/(\w+=&?)(?=(\w+=))|(&?\w+=)(?=(&\w+=)*$)|(\??\w+=&?)(?=(\w+=&?)*$)/', '', $url);


This will filter all variables without value Wink But, this is not the best way Sad


I'm not sure about that. I'll have to look at your regex after a lot of coffee. I have modified the regex's in the above code to handle empty values in parameters. Hopefully this will help a bit. Plus it will set an empty value to an existing parameter. It just doesn't remove them as I think there should be a differently named modifier for that, i.e. modifier_remove_url_param Wink
Back to top
View user's profile Send private message Visit poster's website
barma3
Smarty Rookie


Joined: 12 May 2005
Posts: 5

PostPosted: Thu May 12, 2005 6:33 pm    Post subject: Reply with quote

Is it possible to remove PHPSESSID param from URL?

What you think about this solution:

Code:

// if exist PHPSESSID cookie, remove PHPSESSID param
// from URL.
   
if (isset($_COOKIE['PHPSESSID'])) {
   $url = preg_replace('/([?&]PHPSESSID=[^&]*)/', '', $url) ;
}
Back to top
View user's profile Send private message Visit poster's website
mitchenall
Smarty Pro


Joined: 27 Feb 2004
Posts: 107
Location: London, UK

PostPosted: Thu May 19, 2005 3:36 am    Post subject: Reply with quote

barma3 wrote:
Is it possible to remove PHPSESSID param from URL?

What you think about this solution:

Code:

// if exist PHPSESSID cookie, remove PHPSESSID param
// from URL.
   
if (isset($_COOKIE['PHPSESSID'])) {
   $url = preg_replace('/([?&]PHPSESSID=[^&]*)/', '', $url) ;
}


Hey.. that could be a nice idea! .... strip the PHPSESSID from a URL if the template being output is cached, but it needs to be more generic than that so that it identifies the variable being used as the session ID, just in case it's been customised.

Still.... it sounds a little like it's beyond the scope of this modifier. If you want to remove parameters, I think there should be a modifier which explicitly states that.

Also, when it comes to stripping out PHPSESSID params, I think this would be better handed in a post-filter. Nice idea though.

Best,

Mark
_________________
Mark Mitchenall
Back to top
View user's profile Send private message Visit poster's website
stagnate
Smarty n00b


Joined: 08 Feb 2005
Posts: 2

PostPosted: Mon May 30, 2005 3:45 am    Post subject: strpos doesn't work for empty param string Reply with quote

Note that if ? is the first character, your strpos function doesn't work as expected (0 evaluates as false but should be true). Works fine for a URL, but worth watching out for.

However, the code doesn't work for a URL with just ? at the end. Couple of ways to handle it but you can do whatever's elegant. strpos compared to length of string, perhaps.
Back to top
View user's profile Send private message
Lykurg
Smarty Rookie


Joined: 18 Mar 2005
Posts: 8

PostPosted: Wed Jun 01, 2005 1:51 pm    Post subject: Reply with quote

Hi,

I have the same problem with adding parameters to my links in the templates, and your modifier is nice, but:
The real php-script decides wich parameters should be added, and so the parameter must be assignd first to the template, and then you must take care, that all links are modified.
Is it possible to write a outputfilter, which is using your modifier? I thougt the postfilter extracts all relative links and add a assigned parameter. (For forms maybe hidden-fields) Because then you don't have to care about all the links you are using in your templates.

The only problem is, how to assing a variable to an outputfilter?


Thought such kind of an outputfilter would be nice,
Lykurg
Back to top
View user's profile Send private message
mitchenall
Smarty Pro


Joined: 27 Feb 2004
Posts: 107
Location: London, UK

PostPosted: Mon Jun 06, 2005 8:02 pm    Post subject: Reply with quote

Lykurg wrote:

The only problem is, how to assing a variable to an outputfilter?


The outputfilter gets the smarty instance in it's 2nd parameter, so you can just get the assigned variable from there, can't you?
Back to top
View user's profile Send private message Visit poster's website
douglassdavis
Smarty Junkie


Joined: 21 Jan 2008
Posts: 539

PostPosted: Wed Dec 04, 2013 4:11 pm    Post subject: another version Reply with quote

I made a different version of this (still smarty 2). Just in case it is useful, I decided to post it. Note that it can set and unset (by setting to null) parameters. It also handles parameters that are arrays. Example usage is:

Code:

<a href="<{$url|add_url_param:'page=1&ajax=' }>" 
...



Code:



/**
 * Smarty plugin
 * @package Smarty
 * @subpackage plugins
 */


/**
 * Smarty add_url_param modifier plugin.
 *
 * Will add the parameters in the query string given to the URL.
 * If the URL already has these parameters, then they will be replaced.
 *
 * Type:     modifier<br>
 * Name:     add_url_param<br>
 * Purpose:  Add a parameter to the end of a URL.
 * @author   Douglass Davis
 * @param url A url
 * @param add_query_string The parameter to add in the form of param=value
 * @return The new url
 */


function smarty_modifier_add_url_param($url, $add_query_string)
{
   
   // parse original URL
    $parsed_url = parse_url($url);

   $old_qs_parsed = array();

   // parse query strings
   parse_str($parsed_url['query'], $old_qs_parsed);

   parse_str($add_query_string, $add_qs_parsed);


   // replace old query string params with new
   $new_qs_parsed = smarty_array_merge_recursive_simple($old_qs_parsed, $add_qs_parsed);

   // remove empty params
   foreach ($new_qs_parsed as $key => $value)
   {
      if ($value === null || $value === '')
         unset($new_qs_parsed[$key]);
   }

   $parsed_url['query'] = http_build_query($new_qs_parsed);


   // rebuild URL from parts
   $new_url = '';

   if ($parsed_url['scheme'])
   {
      $new_url .= $parsed_url['scheme'].'://';
   }

   if ($parsed_url['user'])
   {
      $new_url .= $parsed_url['user'];

      if ($parsed_url['pass'])
      {
         $new_url .= ':'.$parsed_url['pass'];
      }

      $new_url .= '@';
   }

   if ($parsed_url['host'])
   {
      $new_url .= $parsed_url['host'];
   }

   if ($parsed_url['path'])
   {
      $new_url .= $parsed_url['path'];
   }

   if ($parsed_url['query'] || $parsed_url['fragment'])
   {
      $new_url .= '?';
   }

   if ($parsed_url['query'])
   {
      $new_url .= $parsed_url['query'];
   }

   if ($parsed_url['fragment'])
   {
      $new_url .= '#'.$parsed_url['fragment'];
   }

   return $new_url;
}




// array_merge handles numeric keys differently than string keys.
// For numeric keys it combines the values in the arrays.
// For string keys it replaces them.
//
// However, array_merge_recursive doesn't have that expected behavior.
//
// So, the following is a replacement for array_merge_recursive that
// acts more like array_merge.
//
// From comments in http://www.php.net/manual/en/function.array-merge-recursive.php
//

function smarty_array_merge_recursive_simple() {

    if (func_num_args() < 2) {
        trigger_error(__FUNCTION__ .' needs two or more array arguments', E_USER_WARNING);
        return;
    }
    $arrays = func_get_args();
    $merged = array();
    while ($arrays) {
        $array = array_shift($arrays);
        if (!is_array($array)) {
            trigger_error(__FUNCTION__ .' encountered a non array argument', E_USER_WARNING);
            return;
        }
        if (!$array)
            continue;
        foreach ($array as $key => $value)
            if (is_string($key))
                if (is_array($value) && array_key_exists($key, $merged) && is_array($merged[$key]))
                    $merged[$key] = call_user_func(__FUNCTION__, $merged[$key], $value);
                else
                    $merged[$key] = $value;
            else
                $merged[] = $value;
    }
    return $merged;
}

Back to top
View user's profile Send private message
osben
Smarty n00b


Joined: 17 Aug 2014
Posts: 1

PostPosted: Sun Aug 17, 2014 9:23 pm    Post subject: Reply with quote

Code:
/**
   * URL
   */
    public function url($params = array())
    {
      $url = @parse_url($_SERVER["REQUEST_URI"]);
      parse_str($url['query'], $query);
      
      if(get_magic_quotes_gpc())
         foreach($query as &$v)
         {
            if(!is_array($v))
               $v = stripslashes(urldecode($v));
         }

      foreach($params as $name=>$value)
         $query[$name] = $value;

      $query_is_empty = true;
      foreach($query as $name=>$value)
         if($value!='' && $value!=null)
            $query_is_empty = false;
      
      if(!$query_is_empty)
         $url['query'] = http_build_query($query);
      else
         $url['query'] = null;
         
      $result = http_build_url(null, $url);
      return $result;
    }
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Smarty Forum Index -> Plugins All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP