Passing multiple variables through a URL using OR instead of AND (&) - php

I am trying to set up a website that will have a drop-down menu, and each option will direct you to a subset of the database. For example, people in the state of Ohio, or the state of Michigan, etc. I have some people who want to be pulled no matter what the state and there is a category called all_states. I've seen how I can add variables to the URL (example: http://www.website.com/page.htm?OH=1) I've also seen examples where two variables are set (example: http://www.website.com/page.htm?OH=1&all_states=1). But how do I set it up so that only one condition needs to be met, effectively an OR instead of an AND? I want to be able to set up links to call data, for example, for those where Ohio is true (OH=1) OR all_states is true (all_states=1) because some people did not specify a particular state but will help in all states so I need to be able to pull in each list in one URL command.

The & symbol in the URL is just a separator between variables, and does not mean that anything is required. Your PHP (or whatever is parsing the GET variables) is what should check for that.
For example, you could parse it by writing something like (in PHP):
if(isset($_GET['all_states'])){
// do something for all states //
}else{
$states = ["OH", "CA", ...];
// recurse through state abbreviations //
foreach($state in $states){
if(isset($_GET[$state])){
// do something for individual state //
}
}
}
In Javascript:
$(document).ready(function(e){
var allStates = getParameterByName('all_states');
if(isset(allStates)){
// do something for all states //
}else{
// check & do something for individual states //
}
});
function isset(obj){
return typeof(obj) !== 'undefined' && obj != null && obj !== '';
}
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
Although I would personally recommend using a state variable, like this:
State Variable for Individual State: http://whatever.com/something.php?state=OH
State Variable for All States: http://whatever.com/something.php?state=all
And just check what the state variable is in your PHP instead.

Related

Rewrite parameters in query string to be compatible to php array

PHP accept array parameters in the query string using the [ ] format
http://my.url/bar.php?foo[]=1&foo[]=2&foo[]=3&foo[]=4
I need to allow the format without square brackets
http://my.url/bar.php?foo=1&foo=2&foo=3&foo=4
I don't want to change my application so I thought about rewrite the second URL to the first one. Is this possible in NGINX?
I think the solution is achievable with a quite simple lua script.
You could:
loop get_uri_args()
accumulate multiple values for the same key in a new key[] variable
put the new args in place using set_uri_args()
Something like the following (not tested, ajust to your real case):
// "foo=val1&bar=baz%foo=val2"
location = /test {
content_by_lua_block {
local args = ngx.req.get_uri_args()
local qs = {}
for key, val in pairs(args) do
if type(val) == "table" then
table.insert(qs, key.."[]" .. table.concat(val, key.."[]"))
else
table.insert(qs, val)
end
end
// qs = { foo[] = {"val1", "val2"}, bar = "baz" }
ngx.req.set_uri_args(qs)
}
// "foo[]=val1&foo[]=val2&bar=baz"
}
Note: this has to be extended if you whant to take into account "multidimensional" arrays too.

comparing variables in PHP with different language files

I have a select menu for users.
It is populated by PHP variables, which are all language variables. For example:
$word = $lang['word'];
$select = array($word);
Therefore, the select menu options will change based on the language the user has chosen. I need to be able to compare users' selections to each other. For example:
if($user1word == $user2word) ...
But because of the language files, this doesn't work. Obviously "one" != "Uno" even though they're the same.
My first fix was to change everything to a numeric value before posting it to the database. Example:
if($_POST['word'] == $lang['word']) { $userWord = 1 }
This worked perfectly for all words except those that contained special characters (å, æ, é...) and nothing I did could resolve this (I tried normalizer; language-specific accept-char onchange events for the form; utf8_encode. It was hopeless.
Currently everything saves to the database as text, dependent on the language the user is in. So if "Language" is an option, but you're in Norwegian, it saves as "Språk".
I need a simple solution that doesn't crush my mind - I am new to PHP.
Currently everything saves to the database as text, dependent on the language the user is in.
This is a design flaw in my opinion. Ideally your data would be as agnostic as possible to language and translations would be performed just for the UI with tools like gettext. Typically items like select values would be stored with keys or IDs.
Use a map that is based on a common index, this index can be english, spanish or numeric. i'd suggest numeric. Store the numeric index in your database.
A step in the right direction:
$lang['en'][0] = 'Hello';
$lang['de'][0] = 'Hallo';
$lang['es'][0] = 'Hola';
$lang['en'][1] = 'Sup?';
$lang['de'][1] = 'Wie gehts?';
$lang['es'][1] = 'Que pasa?';
$userLang = 'en';
// show the select
echo '<select name="word">';
foreach ( $lang[$userLang] as $index => $word {
echo '<option value="'.$index.'">'.$word.'</option>';
}
echo '</select>';
// show the selected word:
echo 'You chose to say "'.$lang[$userLang][$_POST['word']].'".';
// compare the word to what is in the db
if ( $_POST['word'] === $dbRow['word'] ) {
// expression matches!
// assume a column in the db "language" describes the language the user chose, e.g. 'en', 'de', or 'es'
echo 'You previously chose "'.$lang[$dbRow['language']][$dbRow['word']].'" in the language "'.$dbRow['language'].'".;
}
Depending on how you want to organize it, you may favor grouping by phrase instead of grouping by language, i.e.:
$lang[0]['en'] = 'Hello';
$lang[0]['de'] = 'Hallo';
$lang[0]['es'] = 'Hola';

Replacement variable inside of the replacing variable

I have a function, that check user language and write it down in a variable. After a time, i come of idea to merge they, so that i need a call the function anytime before the first use of a variable, so i put a call of function inside of var, with a idea, that i would be replace it self. But it does not working, becouse it trying to give me a "Closure Object" back, i think it is a function in clear and not the result :( Here is the important part of code:
$GLOBALS['user_language'] = function()
{
return get_user_language();
}
function get_user_language()
{
$user_language = 'en';
$GLOBALS['user_language'] = $user_language;
return $user_language;
}
//somewhere in the script
print_r($GLOBALS['user_language']);
I wish to get 'en' out, nothing more.
function get_user_language()
{
$user_language = 'en';
$GLOBALS['user_language'] = $user_language;
return $user_language;
}
$GLOBALS['user_language'] = get_user_language();
//somewhere in the script
print_r($GLOBALS['user_language']);
But this is strange because you set it already in get_user_language() then you pull it again. It would almost create a loop. The proper way would probably be to remove the $GLOBALS['user_language'] = $user_language; from the function.
Hope this answers your question.
Just use print_r(get_user_language()) instead of print_r($GLOBALS['user_language']);.
If getting the user's language multiple times would be particularly slow (e.g. a database query would be executed over and over again), you can do something like this:
function get_user_language()
{
static $user_language = null;
if ($user_language === null) {
$user_language = 'en'; // this would be where you make the DB query
}
return $user_language;
}
In practice, in a large PHP application, this code would generally be located in a class and would store the value as an object property, so that, for example, the application can cache DB query results for multiple users rather than for only the current one.

MySQL/PHP/JS Dynamically Populated Drop Down Menu

I'm working on a DB/web based frontend, and have encountered an issue. First off, I have a form with a drop down menu containing a list of contracts. Upon selection of a contract, I'd like for the jobs associated with that contract (fetched from the MySQL DB) to populate a second drop down menu below the first.
I would have just had all the info in one menu, but an 8000 entry drop down menu is a little unwieldy.
My PHP and HTML are barely passable, but enough for my purposes, however my ECMA experience is limited to a little bit of ActionScript in Flash MX, many moons ago.
I'd like to avoid using third party JS libraries (such as jQuery) if at all possible, and I don't mind writing more code. I just need to know whether this is doable, and a little shove in the right direction.
I'll shut up now, heres the form to fetch the contract ID (and the associated client), and the incomplete job menu.
<select name='idcontract' onchange=''>
<!--fetch/display contracts/clients-->
<?php
include 'sqldb.php';
$cntqres = mysqli_query($dbc, 'SELECT * FROM contract');
while ($cntrow = mysqli_fetch_array($cntqres))
{
$cliqres = mysqli_query($dbc, "SELECT * FROM client WHERE idclient = '$cntrow[idclient]'");
while ($clirow = mysqli_fetch_array($cliqres))
{
echo "<option value='$cntrow[idcontract]'>$cntrow[idcontract] $clirow[name]</option>";
}
}
?>
</select>
<select name='idjob'>
<option value='NULL'>Please select a contract</option>
<!--here goes the magical piece of code I don't know how to write-->
</select>
Any help would be much appreciated.
Edit:
Here's the PHP called by FeatherAJAX:
<?php
include 'sqldb.php';
$cnt = mysqli_real_escape_string($dbc, $_GET['cnt']);
$sql = "SELECT * FROM job WHERE idcontract='$cnt' ORDER BY job.idjob";
$jqres = mysqli_query($dbc, $sql);
$i = 1;
while (($jrow = mysqli_fetch_array($jqres)) && ($i < count($jrow)))
{
echo "idjob=><option value='$jrow[idjob]' id='$jrow[idjob]'>Job-$i $jrow[part_desc]</option>";
$i++;
}
?>
First off, you may want to rewrite the chunk of code that produces the contract options. Looping through query results and performing another query for each record is inefficient. Based on your queries, you might be able to use this code, which does a single query and then generate the options based on that. (I had to use made-up column names in the ORDER clause. In general, you should always sort your recordset so that results are in a determinate order -- even if you don't care what that order is.
<select name="idcontract" id="idcontract">
<!--fetch/display contracts/clients-->
<?php
include 'sqldb.php';
$clients = mysqli_query($dbc, '
SELECT ct.idcontract, ct.idclient, cl.name
FROM contract ct LEFT OUTER JOIN client cl ON ct.idclient = cl.idclient
ORDER BY ct.contractname, cl.clientname
');
while ($client = mysqli_fetch_array($clients)) {
echo "<option value=\"{$client[idcontract]}\">{$client[idcontract} {$client[name]}</option>";
}
?>
</select>
<select name="idjob" id="idjob">
<option value="NULL">Please select a contract</option>
</select>
To your question, the code you're looking for actually doesn't go where that comment is. What you need is an event handler that responds to the user picking an option in the first SELECT; it should then grab the value of that option and request from the server a set of key-value pairs to stuff into the second SELECT.
Something like this:
document.getElementById('idcontract').onchange = function(event) {
// grab currently selected value
var sValue = null;
for(var i = 0, imax = this.childNodes.length; i < imax; i++) {
var eOption = this.childNodes[i]; // shorthand
if(eOption.selected) {
sValue = eOption.value;
break;
}
}
if(!sValue) return;
// get the sub-options for this value
getSubOptions(sValue, function(XHR) {
// this code runs once the response comes back from the server
var aPairs = [];
var nlJobs = XHR.getElementsByTagName('jobs'); // assumptions #1 & #2: response is XML, includes <job> tag for each job
// extract key-value pairs from XML
for(var i = 0, imax = nlJobs.length; i < imax; i++) {
var xJob = nlJobs[i]; // shorthand
/*
assumption #3: <job> tag has "id" property
assumption #4: job name appears inside <job> tag
assumption #4.5: you've got an abstraction layer that normalizes XML node interfaces so that "text" and "textContent" are folded into "textContent"
*/
aPairs.push({ 'key': xJob.getAttribute('id'), 'value': xJob.textContent });
}
// given array of key-value pairs, rebuild select box
var eJobs = document.getElementById('idjob');
setOptions(eJobs, aPairs);
});
}
function setOptions(eNode, aPairs) {
if(!eNode || !eNode.nodeName || eNode.nodeName.toUpperCase() !== 'SELECT') return false;
// empty SELECT of all options
while(eNode.firstChild) {
eNode.removeChild(eNode.firstChild);
}
// build up new nodes
var eOpt = null;
for(var i = 0, imax = aPairs.length; i < imax; i++) {
eOpt = document.createElement('OPTION');
eOpt.value = aPairs[i].key;
eOpt.appendChild(document.createTextNode(aPairs[i].value));
eNode.appendChild(eOpt);
}
return true;
}
Of course, this is missing an important piece: you need some kind of AJAX abstraction layer. You don't need to get that from a framework, and a good library for this can be less than 50 lines of code (e.g. see PPK's ajax script on quirksmode.org), but you absolutely need something. That layer will provide two benefits: (1) cross-browser compatibility; (2) syntactic sugar.
For example, the code above doesn't include the definition of getSubOptions. That's because the logic will vary based on the interface provided by your AJAX abstraction. The idea, though, is that you'll perform a GET request against a script you write that accepts arguments and returns data satisfying that request. In the code above, I pretended that the script you write will return properly-formed XML data, with a MIME type identifying it as such. Alternatively, you could use JSON (or JSONP), straight text (e.g. CSV-style data), or even raw HTML that you'll just insert into the page.
The benefit of using a full framework is that they all provide convenient ways of doing DOM manipulation (i.e. syntactic sugar again).
The bottom line: you can absolutely do this with a homegrown approach (and I'm proud to say I've done it myself). But it will take longer -- not just because it's less convenient, but also because you'll have to re-invent the wheel === finding and fixing bugs in your code instead of leveraging well-tested core components from some library.
EDIT: If you want to use JSON as a data interchange format instead of XML, you'd modify the response handler being passed to getSubOptions like so:
getSubOptions(sValue, function(XHR) {
// this code runs once the response comes back from the server
var aPairs = eval(XHR.responseText); // assumes JSON defines an array of key-value pairs
// given array of key-value pairs, rebuild select box
var eJobs = document.getElementById('idjob');
setOptions(eJobs, aPairs);
});
And here's a sample of what that JSON might look like:
[ { key: '1234', value: 'Job #1' },
{ key: '2345', value: 'Job #2' },
...
];
In this example, the JSON structure conveniently mirrors the property names expected by setOptions; that said, key and value seem pretty inoffensive.
If you're set on using JSON for data, you may want to look into JSONP as a more secure alternative. It's real similar, but the design pattern is a little different from the anonymous callback technique above.
EDIT 2: Modified sample code for the responder:
<?php
include 'sqldb.php';
$cnt = mysqli_real_escape_string($dbc, $_GET['cnt']);
$sql = "SELECT * FROM job WHERE idcontract='$cnt' ORDER BY job.idjob";
$jqres = mysqli_query($dbc, $sql);
$i = 1;
// prepare the response
header('Content-Type: text/html');
while (($jrow = mysqli_fetch_array($jqres)) && ($i < count($jrow))) {
echo "<option value=\"$jrow[idjob]\" id=\"$jrow[idjob]\">Job-$i ${htmlentities(jrow[part_desc])}</option>";
$i++;
}
?>

Suggestive Search From JS Array, Possible?

Ok so what i want to be able to do is to perform a suggestive style search using the contents of an array instead of a doing a mySQL database query on every keyup.
So imagine a javascript object or array that is full of people's names:
var array = (jack,tom,john,sarah,barry,...etc);
I want to then query the contents of this array based on what the user has typed into the input box so far. So if they have typed 'j',both jack and john will be pulled out of the array.
I know this is possible via php mysql and ajax calls, but for reason of optimization I would like to be able to query the js array instead.
Hope someone can help me with this!
W.
as the name suggests, this finds elements of an array starting with the given string s.
Array.prototype.findElementsStartingWith = function(s) {
var r = [];
for(var i = 0; i < this.length; i++)
if(this[i].toString().indexOf(s) === 0)
r.push(this[i]);
return r;
}
// example
a = ["foo", "bar", "fooba", "quu", "foooba"];
console.log(a.findElementsStartingWith("fo"))
the rest is basically the same as in ajax-based scripts.
http://wwwo.google.com?q=autosuggest+using+javascript
AJAX calls fetch the contents from another serverside script files. You already have your data in the JS. Read a AJAX tutorial doing this. Then, just remove the parts where AJAX calls are made and replace it with your array's contents, and you're good to go.
I ended up using the following function to build my AJAX free instant search bar:
Example JS object being searched:
var $members = {
"123":{firstname:"wilson", lastname:"page", email:"wilpage#blueyonder.co.uk"},
"124":{firstname:"jamie", lastname:"wright", email:"jamie#blueyonder.co.uk"}
}
Example of function to search JS object:
$membersTab.find('.searchWrap input').keyup(function(){
var $term = $(this).val(),
$faces = $membersTab.find('.member'),
$matches = [];
if($term.length > 0){
$faces.hide();
$.each($members,function(uID,details){
$.each(details,function(detail,value){
if(value.indexOf($term) === 0){//if string matches term and starts at the first character
$faces.filter('[uID='+uID+']').show();
}
});
});
}else{
$faces.show();
}
});
It shows and hides users in a list if they partially match the entered search term.
Hope this helps someone out as I was clueless as to how to do this at first!
W.

Categories