i have alot of get values that define the page the user gonna see , for example for "profile" i will show the profile page and so on..
to find out what page to display i tried to do something like that:
switch ($_GET) {
case 'profile':
require_once('function/profile.php');
break;
case 'team':
require_once('function/team.php');
break;
but it shows no result..
i send the GET request like that : index.php?profile , for example..
what is the problem here and how can i can manage to do something similar that work as well. thank you in advance!
To make your example work, you could replace $_GET with key($_GET)
be aware though that key() will return the first key of an array, so if you change your URL's variable order, this line'll stop functioning.
$_GET is an array from the key value pairs found in the query string (part of the url after the script name and a question mark).
For example, the query string test=1&foo=bar will translate to:
Array(
test => 1
foo => 'bar'
)
In the OP example, index.php?profile, you will end up with a $_GET array like:
Array(
profile => null
)
Problem with doing urls like this is that it is non-standard. When you do things in a non-standard way, you have to come up with non-standard solutions to fix the problems.
Here are a few options along with issues that each has:
You can use $_SERVER['QUERY_STRING'] which will get you everything after the ? in the url. This is fine if the only thing passed in the url is just profile (or some other single value). In that case, $_SERVER['QUERY_STRING'] will have nothing but profile in it. But you also then lose the ability to pass additional parameters in the get string.
You can go with the method described by #stewe. The php key function will return the key from the current position in the array passed in. If you haven't done any looping, the current position is the first element. This will work fine with multiple get parameters as well. Your query string will just look like index.php?profile&test=1&foo=bar. The problem is that profile (or whatever page) has to be the first or else key will return whatever the key is for the first parameter passed.
Another option is to just go with the standard method of using a key and value. Regardless of page, you use the same key and just the value changes. You then have urls that look like index.php?page=profile and you can always access the page using $_GET['page'].
You can use mod_rewrite. It is simple to setup, most hosts support it (or some other similar) and there are millions of tutorials and examples on how to get it to work. You end up with the cleanest urls and it works with query string parameters. For example, /profile/ can be rewritten to point to /index.php?page=profile. The user sees /profile/ and php sees the standard. This allows you to use $_GET['page'] to get the requested page and not have to do extra parsing to get other values inside php.
$_GET is an array or variables that are populated based on the URL's query string. You need to do something like:
switch ($_GET['myVar']) { ... }
where your URL would look like:
http://www.domain.com/index.php?myVar=value
For more information, see the PHP Manual for $_GET.
$_GET by itself is not very useful to you. I suppose you are looking for a key, like 'page', right ? Remember to declare a default value as well.
so..
$page = $_GET['page'];
switch ($page) {
case 'profile':
require_once('function/profile.php');
break;
case 'team':
require_once('function/team.php');
break;
default:
require_once('function/page-not-found.php');
}
$_GET is a super global variable, where the data are sent as stored as array. So you have to
access it using Index
Assuming you page you are trying to include a page when the data are sent like this:
domain.com?page=product
Then you have to use switch like this
switch($_GET['page']) {
....
}
Note: May be I dont have to remind you how vulnerable this code towards injection.
It's an array, so you need to use a loop to iterate on the values:
foreach($_GET as $key => $val){
switch ($key) {
case 'profile':
require_once('function/profile.php');
break;
case 'team':
require_once('function/team.php');
break;
}
}
with foreach you can get the key and value pair
foreach ($_GET as $switchkey => $switchval) {
switch ($switchkey) {
case 'profile':
require_once('function/profile.php');
break;
case 'team':
require_once('function/team.php');
break;
}
}
i actually use the following after a normal get resulting in lfi/rfi vulnerabilities. the following solution was submitted to me via a bug bounty program and works great. notice the inclusion of the default attribute. very important. the following should be the only acceptable answer. Credit to the flying spaghetti monster(His Noodly Appendage)
switch($_GET['page']) {
case 'foo':
include('pages/foo.php');
break;
case 'bar':
include('pages/bar.php');
break;
default:
include('pages/home.php');
}
As mentioned before, the first thing that seems to come to mind is the non standard way of passing the information. which will generate some difficulties when you parse the values. Although, for me, the main problem is not checking/sanitazing/cleaning the data on $_GET. May be it's too obvious and since almost all the answers have been given by people who seem to know what are they doing, I'll assume they just didn't mention it because of that
But remember that if you don't check it, you are vulnerable to attacks and malfunction of your script. The extent of the damage depends on your own application, so it's not easy to predict.
In any case, this is what I'll do, including the html
<?php
// initialize variables
$variable_1 = false; // assume this is the page you want to load
$variable_2 = false;
$default = 'index.php'; // the idea is to load something controlled by you. index, error, 404, etc.
// process $_GET, check, clean and assign values
if ( isset( $_GET ) !== false ) {
foreach ( $_GET as $keys => $values ) {
// check both, $keys and $values for; character set, length, validity against a white list, content
// using an if to match the $keys garantees that regardless of the order, you will get what you want
if ( $keys === 'field_1' ) {
// do what you have to do with this, for instance ...
$variable_1 = $values;
}
if ( $keys === 'field_2' ) {
// do what you have to do with this, for instance ...
$variable_2 = $values;
}
unset( $_GET[$keys] );
}
unset ( $keys, $values );
}
// check there are no surprises on $_GET. Load and study anything here
if ( empty( $_GET ) === false ) {
// it should be empty, so log what is in here and prepare your code for that
unset( $_GET );
} else {
unset( $_GET );
}
// process the variables according to what you want to do
// if there are just a few options, and they are not going to change often
// use a switch, otherwise, use a method to check if a file/content exists
// for the request and load it. If it doesn't exist, inform the user
// with out giving away internals and suggest a new destination
// process other variables, here or before this part, wherever makes sense
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>testing get</title>
</head>
<body>
<form method="get" action="test_get_00.php" accept-charset="utf-8">
<p><label for="field_1">write something<input type="text" id="field_1" name="field_1" /></label></p>
<p><label for="field_2">write something<input type="text" id="field_2" name="field_2" /></label></p>
<p><button type="submit">send</button></p>
</form>
</body>
</html>
Of course you can do a few more things, but if you prepare your form properly, including the character set, you have less worries, or at least a few more known elements. It's not failproof, but it helps.
Also, the mechanics I mention above work on a white list mindset, that is the idea of the foreach, to check that you get what you expect and discard the rest, after logging it.
You are trying to archive SEO urls in the wrong way.
I see that index.php?profile is better then index.php?page=profile but it's the wrong way of act in this case.
You should use index.php?page=profile and then apply a rewrite rule to create SEO urls, like this one:
RewriteEngine On
RewriteRule ^(.*)$ index.php?page=$1
In this way your users will use:
http://example.com/profile
and the page displayed will be:
http://example.com/index.php?page=profile
instead of switching on the keys (as proposed by key($_GET)) you could define one variable, in $_GET (url) named for example 'action' which would containt 'profile', or 'team' or whatever you wish in the future. then your switch, simply, will be :
switch ($_GET['action'])
so whatever action you assign to this key, you can use as a case in your switch
Related
I have a personal search site project I'm building, at the moment the only data that is being displayed on the website is data that is retrieved using SELECT queries and the GET method using the super global $_GET['example']. Now I don't know if I'm doing this wrong but some parts of my page are only displayed if certain GET variables in the URL are set or not empty. Below shows how my URL looks
EXAMPLE: index.php?search_category=guitar&main_category=9&postcode_val1=NP22&distance_default=100&submit=search
I have a lot of these if(isset($_GET['search_category']) type conditions in my website which are replied upon and show particular parts of content depending whether or not these are either true or false.
I have been on a lot of other websites that have similar URL's, I have tried to alter and manipulate these and the content does not break, alter or change in any way yet when i try this with my url it breaks my page and only certain parts of content gets displayed by being based on what is set. Is there some other layer of protection I should add, would using something like a rewrite rule help? The code below shows how I have wrote a drop down box based on what has been set In the URL but if a user edits the URL this is easily broken.
if(isset($_GET['search_category']) && isset($_GET['main_category']) &&
isset($_GET['postcode_val1']) && isset($_GET['distance_default']))
{
$stmt = $getFromUi->dispCategories();
echo "<option value='0'>All</option>";
echo "<option value='#'>-------------</option>";
while($row = $stmt->fetch(PDO::FETCH_OBJ))
{
$selected = '';
if(!empty($_GET['main_category']) && $_GET['main_category'] == $row->cat_id)
{
$selected = ' selected="selected"';
}
echo '<option value="'.htmlentities($row->cat_id).'"'.$selected.'>'.htmlentities($row->cat_title).'</option>';
}
}
It will break because the strict nature of logic you use on your code. The && mark with isset mean any parameter you define not set will not evaluate to true. If the parameter is quite flexible why not ||.
If you need it to still evaluate all parameter try to do limit first if condition to main determiner. like $_GET['search_category'] and use the remaining $_GET['other_parameter'] as needed inside the block code of main if.
You would need to use a post method, so that this goes through as a request instead. In my experiance, get will only fetch the url you open - not actually pass anything through unless its in the URL.
Not sure if that made any sense, but check post out.
https://www.w3schools.com/tags/ref_httpmethods.asp is a good place to start to see the difference of get vs post.
I'm designing a semi-basic tool in PHP, I have more experience server side, and not in PHP.
My tool contains 10-15 pages, and I am doing the navigation between them with the $_GET parameter.
In my code I have many if statements that look like:
if(isset[param1] && !isset[param2] && .....&& !isset[paramN]){
// code
}
You will agree with me, it's ugly, right?
Is it "how we do it" in PHP? or is there some kind of design pattern / functions for navigation in a PHP website?
Edit: To be clearer, what I want to know is: Is the proper way to design the navigation is with plenty of $_GET variables?
To avoid a huge if else statement try a switch statement:
$param1 = 'something';
switch (true){
case isset($param1):
echo "PARAM 1 is set";
break;
case isset($param2):
echo "PARAM 2 is set";
break;
default:
echo "None set";
}
And to answer your edit - Yes, you can use _GET variables for navigation and it is normal.
Actually the solution to this problem is a little bit complicated, than it might seem at first glance. And you need to implement a handler for that, since you're looking a cleanest way of handling GET parameters and invoking a code fragment.
In your case, your final API, should look like this (since you were asking for the design, not the for implementation):
$nav = new Nav($_GET);
$nav->whenSet('param1', 'param2')->andNotSet('param3')->then(function(){
});
$nav->whenSet('param3')->andNotSet('param1', 'param2')->then(function(){
});
// Or a simpler and shorter way
$nav->register($existingKeys, $nonExistingKeys, function(){
});
Another option you have is to use a routing mechanism. Most PHP frameworks provide this functionality. They all support optional route fragments, so you can handle parameters only defining one route path, like this /page/? (? - means optional).
This is my suggestion add conditions in an array and than use in_array()
echo in_array($yourVar, array('abc', 'def', 'hij', 'klm', 'nop'))
? True
: false;
UPDATE:
$get = "abc";
$navigation = array(
"abc"=>"yourneed",
"def"=>"yourneed2",
"ghi"=>"yourneed3",
);
foreach($navigation as $key => $value){
if($key == $get){
echo $value;
}
}
One more solution you can define routes also.
Same as CI and YII.
(I'm not using switch but you should definitely try that, and try using break between cases)
I'm using this at the moment, it seems to avoid mass-IFfing:
if (!$_GET) {
homePageFunction();
}elseif($_GET) {
contentPagesFunction($_GET['p']);
}
I have a menuer() function that outputs rel paths to content 'things' in links like:
<a href='?p=$relPath'>$name</a>
Although I could probably use different notation to tidy it further... Untested but like this:
if (!$_GET) homePageFunction();
elseif ($_GET) contentPagesFunction($_GET['p']);
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.
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.
I know result page that uses GET method can be bookmarked while the one using POST cannot be. I also know about the restrictions of the GET methods.
Now suppose I want to build a search engine which by default uses GET allowing users to bookmark but when the length of the search phrase exceeds the limit, switch to POST. On the server side I make use of $_GET or $_POST depending on which is set.
Is this doable?
If no, why?
If yes, please provide a brief outline.
Thanks
It is doable, no problem.
There is the $_REQUEST array that merges GET, POST, and COOKIE values but the better way would be to handle GET and POST manually in your script.
Just have your engine check both $_GET["variable"] and $_POST["variable"] and use whichever is set. If a variable is set in both methods, you need to decide which one you want to give precedence.
The only notable difference between the two methods is that a GET parameter has size limitations depending on browser and receiving web server (POST has limitations too, but they are usually in the range of several megabytes).
I think the general rule is that a GET string should never exceed 1024 characters.
Here's how you could use GET and POST in one:
<form action="myfile.php?var1=get1&var2=get2&var3=get3" method="post">
<input type="hidden" name="var1" value="post1" />
<input type="hidden" name="var2" value="post2" />
<input type="submit" />
</form>
The PHP:
print_r($_REQUEST);
// var1 = "post1"
// var2 = "post2"
// var3 = "get3"
print_r($_GET)
// var1 = "get1"
// var2 = "get2"
// var3 = "get3"
print_r($_POST);
// var1 = "post1"
// var2 = "post2"
You could use something like the following:
<?php
function getParam($key)
{
switch (true) {
case isset($_GET[$key]):
return $_GET[$key];
case isset($_POST[$key]):
return $_POST[$key];
case isset($_COOKIE[$key]):
return $_COOKIE[$key];
case isset($_SERVER[$key]):
return $_SERVER[$key];
case isset($_ENV[$key]):
return $_ENV[$key];
default:
return null;
}
}
It's also as well to be aware that using GET opens up a temptation among certain sets of users to manipulate the URL to 'see what happens' so it's absolutely necessary to ensure that your code suitably sanitises the input variables.
Of course you were doing that anyway ;-). But with get it pays to be doubly paranoid.
Myself if I'm using GET I'll generally set a cookie too and drop an ID of some sort in it, then cross-correlate that to a variable in the GET list, just to make sure there's absolutely no issues over user A manipulating the input and letting them see anything originating with user B.
Yes its doable, although (IMHO) the limit at which GET becomes cumbersome is significantly greater than the threshold at which a user interface for providing this much information becomes unusable. Also, the more complex a query you submit to a conventional search engine, the more effectively it can be resolved.
But I'm guessing you have your reasons.
The simplest way, from the information you've provided, to achieve this would be to change the form method at run time from GET to POST using javascript, e.g.
<form method='GET' id='searchform' target='search.php' onsubmit='
if (document.getElementById("searchdata")) {
if ((document.getElementById("searchdata").length >$some_threshold)
&& (document.getElementById("searchform"))) {
// 2nd if in case this moved to action for button
document.getElementById("searchform").method="POST";
}
}
return true;'>
<textarea name='searchdata' id='searchdata'>
</textarea>
<input type='submit' value='go get it'>
</form>
Which also downgrades nicely for non-javascript clients.
C.
function getQVar($key){
return isset($_GET[$key]) ? $_GET[$key] : (isset($_POST[$key]) ? $_POST[$key] : null);
}
echo getQVar("name");
Switch around $_GET and $_POST to prioritize POST over GET vars.