PHP, admins usersystem - php

I was wondering if you think this is possible:
Ok so I have a database storing usernames and I would like to echo the admins which are inside a file called admins.php IF they match the usernames inside the database so far I have got:
admins.php;
$admins = array("username","username2","username3");
and
$users="SELECT username from usrsys";
$query_users=mysql_query($users);
while loop here.
The while loop should hopefully echo the users which matches the admins.php file. I assume I should use something like (inarray()), but I am really not sure.

You should definitely use IN clause in your SQL to do this. Selecting everything from the table in order to determine in PHP if it contains the user names you're looking for makes no sense and is very wasteful. Can you imagine what would happen if you had a table of 1 million users and you needed to see if two of them were on that list? You would be asking your DBMS to return 1 million rows to PHP so that you can search through each of those names and then determine whether or not any of them are the ones you're looking for. You're asking your DBMS to do a lot of work (send over all the rows in the table), and you're also asking PHP to do a lot of work (store all those rows in memory and compute a match), unnecessarily.
There is a much more efficient and faster solution depending on what you want.
First, if you only need to know that all of those users exist in the table then use SELECT COUNT(username) instead and your database will return a single row with a value for how many rows were found in the table. That way you have an all or nothing approach (if that's what you're looking for). Either there were 3 rows found in the table and 3 elements in the array or there weren't. This also utilizes your table indexes (which you should have properly indexed) and means faster results.
$admins = array("username","username2","username3");
// Make sure you properly escape your data before you put in your SQL
$list = array_map('mysql_real_escape_string', $admins);
// You're going to need to quote the strings as well before they work in your SQL
foreach ($list as $k => $v) $list[$k] = "'$v'";
$list = implode(',', $list);
$users = "SELECT COUNT(username) FROM usrsys WHERE username IN($list)";
$query_users = mysql_query($users);
if (!$query_users) {
echo "Huston we have a problem! " . mysql_error(); // Basic error handling (DEBUG ONLY)
exit;
}
if (false === $result = mysql_fetch_row($query_users)) {
echo "Huston we have a problme! " . mysql_error(); // Basic error handling (DEBUG ONLY)
}
if ($result[0] == count($admins)) {
echo "All admins found! We have {$result[0]} admins in the table... Mission complete. Returning to base, over...";
}
If you actually do want all the data then remove the COUNT from the SQL and you will simply get all the rows for those users (if any are found).
$admins = array("username","username2","username3");
// Make sure you properly escape your data before you put in your SQL
$list = array_map('mysql_real_escape_string', $admins);
// You're going to need to quote the strings as well before they work in your SQL
foreach ($list as $k => $v) $list[$k] = "'$v'";
$list = implode(',', $list);
$users = "SELECT username FROM usrsys WHERE username IN($list)";
$query_users = mysql_query($users);
if (!$query_users) {
echo "Huston we have a problem! " . mysql_error(); // Basic error handling (DEBUG ONLY)
exit;
}
// Loop over the result set
while ($result = mysql_fetch_assoc($query_users)) {
echo "User name found: {$result['username']}\n";
}
However, I really urge you to reconsider using the old ext/mysql API to interface with your MySQL database in PHP since it is deprecated and has been discouraged from use for quite some time. I would really urge you to start using the new alternative APIs such as PDO or MySQLi and see the guide in the manual for help with choosing an API.
In PDO, for example this process would be quite simple with prepared statements and parameterized queries as you don't have to worry about all this escaping.
There's an example in the PDOStatement::Execute page (Example #5) that shows you just how to do use the IN clause that way with prepared statements... You can then reuse this statement in other places in your code and it offers a performance benefit as well as making it harder for you to inadvertently expose yourself to SQL injection vulnerabilities.
// Connect to your database
$pdo = new PDO("mysql:dbname=mydb;host=127.0.0.1", $username, $password);
// List of admins we want to find in the table
$admins = array("username","username2","username3");
// Create the place holders for your paratmers
$place_holders = implode(',', array_fill(0, count($admins), '?'));
// Create the prepared statement
$sth = $dbh->prepare("SELECT username FROM usrsys WHERE username IN ($place_holders)");
// Execute the statement
$sth->execute($admins);
// Iterate over the result set
foreach ($sth->fetchAll(PDO::FETCH_ASSOC) as $row) {
echo "We found the user name: {$row['username']}!\n";
}
Your PHP code even looks so much better with PDO :)

Just include admins.php file and use the next construction in your loop:
while ($row = mysql_fetch_array($users)) {
if (in_array($users[0], $admins))
echo $users[0];
}

Try this:
<?php
# include admins.php file that holds the admins array
include "admins.php";
# join all values in the admins array using "," as a separator (to use them in the sql statement)
$admins = join(",", $admins);
# execute the query
$result = mysql_query("
SELECT username
FROM usrsys
WHERE username IN ($admins)
");
if ($result) {
while ($row = mysql_fetch_array($result)) {
echo $row["username"] . "<br>";
}
}
?>

If your looking for syntax to pull in only the users from your $admins array then you could use something like:
$users="SELECT username FROM usrsys WHERE username IN ('".join("','",$admins)."')";
Where the php function JOIN will print username,username2,username3. Your resulting MySQL statement will look like:
SELECT username FROM usrsys WHERE username IN ('username','username2','username3')
Alternatively, if your looking to iterate through your $query_vars array and separate your admins from non-admins then you could use something like:
<?php
while($row = mysql_fetch_assoc($query_users)){
if(in_array($row['username'],$admins)){
//do admin stuff here
}else{
//do NON-admin stuff here
}
}?>

Related

Query for multiple SQLite tables with PHP

Forgive me if my question sounds stupid as I'm a begginer with SQLite, but I'm looking for the simplest SQLite query PHP solution that will give me full text results from at least three separate SQLite databases.
Google seems to give me links to articles without examples and I have to start from somewhere.
I have three databases:
domains.db (url_table, title_table, date_added_table)
extras.db (same tables as the first db)
admin.db (url_table, admin_notes_table)
Now I need a PHP query script that will execute a query and give me results from domains.db but if there are matches also from extras.db and admin.db.
I'm trying to just grasp the basics of it and looking for a starting point where I can at least study and learn the first code.
First, you connect to 'domains.db', query what you need, save however you want, than if there were a result in the first query, you connect to the others and query them.
$db1 = new SQLite3('domains.db');
$results1 = $db1->query('SELECT bar FROM foo');
if ($results1->numColumns() && $results1->columnType(0) != SQLITE3_NULL) {
// have rows
// so, again, $result2 = $db2->query('query');
// ....
} else {
// zero rows
}
// You can work with the data like this
//while ($row = $results1->fetchArray()) {
// var_dump($row);
//}
Source:
http://php.net/manual/en/sqlite3.query.php
http://php.net/manual/en/class.sqlite3result.php
Edit.: A better approach would be to use PDO, you can find a lot of tutorials and help to use it.
$db = new PDO('sqlite:mydatabase.db');
$result = $db->query('SELECT * FROM MyTable');
foreach ($result as $row) {
echo 'Example content: ' . $row['column1'];
}
You can also check the row count:
$row_count = sqlite_num_rows($result);
Source: http://blog.digitalneurosurgeon.com/?p=947

Building interactive WHERE clause for Postgresql queries from PHP

I'm using Postgresql 9.2 and PHP 5.5 on Linux. I have a database with "patient" records in it, and I'm displaying the records on a web page. That works fine, but now I need to add interactive filters so it will display only certain types of records depending on what filters the user engages, something like having 10 checkboxes from which I build an ad-hoc WHERE clause based off of that information and then rerun the query in realtime. I'm a bit unclear how to do that.
How would one approach this using PHP?
All you need to do is recieve all the data of your user's selected filters with $_POST or $_GET and then make a small function with a loop to concatenate everything the way your query needs it.
Something like this... IN THE CASE you have only ONE field in your DB to match with. It's a simple scenario and with more fields you'll need to make it so that you add the field you really need in each case, nothing too complex.
<?php
//recieve all the filters and save them in array
$keys[] = isset($_POST['filter1'])?'$_POST['filter1']':''; //this sends empty if the filter is not set.
$keys[] = isset($_POST['filter2'])?'$_POST['filter2']':'';
$keys[] = isset($_POST['filter3'])?'$_POST['filter3']':'';
//Go through the array and concatenate the string you need. Of course, you might need AND instead of OR, depending on what your needs are.
foreach ($keys as $id => $value) {
if($id > 0){
$filters.=" OR ";
}
$filters.=" your_field = '".$value."' ";
}
//at this point $filters has a string with all your
//Then make the connection and send the query. Notice how the select concatenates the $filters variable
$host = "localhost";
$user = "user";
$pass = "pass";
$db = "database";
$con = pg_connect("host=$host dbname=$db user=$user password=$pass")
or die ("Could not connect to server\n");
$query = "SELECT * FROM table WHERE ".$filters;
$rs = pg_query($con, $query) or die("Cannot execute query: $query\n");
while ($row = pg_fetch_row($rs)) {
echo "$row[0] $row[1] $row[2]\n";
//or whatever way you want to print it...
}
pg_close($con);
?>
The above code will get variables from a form that sent 3 variables (assuming all of them correspond to the SAME field in your DB, and makes a string to use as your WHERE clause.
If you have more than one field of your db to filter through, all you need to do is be careful on how you match the user input with your fields.
NOTE: I did not add it here for practical reasons... but please, please sanitize user input.. ALWAYS sanitize user input before using user controlled data in your queries.
Good luck.
Don't do string concatenation. Once you have the values just pass them to the constant query string:
$query = "
select a, b
from patient
where
($x is not null and x = $x)
or
('$y' != '' and y = '$y')
";
If the value was not informed by the user pass it as null or empty. In the above query the x = $x condition will be ignored if $x is null and the y = '$y' condition will be ignored if $y is empty.
With that said, a check box will always be either true or false. What is the exact problem you are facing?
Always sanitize the user input or use a driver to do it for you!
I have created a Where clause builder exactly for that purpose. It comes with the Pomm project but you can use it stand alone.
<?php
$where = Pomm\Query\Where::create("birthdate > ?", array($date->format('Y-m-d')))
->andWhere('gender = ?', array('M'));
$where2 = Pomm\Query\Where::createWhereIn('something_id', array(1, 15, 43, 104))
->orWhere($where);
$sql = sprintf("SELECT * FROM my_table WHERE %s", $where2);
$statement = $pdo->prepare($sql);
$statement->bind($where2->getValues());
$results = $statement->execute();
This way, your values are escaped and you can build dynamically your where clause. You will find more information in Pomm's documentation.

How to pull multiple rows from mysql with a function

How can I pull multiple rows from a database using a function?
The function I have is:
function search($subject, $table) {
$query = "SELECT {$subject} ";
$query .= "FROM {$table} ";
$content = mysql_query($query);
return $content;
}
On the page which is calling the function I have:
if (isset($_POST['search'])){
$search = $_POST['search'];
}
$content = search($subjectName, $tableName);
while ($results = mysql_fetch_assoc($content)){
$phrase = $results[$subjectName];
//if phrase exists in database
if (strpos($search,$phrase) !== false) {
echo $phrase;
//if phrase does not exist in database
} else {
echo 'fail';
}
This setup does not work, however if I put everything into the function it works:
function search($subject, $table, $where = 0, $is = 0) {
global $search;
$query = "SELECT {$subject} ";
$query .= "FROM {$table} ";
if ($where > 0) {
$query .= "WHERE {$where} = '{$is}' ";
}
$content = mysql_query($query);
while ($results = mysql_fetch_assoc($content)){
$phrase = $results[$subject];
//if phrase exists in database
if (strpos($search,$phrase) !== false) {
echo $phrase;
//if phrase does not exist in database
} else {
echo 'fail';
}
}
return $content;
}
On Page:
search('main_subject', 'main_search');
The problem is that I would like to call that function again in the if statement to have it search for another phrase. Is there an easier way to do this?
EDIT: The current setup pulls the first item in an infinite loop.
There are a number of issues that should be addressed here:
First, if you are trying to search a field for a specific partial match, you would likely want to use SQL LIKE construct.
SELECT field FROM table WHERE field LIKE '%search phrase%'
Doing this would eliminate the need for you to iterate through each row trying to do a string comparison for your search phrase, as you would only be returned the rows that match the search phrase and nothing more.
Second, using global to make data available to your function is really poor practice. You really should be passing any data needed by the function to the function as a parameter. This would include your search string and probably your database connection/object.
function search($field, $table, $search, $db) {
...
}
Third, You are doing nothing at all to prevent against SQL injection right now. You need to escape the input data or, better yet use prepared statements.
Fourth, you really should not be using the mysql_* functions. They are deprecated. Try using mysqli or PDO (and I would highly recommend going ahead and learning how to use prepared statements with either of these.) You might start with mysqli ,at it provide procedural functions similar to mysql_* so the learning curve might be less steep (though really most experienced developers would prefer the object-oriented usage).
Fifth, to your original question. If you want search for multiple phrases, there are a couple approaches you can take. You can either pass all the phrases at once like this:
SELECT field FROM table WHERE field LIKE '%search phrase%' OR field LIKE '%another search phrase%'
Or, you could just make iterative function calls to get the results you want. This really depends on whether you only want to search for the second phrase if the first is not successful (use the iterative approach) or whether you just want all possible matches in one query (use the LIKE-OR-LIKE approach).

MySQL query within foreach loop

I want to show all text messages from db where id=$e ($err is an array).
Inserted the query into the foreach loop, it works well but it does extra work (does query for every value of array).
Is there any other way to do it (i mean extract query from foreach loop)?
My code looks like this.
foreach ($err as $e)
{
$result = $db -> query("SELECT * from err_msgs WHERE id='$e'");
$row = $result -> fetch_array(MYSQLI_BOTH);
echo "<li><span>".$row[1]."</span></li>";
}
It is much more efficient to do this with implode() because it will only result in one database query.
if (!$result = $db->query("SELECT * FROM `err_msgs` WHERE `id`='".implode("' OR `id`='",$err)."'")) {
echo "Error during database query<br />\n";
// echo $db->error(); // Only uncomment this line in development environments. Don't show the error message to your users!
}
while ($row = $result->fetch_array(MYSQLI_BOTH)) {
echo "<li><span>".$row[1]."</span></li>\n";
}
Check the SQL IN clause.
Firstly, a bit of a lecture: embedding strings directly into your queries is going to cause you trouble at some point (SQL injection related trouble to be precise), try to avoid this if possible. Personally, I use the PDO PHP library which allows you to bind parameters instead of building up a string.
With regard to your question, I'm not sure I have understood. You say that it does extra work, do you mean that it returns the correct results but in an inefficient way? If so then this too can be addressed with PDO. Here's the idea.
Step 1: Prepare your statement, putting a placeholder where you currently have '$e'
Step 2: Loop through $err, in the body of the loop you will set the place holder to be the current value of $e
By doing this you not only address the SQL injection issue, you can potentially avoid the overhead of having to parse and optimise the query each time it is executed (although bear in mind that this may not be a significant overhead in your specific case).
Some actual code would look as follows:
// Assume that $dbdriver, $dbhost and $dbname have been initialised
// somewhere. For a mysql database, the value for $dbdriver should be
// "mysql".
$dsn = "$dbdriver:host=$dbhost;dbname=$dbname";
$dbh = new PDO($dsn, $dbuser, $dbpassword);
$qry = "SELECT * from err_msgs WHERE id = :e"
$sth = $dbh->prepare($qry);
foreach ($err as $e) {
$sth->bindParam(":e", $e);
$sth->execute();
$row = $sth->fetch();
// Prints out the *second* field of the record
// Note that $row is also an associative array so if we
// have a field called id, we could use $row["id"] to
// get its value
echo "<li><span>".$row[1]."</span></li>";
}
One final point, if you want to simply execute the query once, instead of executing it inside the loop, this is possible but again, may not yield any performance improvement. This could be achieved using the IN syntax. For example, if I'm interested in records with id in the set {5, 7, 21, 4, 76, 9}, I would do:
SELECT * from err_msgs WHERE id IN (5, 7, 21, 4, 76, 9)
I don't think there's a clean way to bind a list using PDO so you would use the loop to build up the string and then execute the query after the loop. Note that a query formulated in this way is unlikely to give you any noticable performance improvment but it really does depend on your specific circumstances and you'll just have to try it out.
You can do this much simpler by doing
$err_csv = implode("','",$err);
$sql = "SELECT FROM err_msgs WHERE id IN ('$err_csv')";
$result = $db -> query($sql);
while ($row = $result -> fetch_array(MYSQLI_BOTH))
{
echo "<li><span>".$row[1]."</span></li>";
}
That way you don't have to keep sending queries to the database.
Links:
http://php.net/manual/en/function.implode.php

SQL full text search with PHP and PDO

I'm trying to write a simple, full text search with PHP and PDO. I'm not quite sure what the best method is to search a DB via SQL and PDO. I found this this script, but it's old MySQL extension. I wrote this function witch should count the search matches, but the SQL is not working. The incoming search string look like this: 23+more+people
function checkSearchResult ($searchterm) {
//globals
global $lang; global $dbh_pdo; global $db_prefix;
$searchterm = trim($searchterm);
$searchterm = explode('+', $searchterm);
foreach ($searchterm as $value) {
$sql = "SELECT COUNT(*), MATCH (article_title_".$lang.", article_text_".$lang.") AGINST (':queryString') AS score FROM ".$db_prefix."_base WHERE MATCH (article_title_".$lang.", article_text_".$lang.") AGAINST ('+:queryString')";
$sth = $dbh_pdo->prepare($sql);
$sql_data = array('queryString' => $value);
$sth->execute($sql_data);
echo $sth->queryString;
$row = $sth->fetchColumn();
if ($row < 1) {
$sql = "SELECT * FROM article_title_".$lang." LIKE :queryString OR aricle_text_".$lang." LIKE :queryString";
$sth = $dbh_pdo->prepare($sql);
$sql_data = array('queryString' => $value);
$sth->execute($sql_data);
$row = $sth->fetchColumn();
}
}
//$row stays empty - no idea what is wrong
if ($row > 1) {
return true;
}
else {
return false;
}
}
When you prepare the $sql_data array, you need to prefix the parameter name with a colon:
array('queryString' => $value);
should be:
array(':queryString' => $value);
In your first SELECT, you have AGINST instead of AGAINST.
Your second SELECT appears to be missing a table name after FROM, and a WHERE clause. The LIKE parameters are also not correctly formatted. It should be something like:
sql = "SELECT * FROM ".$db_prefix."_base WHERE article_title_".$lang." LIKE '%:queryString%' OR aricle_text_".$lang." LIKE '%:queryString%'";
Update 1 >>
For both SELECT statements, you need unique identifiers for each parameter, and the LIKE wildcards should be placed in the value, not the statement. So your second statement should look like this:
sql = "SELECT * FROM ".$db_prefix."_base WHERE article_title_".$lang." LIKE :queryString OR aricle_text_".$lang." LIKE :queryString2";
Note queryString1 and queryString2, without quotes or % wildcards. You then need to update your array too:
$sql_data = array(':queryString1' => "%$value%", ':queryString2' => "%$value%");
See the Parameters section of PDOStatement->execute for details on using multiple parameters with the same value. Because of this, I tend to use question marks as placeholders, instead of named parameters. I find it simpler and neater, but it's a matter of choice. For example:
sql = "SELECT * FROM ".$db_prefix."_base WHERE article_title_".$lang." LIKE ? OR aricle_text_".$lang." LIKE ?";
$sql_data = array("%$value%", "%$value%");
<< End of Update 1
I'm not sure what the second SELECT is for, as I would have thought that if the first SELECT didn't find the query value, the second wouldn't find it either. But I've not done much with MySQL full text searches, so I might be missing something.
Anyway, you really need to check the SQL, and any errors, carefully. You can get error information by printing the results of PDOStatement->errorCode:
$sth->execute($sql_data);
$arr = $sth->errorInfo();
print_r($arr);
Update 2 >>
Another point worth mentioning: make sure that when you interpolate variables into your SQL statement, that you only use trusted data. That is, don't allow user supplied data to be used for table or column names. It's great that you are using prepared statements, but these only protect parameters, not SQL keywords, table names and column names. So:
"SELECT * FROM ".$db_prefix."_base"
...is using a variable as part of the table name. Make very sure that this variable contains trusted data. If it comes from user input, check it against a whitelist first.
<< End of Update 1
You should read the MySQL Full-Text Search Functions, and the String Comparison Functions. You need to learn how to construct basic SQL statements, or else writing even a simple search engine will prove extremely difficult.
There are plenty of PDO examples on the PHP site too. You could start with the documentation for PDOStatement->execute, which contains some examples of how to use the function.
If you have access to the MySQL CLI, or even PHPMyAdmin, you can try out your SQL without all the PHP confusing things. If you are going to be doing any database development work as part of your PHP application, you will find being able to test SQL independently of PHP a great help.

Categories