Search filtering using PHP and MySQL - php

I am writing a search filter that will take a list of criteria, query the database, and return an array of usernames that match. Here is essentially what I'm doing:
if (!empty($_GET['cat'])) {
$category = urldecode($_GET['cat']);
$category_query = "SELECT DISTINCT username FROM tutor_subjects_taught WHERE category = '{$category}'";
$category_process = mysql_query($category_query);
while ($row2 = mysql_fetch_assoc($category_process)) {
$usernames[] = $row2['username'];
}
}
This takes the set category from the URL and queries the database for usernames that match this and puts it into an array.
Now, what I need to do is use additional "filters" to narrow down those usernames. My issue is: if the $usernames array is already set, how can I create a looped query that will check out each username and then return a subset array that matches?
For example, let's say $usernames is already set by the previous bit of code because we already have a $_GET['cat'] variable set. Now we add another $_GET variable "rev":
if (!empty($_GET['rev']) && isset($usernames)) {
//Need to create loop here that will take all usernames in array from the previous block of code, check them for rev matching specific number, and return those that match into the $usernames array.
}

First off, you shouldn't use mysql. Use mysqli instead. This improves the security of your website. This will make it harder for hackers to use SQL injection.
For the filtering you could make it all in one query by setting up all the filters at the beginning. Make a $filter variable where you save all the values.
Example:
$filters = array();
if (!empty($_GET['cat'])) {
$category = urldecode($_GET['cat']);
$filter[] = 'category = ' . $category;
}
if (!empty($_GET['rev'])) {
$anotherFilter = urldecode($_GET['rev']);
$filters[] = 'anotherFilter = ' . $anotherFilter;
}
$filter = implode(' AND ', $filters);
$filter = $mysqli->real_escape_string($filter);
$mysqli = new mysqli('localhost', 'username', 'password', 'database');
$stmt = $mysqli -> prepare("SELECT DISTINCT username FROM tutor_subjects_taught WHERE '$filter'");
$stmt -> execute();
$stmt -> bind_result($username);
/* fetch values */
while ($stmt->fetch()) {
printf ("%s\n", $username);
}
$stmt -> close();
$mysqli -> close();

Related

How to check if column equals a value and do somthing if true? [duplicate]

This question already has answers here:
Single result from database using mysqli
(6 answers)
Closed 2 years ago.
I am trying to write a function that will check for a single value in the db using mysqli without having to place it in an array. What else can I do besides what I am already doing here?
function getval($query){
$mysqli = new mysqli();
$mysqli->connect(HOST, USER, PASS, DB);
$result = $mysqli->query($query);
$value = $mysqli->fetch_array;
$mysqli->close();
return $value;
}
How about
$name = $mysqli->query("SELECT name FROM contacts WHERE id = 5")->fetch_object()->name;
The mysql extension could do this using mysql_result, but mysqli has no equivalent function as of today, afaik. It always returns an array.
If I didn't just create the record, I do it this way:
$getID = mysqli_fetch_assoc(mysqli_query($link, "SELECT userID FROM users WHERE something = 'unique'"));
$userID = $getID['userID'];
Or if I did just create the record and the userID column is AI, I do:
$userID = mysqli_insert_id($link);
Always best to create the connection once at the beginning and close at the end. Here's how I would implement your function.
$mysqli = new mysqli();
$mysqli->connect(HOSTNAME, USERNAME, PASSWORD, DATABASE);
$value_1 = get_value($mysqli,"SELECT ID FROM Table1 LIMIT 1");
$value_2 = get_value($mysqli,"SELECT ID FROM Table2 LIMIT 1");
$mysqli->close();
function get_value($mysqli, $sql) {
$result = $mysqli->query($sql);
$value = $result->fetch_array(MYSQLI_NUM);
return is_array($value) ? $value[0] : "";
}
Here's what I ended up with:
function get_col($sql){
global $db;
if(strpos(strtoupper($sql), 'LIMIT') === false) {
$sql .= " LIMIT 1";
}
$query = mysqli_query($db, $sql);
$row = mysqli_fetch_array($query);
return $row[0];
}
This way, if you forget to include LIMIT 1 in your query (we've all done it), the function will append it.
Example usage:
$first_name = get_col("SELECT `first_name` FROM `people` WHERE `id`='123'");
Even this is an old topic, I don't see here pretty simple way I used to use for such assignment:
list($value) = $mysqli->fetch_array;
you can assign directly more variables, not just one and so you can avoid using arrays completely. See the php function list() for details.
This doesn't completely avoid the array but dispenses with it in one line.
function getval($query) {
$mysqli = new mysqli();
$mysqli->connect(HOST, USER, PASS, DB);
return $mysqli->query($query)->fetch_row()[0];
}
First and foremost,
Such a function should support prepared statements
Otherwise it will be horribly insecure.
Also, such a function should never connect on its own, but accept an existing connection variable as a parameter.
Given all the above, only acceptable way to call such a function would be be like
$name = getVal($mysqli, $query, [$param1, $param2]);
allowing $query to contain only placeholders, while the actual data has to be added separately. Any other variant, including all other answers posted here, should never be used.
function getVal($mysqli, $sql, $values = array())
{
$stm = $mysqli->prepare($sql);
if ($values)
{
$types = str_repeat("s", count($values));
$stm->bind_param($types, ...$values);
}
$stm->execute();
$stm->bind_result($ret);
$stm->fetch();
return $ret;
}
Which is used like this
$name = getVal("SELECT name FROM users WHERE id = ?", [$id]);
and it's the only proper and safe way to call such a function, while all other variants lack security and, often, readability.
Try something like this:
$last = $mysqli->query("SELECT max(id) as last FROM table")->fetch_object()->last;
Cheers

Stop SQL from inserting duplicates (php)

It seems to be impossible to do this just with SQL statements, so I wrote a php check, which is completely ignored by the script. $resourse array holds the right data.
public function handleUpdates($updates) {
$stmt = $this->database->connect()->prepare("SELECT ? FROM users"); //<-
$stmt->execute(["username"]); //<-
$resource = $stmt->fetch(PDO::FETCH_ASSOC); //<-
foreach ($updates["result"] as $update) {
$text = $update["message"]["text"];
$args = $update["message"]["chat"]["username"];
if ($text === "/start") {
if ($resource['username'] !== $args) //this here is ignored
$this->database->add($args);
}
}
}
From what I remember about PDO/SQL (I moved to MVC/Doctrine a while back), this part seems a little redundant
$stmt = $this->database->connect()->prepare("SELECT ? FROM users"); //<-
$stmt->execute(["username"]); //<-
and could be replaced with
$stmt = $this->database->connect()->prepare("SELECT username FROM users"); //<-
as you're only ever wanting to get the data found in the username column there's no need to bind it (which isn't fully possible in PDO anyway).
The reason your query fails is that you are using fetch over fetchAll which returns only the first row of results, while this will run it won't give the desired result (which I'm guessing is to check if the username already exists). Even then (as Ivan Vartanyan points out), you would need to foreach or in_array over $resource as it's results are sent as an array anyway.
Realistically you don't need to search and iterate over all the data in PHP, consider searching for your passed username data with SQL instead (code untested);
public function handleUpdates($updates) {
$stmt = $this->database->connect()->prepare("SELECT username FROM users WHERE username = ?");
$stmt->execute(array($update["message"]["chat"]["username"]));
$resource = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$resource) {
foreach ($updates["result"] as $update) {
$text = $update["message"]["text"];
$args = $update["message"]["chat"]["username"];
if ($text === "/start") {
$this->database->add($args);
}
}
}
}

Exclude a field from a SELECT * FROM $table

I need to exclude a field 'password' from a SELECT * FROM $table; where $table is a PHP variable.
Only one of the four posible tables has a 'password' field.
Here is what I have:
function myData($table)
{
include "conf.php";
$con = mysqli_connect($host, $user, $password, $db);
$sql = "SELECT * FROM $table;";
$resul = mysqli_query($con, $sql);
return $resul;
}
Any ideas?
EDIT: This is how I treat the data returned:
$resulFields = myFields($table);
$resulData = myData($table);
while ($fields = mysqli_fetch_array($resulFields, MYSQLI_ASSOC)) {
$field = $fields['Field'];
$header .= "<th>$field</th>";
while ($data_array = mysqli_fetch_array($resulData, MYSQLI_ASSOC) ) {
$body .= "<tr id='$data_array[id]'>";
foreach ($data_array as $data){
$body .= "<td>$data</td>";
}
}
}
Sorry if it's a little bit messy, I'm just starting to learn programming.
I understand that you're wanting to have a single PHP function that will return all the results in a given table. Perhaps instead of returning the $resul variable and parsing the data after the return, you should parse it into an associative array prior to returning it. You can try something like this:
function myData($table) {
include "conf.php";
$con = mysqli_connect($host, $user, $password, $db);
$sql = "SELECT * FROM {$table}";
$resul = mysqli_query($con, $sql);
$row = $resul->fetch_assoc();
unset( $row['password'] );
return $resul;
}
Though I feel it's important to note that in the interests of proper coding practices and single responsibility, you should have specific data access functions for each query you wish to run. I don't recommend having a single function that just returns everything from a table. Functions should also be named such that you know what they're doing. "myData" is very non-descriptive and as such a very poor name for a data access function.
Also, if you're going to name a variable $resul, just go ahead and type the "t" and name it $result FFS.
In the foreach loop, get the key and the data from the array. (The current code is getting only the data.)
Inside the foreach loop, do a conditional test on the value of key.
If the value of the key matches "password", then skip over outputting anything for that element of the array. If it doesn't match key, then output it (like the current code is doing.)
Look at the alternative syntax for foreach:
References: http://php.net/manual/en/control-structures.foreach.php
And for simple conditional tests
Reference: http://php.net/manual/en/control-structures.if.php
Consider whether you want to match "password", "PASSWORD", "Password", etc. You might want a case insensitive match.
Maybe you can do something like this:
function myData($table) {
include "conf.php";
$con = mysqli_connect($host, $user, $password, $db);
$sql = "SELECT field1, field2";
if ($table == "TABLE_WITH_PASSWORD") {
$sql.=",password";
}
$sql.=" FROM $table;";
$resul = mysqli_query($con, $sql);
return $resul;
}
Obviously the best bet is to select what you do want:
SELECT id, name, whatever FROM $table
Hopefully I'm not going down the wrong path, but here is one way other than querying for the fields and removing the password:
$columns['tableA'] = array('id', 'name', 'whatever');
$columns['tableB'] = array('id', 'user', 'something');
Then do:
$select = implode(',', $columns[$table]);
$sql = "SELECT $select FROM $table";
IMO i think the simplest way in this case is to use special case for php
function myData($table) {
include "conf.php";
$con = mysqli_connect($host, $user, $password, $db);
if($table == "special_case_table"){
$sql = "SELECT col1, col2, col3 FROM special_case_table;"; //except "password" column
}
else $sql = "SELECT * FROM $table;";
$resul = mysqli_query($con, $sql);
return $resul;
No need more function or go search in INFORMATION_SCHEMA of database to find column password.

About the mysql_query -> mysql_fetch_array() procedure

Sample code:
$infoArray = array();
require_once("connectAndSelect.php");
// Connects to mysql and selects the appropriate database
$sql = "SOME SQL";
if($results = mysql_query($sql))
{
while($result = mysql_fetch_array($results, MYSQL_ASSOC))
{
$infoArray[] = $result;
}
}
else
{
// Handle error
}
echo("<pre>");
print_r($infoArray);
echo("</pre>");
In this sample code, I simply want to get the result of my query in $infoArray. Simple task, simple measures... not.
I would have enjoyed something like this:
$sql = "SOME SQL";
$infoArray = mysql_results($sql);
But no, as you can see, I have two extra variables and a while loop which I don't care for too much. They don't actually DO anything: I'll never use them again. Furthermore, I never know how to call them. Here I use $results and $result, which kind of represents what they are, but can also be quite confusing since they look so much alike. So here are my questions:
Is there any simpler method that I
don't know about for this kind of
task?
And if not, what names do you
give those one-use variables? Is
there any standard?
The while loop is really only necessary if you are expecting multiple rows to be returned. If you are just getting one row you can simply use mysql_fetch_array().
$query = "SOME SQL";
$result = mysql_query($query);
$row = mysql_fetch_array($result);
For single line returns is the standard I use. Sure it is a little clunky to do this in PHP, but at least you have the process broken down into debug-able steps.
Use PDO:
<?php
/*** mysql hostname ***/
$hostname = 'localhost';
/*** mysql username ***/
$username = 'username';
/*** mysql password ***/
$password = 'password';
try {
$dbh = new PDO("mysql:host=$hostname;dbname=mysql", $username, $password);
$sql = "SELECT * FROM myTable";
$result = $dbh->query($sql)
//Do what you want with an actual dataset
}
catch(PDOException $e) {
echo $e->getMessage();
}
?>
Unless you are legacied into it by an existing codebase. DONT use the mysql extension. Use PDO or Mysqli. PDO being preferred out of the two.
Your example can be come a set of very consise statements with PDO:
// create a connection this could be done in your connection include
$db = new PDO('mysql:host=localhost;dbname=your_db_name', $user, $password);
// for the first or only result
$infoArray = $db->query('SOME SQL')->fetch(PDO::FETCH_ASSOC);
// if you have multiple results and want to get them all at once in an array
$infoArray = $db->query('SOME SQL')->fetchAll(PDO::FETCH_ASSOC);
// if you have multiple results and want to use buffering like you would with mysql_result
$stmt = $db->query('SOME SQL');
foreach($stmt as $result){
// use your result here
}
However you should only use the above when there are now variables in the query. If there are variables they need to be escaped... the easiest way to handle this is with a prepared statement:
$stmt = $db->prepare('SELECT * FROM some_table WHERE id = :id');
$stmt->execute(array(':id' => $id));
// get the first result
$infoArray = $stmt->fetch(PDO::FETCH_ASSOC);
// loop through the data as a buffered result set
while(false !== ($row = $stmt->fetch(PDO::FETCH_ASSOC))){
// do stuff with $row data
}

Store elememts of a datatable into an array

I have a database table made in phpmyadmin. I want the elements of the table to be stored row-wise in an array. I have three columns named edge_id, vertexA and VertexB. I want the elements of these three columns to be stored into an array.
I don't know those commands for PHP. Please help me out.
i have columns in my table named
"vertexa" and "vertexb",i want to
store the colums in two separate
arrays ...how can i do it??
The simplest way would be:
$db = new PDO('mysql:host=localhost;dbname=your_db_name;', $user, $password);
$vertices_a = array();
$vertices_b = array();
foreach($db->query('SELECT * from your_table_name') as $row){
$id = $row['edge_id'];
// add them to the proper array using the edge_id as the index -
// this assumes edge_id is unique
$vertices_a[$id] = $row['vertexa'];
$vertices_b[$id] $row['vertexb'];
}
So with PDO:
$db = new PDO('mysql:host=localhost;dbname=your_db_name;', $user, $password);
foreach($db->query('SELECT * from your_table_name') as $row){
echo $row['edge_id'];
echo $row['vertexA'];
echo $row['vertexB'];
}
Now if you need to use input data you need to escape it. The best way to do this is to use a prepared statement because escaping is handle when the parameters are bound to the query.
Lets say for example you want to use the edge_id supplied from a get request like mysite.com/show-boundry.php?edge=5...
$db = new PDO('mysql:host=localhost;dbname=your_db_name;', $user, $password);
// create a prepared statement
$stmt = $db->prepare('SELECT * from your_table_name WHERE edge_id = ?');
// execute the statement binding the edge_id request parameter to the prepared query
$stmt->execute(array($_GET['edge']));
// loop through the results
while(false !== ($row = $stmt->fetch(PDO::FETCH_ASSOC))){
echo $row['edge_id'];
echo $row['vertexA'];
echo $row['vertexB'];
}
Also you shouldnt use mixed case column/table names like vertexA instead use underscore separators like vertex_a.
You first need to connect to the database:
$link = mysql_connect('localhost','username','password');
if (!$link) {
// Cannot connect
}
$ret = mysql_select_db('database-name', $link);
if (!$ret) {
// Cannot select database
}
Then you need to execute your query:
$ret = mysql_query('SELECT * FROM `table`;', $link);
if (!$ret) {
// Query failed
}
Then you simply load each row:
$data = array();
while ($row = mysql_fetch_assoc($ret)) {
$data[] = $row;
}
Then you should free your request results
mysql_free_result($ret);
And voilĂ .
$res = mysql_query("............");
$row = mysql_fetch_array($res);
Checkout: mysql_fetch_array PHP page

Categories