I have a small issue with manipulating the current URL query string to add an extra parameter at the end.
Per example, say there's a category layout for products, the URL would be:
index.php?category=3&type=5
Now, on that page I have a link for a layout that is either a table or a grid. In those URLs I currently have:
<a href="index.php?<?php echo preg_replace($array,'',$_SERVER['QUERY_STRING']); ?>&layout=grid" ...
Then, I do the same for the table href as well. Also in my array I have just:
$array = array ( '/&layout=table/', '/&layout=grid/' )
Is this the right way, or is there a better way for doing this? I'm asking because without preg_replace, it will continue adding that same layout parameter everytime it is clicked, so it will also show the previous parameter, then the next, then the next.. without removing the previous layout parameters.
Any insight on this will be much appreciated.
EDIT:
Thanks to the answers below, I have created a little function:
function buildQuery($key,$value) {
$params = $_GET;
$params[$key] = $value;
return http_build_query($params);
}
Then its only a matter off:
grid
this might seem pointless but i like to have my view / template files without the extra set vars. Im a clean freak. I might even return the 'index.php?' with it just so i can be more lazy, anyways something to play with now :)..
If you want to modify the query string, it's easier to simply modify the GET variables and rebuild the query string:
$params = $_GET;
$params['layout'] = 'new_layout';
Then:
...
Although you could also do:
...
Think about directly parsing the $_GET paramaters to build your url.
I think what you want to do is have the link going to index.php with all the same parameters as you have at the moment, but changing layout to grid. I'd suggest you do something like this:
<?php
// make a copy of the $_GET array with all the parameters from the query string
$params = $_GET;
// set layout=grid regardless of whether layout was set before or its value
$params['layout'] = 'grid';
// generate a query string to append to your urls.
// Note that & is used as the arg separator; this is necessary for XHTML and advised for HTML
$queryString = http_build_query($params, '', '&');
?>
href="index.php?<?php echo $queryString; ?>">
This is much easier than trying to edit and fix the $_SERVER['QUERY_STRING'] yourself.
Related
I have on website a part which is at the moment hidden. I have also a few requests on query string ?visible=true. How can i add this query string automatic to every url if in url is this querystring available ?visible=true? This is simple method where i enable hidden parts of website.
If i understand you correctly, you mean your page loads with various parameters and your wanting to have the next page load with any existing parameters as well as any that you want to add along with them.?
Example: somepage.html?visible=true&showmenu=5
Then you want to add "anotheropt=helloworld"
Example: somepage.html?visible=true&showmenu=5&anotheropt=helloworld
To do something like this, you have a few different options depending on what resources you have available...
Javascript / Client Side:
Use a function to get all the parameters from the current url Something Like This
Loop over all of them and build a new string with the ones you want to keep
Add your own to the end of the string
Note the above link only retrieves them by name, you would want to simple do a split/explode type operation on the string and them perform your own logic to which items you want.
PHP / Server Side:
Same deal, loop or something to get all of the current ones $_GET should do...
Echo these into a hidden input box and append them to the end of new links..
Note you still need to filter your parameters to choose what to keep and what to ignore.
Further more, it would not be hard to write or find a function that will merge two arrays or perform a comparison.
OR
Is it as simple as this below??
var x = location.search;
var sl = "mypage.html" + x + "&someoption=helloworld"
OR THIS
<?php
if (isset($_GET['visible']) && $_GET['visible']=='true') {
echo "SHOW ME, i was a hidden element";
} else {
// NOTHING, VISIBLE IS NOT TRUE OR NOT SET...
}
?>
Your home page is accessed without ?visible=true. So you have add it at-least once. When you make link, call some function for that:
class Link {
const BASE_URL = 'http://example.com';
public static function url($link, $visible = false) {
return self::BASE_URL."/".$link.(!empty($visible) ? '?visible=true' : '');
}
}
I have small problem.
I've coded a full website in php using CodeIgniter framework. One of my modules is search module, it contains text input with keyword and three select lists with filtering criterias.
That's ok, when I'm searching something - result's listing pagination is done via URL like that:
mysite.com/$keyword/$criteria1/$criteria2/$criteria3/$offset
works like a charm.
But when I'm entering into one of my images (it's image gallery) I want to have an option to go into NEXT and PREVIOUS image from my search results - the ones which I entered this image from.
I'm solving this case now in this way - I have session table called 'search_conditions' and I'm storing values of keyword and my three criterias there, but that's quite not comfortable, because why if someone opens second window and search something else there?
Then all of his searches in another windows or tabs are getting the same criteria - because with every new search, user overwrite the session value.
My next and previous functions:
public function next($count)
{
$search = $this->session->userdata('search_conditions'); //getting session table and overwriting it
$catid = isset($search['catid'])?$search['catid']:'0';
$brandid = isset($search['brandid'])?$search['brandid']:'0';
$prodid = isset($search['prodid'])?$search['prodid']:'0';
$keyword = isset($search['keyword'])?$search['keyword']:'';
$res = $this->search_model->main_search($keyword, $catid, $brandid, $prodid, $count, 1);
}
public function previous($count)
{
$search = $this->session->userdata('search_conditions');
$catid = isset($search['catid'])?$search['catid']:'0';
$brandid = isset($search['brandid'])?$search['brandid']:'0';
$prodid = isset($search['prodid'])?$search['prodid']:'0';
$keyword = isset($search['keyword'])?$search['keyword']:'';
$res = $this->search_model->main_search($keyword, $catid, $brandid, $prodid, $count-2, 1);
}
Can you recommend me some other, more comfortable solution, because this seems not to be good...
: )
Thank you!
Add an index to the $search_conditions variable:
$search_conditions[1]['catid']
$search_conditions[1]['brandid']
...
then refer to it with a controller's or config variable. This way you can allow one session to store multiple search conditions.
But I would recommend you drop storing the search condition in session. Instead, just pass it with the URI. Session data, in the case you describe, work as an intermediary; you don't need it. Use the Pagination Class and pass the search page number, not the direction (next or previous) to the URI.
Do not worry that the URI may look ugly - it only depends on what user searches for, and it's still friendly to share. Your only concern is if the GET string does not extend the limited length.
Pull the segments from the URI in your next() and previous() functions. Use the codeigniter URL helper. That should allow you to pass the different search criterion as variables to the next page, this would also remove your need to use the session.
I am creating a website using the MVC structure. Below is a code I have used to use clean URLS and load the appropriate files. However it only works for the first level.
Say I wanted to visit mywebsite.com/admin it would work, however mywebsite.com/admin/dashboard would not. The problem is in the arrays, how could I get the array to load content after the 2nd level along with the second level.
Would it be best to create an array like this?
Array
- controller
- view
- dashboard
Any help here would be great. Also as a side question. What would be the best way to set up "custom" urls. So if I were to put in mywebsite.com/announcement it would check to see if its got controllers, failing that, check to see if it's got custom content (maybe a file of the same name in "customs" folder, and then if there's nothing execute the 404 page not found stuff) This isn't a priority question though, but loosely associated in how the code works so I thought it best to add.
function hook() {
$params = parse_params();
$url = $_SERVER['REQUEST_URI'];
$url = str_replace('?'.$_SERVER['QUERY_STRING'], '', $url);
$urlArray = array();
$urlArray = explode("/",$url);
var_dump($urlArray);
if (isset($urlArray[2]) & !empty($urlArray[2])) {
$route['controller'] = $urlArray[2];
} else {
$route['controller'] = 'front'; // Default Action
}
if (isset($urlArray[3]) & !empty($urlArray[3])) {
$route['view'] = $urlArray[3];
} else {
$route['view'] = 'index'; // Default Action
}
include(CONTROLLER_PATH.$route['controller'].'.php');
include(VIEW_PATH.$route['controller'].DS.$route['view'].'.php');
var_dump($route['controller']);
var_dump($route['view']);
var_dump($urlArray);
var_dump($params);
// reseting messages
$_SESSION['flash']['notice'] = '';
$_SESSION['flash']['warning'] = '';
}
// Return form array
function parse_params() {
$params = array();
if(!empty($_POST)) {
$params = array_merge($params, $_POST);
}
if(!empty($_GET)) {
$params = array_merge($params, $_GET);
}
return $params;
}
Can you clarify this: "The problem is in the arrays, how could I get the array to load content after the 2nd level along with the second level."
I don't understand how you want this thing to work. I checked your code and it works. Maybe you just need to put $urlArray[1] instead of $urlArray[2] and 2 instead of 3? First element in the array is at index 0.
Usually it's done like this:
Url format:
/controller/action/param1/param2/...
-controller- should be a class. That class has a method/function called -action-.
ex. /shoes/show/121/ --> this will load controller shoes
and execute the method/function show(121)
that will show the shoes that have the id 121 in the
database.
ex. /shoes/list/sport --> this will load controller shoes
and execute function list('sport') that will list all
shoes in the sport category.
As you can see, you only load one controller and from that controller you run only one function and that function will get the rest of the path and use it as parameters.
If you want to have multiple controllers for one URL, then the rest of the controllers will have to be loaded from the main controller. Most MVCs (like CodeIgniter) load only one controller per URL.
Second question:
Best way for pretty urls would be to save them in the db. This means you can have URLs like this:
/I-can-write-anything-here-No-need-to-add-ids-or-controller-names
Then you take this URL and search it in db and get the -controller- and -action- that you need for this URL.
But I have yet to see a popular MVC framework do this. I guess the reason is that the db will get a lot of queries for text matches and that will slow things down.
Popular MVC frameworks use:
/controller/action/param1/param2
This has the benefit that you can directly find the controller/action from the url.
The downside is that you will get urls like:
/shoes/list/sport
//when what you really want is
/shoes/sport
//or just
/sport //if the website only sells shoes
This can be fixed by redirecting /shoes/sport to /shoes/list/sport
If you make your own MVC then you should use OOP because if not, thing will get ugly quick: all actions/functions are in the same namespace.
Personally I would recommend that you use one of the many PHP frameworks that exist as that will take care of the routing for you and let you concentrate on writing your application. CakePHP is one that I've used for a while and it makes my life so much easier.
What I do:
I create a .htaccess file that redirects an url like www.example.com/url/path/or/something to www.example.com/index.php?url=url/path/or/something, so it will be pretty easy to do an explode on your $_GET['url']
Second, it's better because everything a user input, will be redirected to your index.php, so you have FULL control over EVERYTHING.
If you want I can PM you the url to my mvc (bitbucket) so you can have a look on how I do this ;)
(Sorry for the others, but I don't like to put url's to my site in public)
edit:
To be more precise to your particular question; It will solve your problem, because everything goes to index.php and you have full control over the requested url.
My site is organized into topics. Users can switch between topics on any page, at any time. I would like to be able to pass this topic along from page to page. I am guessing this should be done in a php post or get variable. I can grab the topic from the post or get variable and then run the rest of my site. However, this seems like it requires a form on every page to pass along this variable. As of now, the only way I have passed post or get variables was from forms on the previous page. I have never passed along these variables over several pages. Will I need a form on every page to pass these variables? Also, is this the standard way of doing this?
You should probably use GET, because it sounds like you're just trying to display different information, and POST is supposed to be for performing changes or actions.
If you decide to use GET variables, all you have to do is append them to the end of the link's href:
MORE BANANAS
the least overhead method of doing this would be to add some javascript that sets a cookie each time someone navigates to a new topic. This would assume you can select somehow all links that match topics (presumably trough classes)
A better method - because of compatibility,reliability and overhead - but not necessarily feasible, if a large number of links needs changing, is to use GET requests, as another poster suggested
You can create a helper function to generate your anchor tags and just append any existing query string to it, so instead of this:
Foobar
you would do this:
<?php echo anchor('page2.php','Foobar'); ?>
where your function would look like this:
/**
* Function creates an anchor tag and optionally
* appends an existing query string
* #param string $url
* #param string $txt
* #param bool $attach_qs Whether or not to follow a query string
*/
function anchor($url, $txt, $attach_qs = true)
{
$qs = '';
if ($attach_qs === true) {
$qs = (!empty($_SERVER['QUERY_STRING'])) ? '?' . $_SERVER['QUERY_STRING'] : '';
}
return '' . $txt . '';
}
Kolink's suggestion of placing the topic in via a PHP echo statement for every URL would certainly work. There is however, another option that I am surprised hasn't come up yet.
You could use PHPs Session Manager to store the variable. It is similar to using cookies; however, it is only temporary (limited to the session). Where a cookie can be persistent over multiple sessions.
<?php
// use this code before the page is generated, before the topic is decided.
session_start();
if (isset($_GET['topic']) && $_GET['topic'] != $_SESSION['topic']) {
// GET['topic'] is set, session variable does not match
// you may want to sanitize or limit what can be passed via ?topic=
$_SESSION['topic'] = $_GET['topic'];
} else if (isset($_SESSION['topic'])) {
// Session topic is not empty, run code to display appropriate content
} else {
// No topic is set, display default
}
?>
It's by no means the only solution, but it does give you an extra option.
I'm doing a website. There's a pagination, you click on links and they take you to the page you need, the links pass $_GET variable ( a href="?pn=2" ) and that works fine.
However when i add the category links (also contain $_GET variable
(a href="?sort=english") on the same page, which kind of sort the content on the page, and click it, the system simply overrides the url and deletes all the previous $_GET's.
For example, I'm on page 2 (http://website.com/index.php?pn=2)
and then I click this sorting link and what I'm expecting to get is this (http://website.com/index.php?pn=2&sort=english), but what I get is this:
(http://website.com/index.php?sort=english). It simply overrides the previous $_GET, instead of adding to it!
A relative URI consisting of just a query string will replace the entire existing query string. There is no way to write a URL that will add to an existing query. You have to write the complete query string that you want.
You can maintain the existing string by adding it explicitly:
href="?foo=<?php echo htmlspecialchars($_GET['foo']); ?>&bar=123"
Try using this:
$_SERVER['REQUEST_URI'];
On this link you can see examples. And on this link I have uploaded test document where you can try it yourself, it just prints out this line from above.
EDIT: Although this can help you get the current parameters in URL, I think it's not solution for you. Like Quentin said, you will have to write full link manually and maintain each parameter.
You could create a function that will iterate through your $_GET array and create a query string. Then all you would have to do is change your $_GET array and generate this query string.
Pseudocode (slash I don't really know PHP but here's a good example you should be able to follow):
function create_query_string($array) {
$kvps = array();
for ($key in $array) {
array_push($kvps, "$key=$array[$key]");
}
return "?" . implode("&", $kvps);
}
Usage:
$_GET["sort"] = "english";
$query_string = create_query_string($_GET);
You need to maintain the query parameters when you create the new links. The links on the page should be something like this:
Sort by English
The HTTP protocol is stateless -- it doesn't remember the past. You have to remind it of what the previous HTTP parameters were via PHP or other methods (cookies, etc). In your case, you need to remind it what the current page number is, as in the example above.