But for completeness and since I left it dangling there
Still very nice example of using bitwise operators. Useful in other cases, too, like PHP error reporting.
But for completeness and since I left it dangling there
Still very nice example of using bitwise operators. Useful in other cases, too, like PHP error reporting.
Can you put this debugging code into Update.php on the very beginning:
<?php
die(print_r($_POST, 1));
?>
This will print the contents of the $_POST array and stop the script. Please post the output.
It's still going to the wrong page
What page does it go to? It should go to the Update.php.
OK, we are getting there. This could be due to stray single quote in the query:
WHERE id = {$customer_id'}";
Either remove it or change it to:
WHERE id = '{$customer_id}'";
I am guessing but I think customer ID should be in the value of hidden input on line 34. This is the current code:
<input type="hidden" name="customer_id" class="customer_id" value="">
Shouldn't it be:
<input type="hidden" name="customer_id" class="customer_id" value="<?php echo $customer['customer_id']; ?>">
OK, I see. TThe problem is that the ID is not comming to the update.php page from previous page. Can you post that page code too?
Well, the trouble is there is no id
in your query. This is why this code:
if(!isset($_POST['id']) || !is_numeric($_POST['id'])) {
// handle the error here
...
}
Redirecting to logout was just my guess. The thing is if there is no value in $_POST['id'] then you have to do something about it (warn the user, provide a default value...).
Why is there no $_POST['id'] is another question. How does the user pprovide the ID? If it is a form then the method of the form has to be post. If it is a link, it is usually get, but if updating, try to use post. Can you show the code for update.php?
The method in the form is POST while you are reading $_GET. Change it to $_POST.
$customer_id = $_POST['id'];
And for security reasons validate and/or escape it.
if(!isset($_POST['id']) || !is_numeric($_POST['id'])) {
header('location:logout.php');
}
$customer_id = mysql_real_escape_string($_POST['id']);
This won't work since you use links for your pagination which refresh the whole page which in turn defeats the purpose of ajax. If you want to keep the ajax approach then you have to do the pagination with ajax too (not using querystrings and $_GET) but this might be more complicated. If you want to use traditional non-ajax approach you will have to drop the ajax functionality just implemented.
And what is the difference and which approach to choose? When using non-ajax approach the page will refresh on each click on any link while with ajax approach only the contents of div will refresh. But ajax is meant to be used when you want to refresh a small portion f your page (i.e. the shopping basket contents) and you do not want to refresh the whole page. In your case the most of page will get refreshed anyway so it is maybe better to use non-ajax approach which is less complicated and easier to mantain.
If you want to stick with ajax approach I am happy to help but have never done this way of pagination through ajax calls so I am not sure how difficult it is. It might take some time. If you decide to do it non-ajax way than again I do not have much experience with coding pagination since I always used library for taht (PEAR Pager is a package that does this job nicely.
The ready handler will not change the functionality at all it will just make sure the functionality is loaded once the DOM is ready which in most cases takes just a fraction of second. And it affects only the page with jquery script not the ajax processing script (getProductData.php). In other words: you do not have to use the ready handler at this stage.
Pagination will work. In the getProductData.php page you have to prepare the html code for pagination and send it back into product-data div.
You are welcome, mate. Just to suggest an minor improvement: if the page grows and has more elments that might take some time to load, or if you change the triggers for ajax you might want to enclose the whole javascript/jquery code in $(document).ready handler which will ensure that functionality is available after the DOM is ready:
<script>
$(document).ready(function() {
$('a.category').click(function(e) {
...
});
</script>
But that might not be absolutely neccessary in all cases.
You can do it using case statement:
if(!isset($_SESSION['access_level']) || $_SESSION['access_level'] < 180) {
header('location: logout.php');
} else {
switch($_SESSION['access_level']) {
case 220 : header('location:restricted_page1.php'); break;
case 200 : header('location:restricted_page2.php'); break;
case 180 : header('location:restricted_page1.php'); break;
default : header('location:logout.php');
}
}
I haven't noticed your question to me about access levels in one of your previous posts. Have you got those answers yet?
Have you copied the above javascript code exactly as I posted it? Does it contain the line
e.preventDefault();
Your links should not go anywhere when you click on them (the above code prevents that) since you choose to use ajax. In this case links are there just to get people click on them but you allways stay on the same page, only the contents of the div changes.
This is when ajax comes in. Links will have a class, I'll name it category
. jquery will catch clicks on all links having that class and sending a request to the php file that will retrieve the data and return it formated as html.
This is the file with links (the whole lot, containing the jquery bit):
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
</head>
<body>
<!-- href attributes are the values of categories -->
<a href="1" class="category">Category 1</a>
<a href="2" class="category">Category 2</a>
<a href="3" class="category">Category 3</a>
<a href="4" class="category">Category 4</a>
<a href="5" class="category">Category 5</a>
<a href="100" class="category">Category 100</a>
<!-- This div will display the product data -->
<div id="product-data">
</div>
<?php
?>
<script>
// whenever a link with category class is clicked
$('a.category').click(function(e) {
// first stop the link to go anywhere
e.preventDefault();
// you can get the text of the link by converting the clicked object to string
// you something like 'http://mysite/categories/1'
// there might be other methods to read the link value
var linkText = new String(this);
// the value after the last / is the category ID
var categoryValue = linkText.substring(linkText.lastIndexOf('/') + 1);
// send the category ID to the getProductData.php script using jquery ajax post method
// send along a category ID
// on success insert the returned text into the product-data div
$.post('getProductData.php', {category: categoryValue}, function(data) {
$('#product-data').html(data);
});
});
</script>
</body>
</html>
And this is the script that reads data and echoes it back:
<?php
// if no …
if the user's access_level is below than 180 it will directly go to the logout page right?
Yes. It also redirects you to logout if the session variable does not exist.
i tried that way, but even the access level is higher that 180, it still directly go to logout page.
Can you show the code. Have you started the session? Does the $_SESSION['access_level']
exist at all?
Please post the code you have so far (the page with links) and structure of the table(s).
You might be better off declaring the method this way:
public function load_Array($data)
{
$this->anArray = array();
foreach($data as $element) {
$this->anArr[] = $element;
}
...
Now you can pass an array as argument (as cereal suggested):
$andy->load_Array(array("andy","bill"));
POST[customer]
is incorrect while POST['customer']
is correct in php code.
Another variation is to use Ajax. The difference form Atli's approach is that the page does not get refreshed each time you click a link, only the content in the div changes. Te easiest way to do it is to use jQuery and it's ajax methods.
http://api.jquery.com/jQuery.ajax/
http://www.w3schools.com/jquery/jquery_ref_ajax.asp
With the chosen ajax method you call your php script that retrieves the contents from the DB and returns HTML code for displaying in the div.
Yes, it basicaly exits teh function if there are less than 3 chars in the search_term. Haven't tested it, though, but I am pretty sure return statement works like exit in php. Other way of doing it would be wrapping the whole ajax bit in if(search_term.length >= 3)
.
$(document).ready(function() {
$('.autosuggest').keyup(function () {
var search_term = $(this).attr('value');
if(search_term.length >= 3) {
// read the values of the select elements (drop downs)
// read the value of category
var category=$('#category').attr('value');
// this is the conditions you will post over to the searchApp.php script
// assembled here for clarity
var conditions = {
'search_term' : search_term,
'category' : category
};
// alert(conditions.toSource());
// post the conditions over to the searchApp.php script
$.post('ajax/searchApp.php', conditions, function(data) {
//alert(data);
$('.result').html(data);
/*
// you can sort this out yourself
$('.result li').click(function() {
var result_value=$(this).text();
$('.autosuggest').attr('value',result_value);
//alert(result_value);
$('.result').html('');
});
*/
});
});
});
}
And also I made a small mistake in the html code, sory. I put the result unnumbered list (ul) at the end of the page. I later realized that it should be in the place where you put it originally, just after the input box, since it is the basis for extending the input box into combo box. So please move it back there.
<input type="text" name="tag" value="" placeholder="All" class="autosuggest" />
<div class="dropdown">
<ul class="result">
</ul>
...
for the 3 characters that have to be typed in so the jquery to launch and resource for that ?
All you have to do is check in the javascript code whether the search_term is at least 3 chars long. If not, you do not do an ajax call at all.
$(document).ready(function() {
$('.autosuggest').keyup(function () {
var search_term = $(this).attr('value');
// if we have less than 3 chars just exit the function
if(search_term.length < 3) {
return;
}
...
mysql_fetch_array function returns result in both associative and numeric arrays while
mysql_fetch_assoc function returns result only in an associative array.
It is the matter of what you want when choosing among them.
And finaly the html page with the form. I have ammended a few things here, too. First I put the javascript directly in the html but you can keep it separate in Primary.js file, if you wish. The most important thing is that you add an ID to all of the select elements (drop downs) you want to use in the query. I have done so for the category. This way jacascript (jquery) can read the selected values and send them over to searchApp.php.
The div block that displays the results (id= result) should be placed outside the form just for sematic reasons, but should work inside too, I guess.
And there is a span tag towards the end that is in wrong place. I suggest you put it somewhere else.
There are some other small errors in the html. Open the html in a good editor, you will get the errors highlighted.
And here is my version of the code (with the javascript included directly):
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form action="searchAppliance.php" method="post" name="search1" onsubmit='return validateForm()'>
<table width="685" border="0">
<tr>
<td width="238" height="23" valign="top">
<font size="-2">Search</font><font size="-1"><strong> APPLIANCES </strong></font>
</td>
<td width="443" valign="top">
<input type="submit" value="Find" id="findbuton">
</td>
</tr>
</table>
<div id="dropdown">
<table width="621" border="0" align="center">
<tr><td width="100">
<span>Category</span><br />
<!-- give category dropdown an ID so you can read it's value with jQuery -->
<select name="category" id="category"
style="width: ; background-color: #FFF; font-weight: bold; font-size: 12px; width: 120px;">
<!-- onchange="setup(document.search1.category.value)"> -->
<option value="all" selected="selected">All</option>
<option value="cleaning">Cleaning</option>
<option value="cooling">Cooling</option> …
Now the searchApp.php. You first have to check if all the conditions, passed over by ajax call, exist. Then you escape the values, to be safe. Next you construct the query without any conditions. Then you check if any of conditions exist and add WHERE and AND statements. In this case we have only one possible condition: the category. You can do a bit of error checking too, I have left it out for clarity. See the comments in the code.
<?php
// the database connection has to be setup here (the link has to exist)!
require_once '../connect.php';
// check if all the conditions exist
// (for now check only for search_term and category, later add other drop downs)
if(
isset($_POST['search_term']) &&
!empty($_POST['search_term']) &&
isset($_POST['category'])
) {
$search_term = mysql_real_escape_string($_POST['search_term']);
$category = mysql_real_escape_string($_POST['category']);
// construct the query for all categories first
$query = "SELECT Type FROM autosuggest WHERE Type LIKE '$search_term%'";
// then if category is other than all add the condition
if($category != 'all') {
$query .= " AND Category LIKE '$category'";
}
// die($query);
$resource = mysql_query($query);
while(($row=mysql_fetch_assoc($resource))) {
echo '<li><b>',$row['Type'],'</b></li>';
}
}
?>
OK, I had a quick look and fortunately spotted the errors soon enough to reply tonight. I will reply in several posts since it is going to be a lot of code
The script in the Primary.js should post over to the searchApp.php also the category (and other dropdown values) not just the value of the input box. You need category to filter the data from DB in the query. I named the variable with data conditions in the code below (also see the comments in the code).
$(document).ready(function() {
$('.autosuggest').keyup(function () {
var search_term = $(this).attr('value');
// read the values of the select elements (drop downs)
// read the value of category
var category=$('#category').attr('value');
// this is the conditions you will post over to the searchApp.php script
// assembled here for clarity
var conditions = {
'search_term' : search_term,
'category' : category
};
// just for debugging
// alert(conditions.toSource());
// post the conditions over to the searchApp.php script
$.post('ajax/searchApp.php', conditions, function(data) {
//alert(data);
$('.result').html(data);
/*
// you can sort this out yourself
$('.result li').click(function() {
var result_value=$(this).text();
$('.autosuggest').attr('value',result_value);
$('.result').html('');
});
*/
});
});
});
This script works fine and sends object with conditions to searchApp.php, which I will explain in next post.
P.S. You can enhance this code so that ajax post will get launched only after say 3 characters have been typed in. This is how many autosuggesters work, they do not fire on the first character due to a possibility of large result sets returned.
Just sent you a PM. Otherwise just click on my name (broj1). You will see my profile. Click on contact me button.
Can you send me all your scripts in question, database structure and data on PM. You can send me the table structure and data as an SQL statement (go to phpmyadmin and export the table in sql format).
Tis is how I did it and it proved to be a good concept. I have defined access levels which were integers. The higher the level (value) the higher the privileges.
Between each level I had a space for new levels if I need them later. The access level is saved in the user database for each user.
access_level | description
--------------------------
220 | application admin (developes only)
200 | contents admin
180 | system admin
100 | regular user (edit, view)
60 | viewer (view)
0 | no access
As you can see I use unsigned integer for access level so it does not take much space in db. I have plenty of room below and above the range and also between access levels which proved good tactics since I had to add levels already. The access level gets stored in the session during login so all I have to do is to compare it with required level on the beginning of each page:
// example for checking a system admin's access level
if(!isset($_SESSION['access_level']) || $_SESSION['access_level'] < 180) {
header('location: logout.php');
}
In the above example only system admin and higher levels can access the page.
I also define constants to make the code more readable:
define('ACCESS_LVL_APPADMIN', 220);
define('ACCESS_LVL_CONTADMIN', 200);
define('ACCESS_LVL_SYSADMIN', 180);
define('ACCESS_LVL_REGUSER', 100);
define('ACCESS_LVL_VIEWER', 60);
define('ACCESS_LVL_NOACCESS', 0);
// example for checking a system admin's access level
if(!isset($_SESSION['access_level']) ||
$_SESSION['access_level'] < ACCESS_LVL_SYSADMIN) {
header('location: logout.php');
}
In line 4 in above snippet you misspelled category (you left out letter g):
$("#cateory").change(function(){
If I understand the thing after revising your code you wish to have a functionality that will display suggestions upon typing in an input box and based on selection in dropdowns. This is quite a complex task which involves ajax calls fired on each keypress while you are in the input box. jquery has functionalities ready for that but still you have to do customization since you have additional selections.
The javascript logic is not in the posted code and I guess it is in the primaryapp.js, which is included with script tags. But this case is quite hard to debug since all the javascript should be posted, the db tables should be posted (structure and contents) and the php and html scripts should be examined. I can not promise you that I can do that quickly.
Meanwhile see here for nice tutorials how to do the autosuggest feature.
I hope someone with experience with this will be also able to contribute.
Check the query. Insert this code right after line 5:
die($sql);
It is a simple debugging technique. It will display the query and you can inspect it and test it in phpmyadmin. You can also post it here.
OK, so the category is not comming through. Can you post the code for the form (to check the select).
But category is obviously not in the $_POST. Can you put this line in the very beginning of the script and post the result:
die(print_r($_POST, 1));
This will print the contents of the $_POST array and stop the script.
Yo check for search term before issuing the query but you do not check for Category. Is this OK? Is category not mandatory to have a value?
if(isset($_POST['search_term'])==true && empty($_POST['search_term'])==false)
As you can see there is no value for the Category in the query. Is this OK?
There is a backtick just before the AND that should not be there. Remove it (and comment out the die statement) then try it out.
Looks like there is still an error in the query. Can you add this line of code just after line 6:
die("SELECT `Category`, `Type` FROM `autosuggest` WHERE `Category`='{$_POST[category]}'` AND `Type` LIKE '$search_term%'");
As you see it will display the constructed query. Can you please post it here.
You can also copy the displayed query and test it in phpmyadmin.
What is the error? Can you please post the newest version of the code?
Did you maybe forget to declare the ID colums Autoincrement? That way you can leave the id values out and db will autogenerate them.
Edit: sory pritaeas, posted just seconds after you did :-)
The $query variable does not contain a valid resource since there is an error in the query. You can not perform a concatenation within a double quoted string. Correct the query this way: remove the .
and enclose the array element $_POST[category]
in curly braces). I also changed &&
to AND
since I am not sure whether &&
is valid in mysql. Also a backtick was missing after the Category
.
$query=mysql_query("SELECT `Category`, `Type` FROM `autosuggest` WHERE `Category`='{$_POST[category]}'` AND `Type` LIKE '$search_term%'");
The name of the $query variable is missleading since it contains a resource not a query. I would change it to $resource.
$resource=mysql_query("SELECT `Category`, `Type` FROM `autosuggest` WHERE `Category`='{$_POST[category]}'` AND `Type` LIKE '$search_term%'");
while($row=mysql_fetch_assoc($resource))
{
echo '<li><b>',$row['Type'],'</b></li>';
}
And as bradly.spicer said switch to newer mysqli instead of older mysql, when possible.
One more thing: if password is incorrect, do not tell that to the user; if username is incorrect, do not tell that to the user. Allways tell them that login failed, but not the reason. This way you give no clue to potential attacker.
Escaping values using mysql_real_escape_string or similar (i.e. mysqli_real_escape_string) function greatly minimizes a possibility of sql injection by escaping dangerous characters. Some other things you have to do are (not a comprehensive list):
Also use newer mysqli extension instead of old mysql which might soon get deprecated.
More on this topic is here and here.
And more on login security.
As long as this is not a higly confidential banking or government site this might be enough. Hopefully you have done the password hashing as per good practices. You might want to check this link.
Other aspect of security is input data validation/sanitization (username and password) to prevent sql injections.
I am not sure whether I understood your question correctly but here we go: Setting an action attribute to another page is not a bad practice and I do not think it causes a lot of workload for the server. But you can have the action attribute set to the same page if you wish. In that case you have to check if the form was submitted on the beginning of the page. If yes, then you have to act appropriately (delete the record, redirect or display a message or whatever). But in your current case You have to check whether the query is OK so I suggest you do a little debugging. Change the deleteuserform.php page sligtly like this:
<?php
// this line is only for debugging, you will remove it later
die("Delete FROM Customers WHERE id = {$data['id']}");
mysql_query("Delete FROM Customers WHERE id = {$data['id']}");
?>
Now when you select an option from the drop down you will be redirected to the second page but the query will only get displayed and not executed. You can examine it and copy it to phpmyadmin and test it there.
I also suggest you state the form method explicitly to POST which is more appropriate for deleting.
<form action="deleteuserform.php" method="post">
Echoing should work in most cases if you put echo in correct place which can be sometimes tricky. Take in account included files and functions, ajax calls etc. And have all error reporting enabled while you are debugging.
There is also a comprehensive debug tool called xdebug. I have never used it but have seen some demos and it seems that might be what you are after. But I think it requires a little bit of learnig to start using it.
Maybe a word or two also on a poor man's debugging technique. When you quickly want to examine values of variables you just insert an echo
or die
statement after the point in code that interests you. When examining simple values (strings, integer, floats...) just use echo
(or die
if you also want to stop the execution). If you want to examine arrays or objects then you add a little bit of formatting and use print_r
function (with second parameter set to 1 to use the output in echo):
$myArray = array('key1' => 'value1', 'key2' => 'value12);
echo '<pre>' . print_r($myArray, 1) . '</pre>';
You can also send output into html code only in a form of a html comment:
echo '<!-- ' . print_r($myVar, 1) . ' -->';
This way the debug output won't interfere with displayed page, it will be included in source code of the page only (in Firefox then you just right click and select View page source).
Sorry, my mistake in the post before your last question. If we want to use $style variable in the printf statement, the parameter should be enclosed in double quotes (and normal double quotes escaped):
printf("<tr><td align=\"center\" style=\"$style\">%s</td><td align=\"center\" style=\"$style\">%s</td></tr>", $fullname, $myrow['TotalPoints']);
One more edit: if the table borders are not collapsed it is better to aplly styles to <tr> tag as szabisz suggested:
printf("<tr style=\"$style\"><td align=\"center\">%s</td><td align=\"center\">%s</td></tr>", $fullname, $myrow['TotalPoints']);