PHP - Form fields that create MYSQL Queries on submit - php

can anyone help me with how can I achieve form fields that create MySQL queries? below are the details
Table name: books
id
user_id
cateory_id
name
1
2
1
Book name 1
1
4
4
Book name 2
and in my HTML view this is how the form looks like
https://imgur.com/Sy0NSf7
The Column field drop down values are the table field names: id, user_id, category_id, name
The Comparison drop down values are: '=', '<', '>', 'contains'
'contains' value is like 'LIKE' this must be change on the backend
and the Value input field is just a text field where you put what you are looking for
This form is dynamic where you can add filter with the radio button condition value of 'or' or 'and'
so my goal is when I click the submit button it will create mysql query with LEFT JOIN?I'm not really sure what I'm supposed to do.
Sample output:
id
user_id
cateory_id
name
1
James
Fiction
Book name 1
1
John
Non-Fiction
Book name 2
below is my code to create mysql query but I think this is wrong because I have a user_id and category_id which I need to append the JOIN
$data = $request->getParsedBody();
$query = "SELECT * FROM books WHERE ";
foreach ($data['column'] as $key => $value) {
if ($data['comparison'][$key] == 'contains')
{
$data['comparison'][$key] = 'LIKE';
$data['value'][$key] = "'%" . $data['value'][$key] . "%'";
}
if ($key <= 0)
{
$query .= "{$value} {$data['comparison'][$key]} '{$data['value'][$key]}'";
}
if ($key > 0) {
if (!$value == "" && !$data['comparison'][$key] == "" && !$data['value'] == "")
{
$query .= " {$data['and_or'][$key-1]} {$value} {$data['comparison'][$key]} '{$data['value'][$key]}'";
}
}
}
$query .= " ORDER BY id DESC";
sorry for my bad english.

As there are only 2 additional tablex we can hardcode them in the query, using a LEFT JOIN so that we will always get any matching data from books.
The following example uses one value for each possible search field. You could construct your query string dynamically using the same logic
<?php
/* We are not prepared prepared to take any risks with sql injection */
if ("$data['comparison1'][$key]" == "AND") { andor[1] = AND } else { andor[1] = "OR"};
if ("$data['comparison2'][$key]" == "AND") { andor[2] = AND } else { andor[2] = "OR"};
if ("$data['comparison3'][$key]" == "AND" ){ andor[3] = AND } else { andor[3] = "OR"};
/* prepare the query using string concatenation with the the values in andor[] */
$query = "SELECT b.id, u.user_id, c.category_id, b.name
FROM books b
LEFT JOIN categories c ON b.id = c.id
LEFT JOIN users u ON b.id = u.id
WHERE
( b.id = COALESCE(:book_id , b.id)"
.andor[1].
"( b.name = COALESCE(:book_name , b.name)"
.andor[2].
"( c.category_id = COALESCE(:category , c.category_id)"
.andor[3].
"( u.user_id = COALESCE(:user_id , u.user_id);";
/* Here you need to prepare the database connecter $dbh */
$host = 'localhost';
$db = 'bookdb';
$user = 'root';
$password = 'S#cr#t1!';
$dsn = "mysql:host=$host;dbname=$db;charset=UTF8";
/* and connect to the database */
try {
$pdo = new PDO($dsn, $user, $password);
if ($pdo) {
echo "Connected to the $db database successfully!";
}
} catch (PDOException $e) {
echo $e->getMessage();
}
/* we prepare the query and load the variables */
$sth = $pdo->prepare($query);
$sth->bindValue(':bookname', "$data['book_id'][$key]");
$sth->bindValue(':book_name', "$data['book_name'][$key]"); ;
$sth->bindValue(':category', "$data['category'][$key]");
$sth->bindValue(':user_id', "$data['user_id'][$key]");
/* here we execute the query and extract the results*/
$sth->execute();
$book_results = $sth->fetchAll();
/* now you can exploit the table $book_results
here we simply print it so that you can check */
print_r( $book_results);
?>

Related

Selecting rows where out of two columns one is null

Out of two search selections if a visitor select one only there is no search result. Following is my sql query:
$sql = "SELECT * FROM table WHERE column1='$column1' AND column2 ='$column2' ORDER BY id DESC
If I use 'OR' or otherwise I got wrong result in pagination. What should be right coding if a visitor opted only one criteria to search he will get result in first and subsequent pages?
In PHP construct your query:
$where = [];
$params = [];
if (!empty($column1)) {
$where[] = 'column1 = :column1';
$params[':column1'] = $column1;
} else {
$where[] = 'column1 IS NULL';
}
if (!empty($column2)) {
$where[] = 'column2 = :column2';
$params[':column2'] = $column2;
} else {
$where[] = 'column2 IS NULL';
}
if (!empty($where)) {
$pdo
->prepare("SELECT * FROM table WHERE ".implode(' AND ', $where))
->execute($params);
}
If you allow selection only by one column, remove else parts
A fast solution is that you can put the filters into a variable checking if the values of $column1 or $column2 it's filled and add after that in the SELECT clause:
$where_column = 'WHERE ';
if ($column1 != false)
$where_column .= "column1='$column1'";
if ($column2 != false) {
if ($where_column != 'WHERE') {
$where_column .= "AND column2='$column2'";
else
$where_column = "column2='$column2'";
}
}
$sql = "SELECT * FROM table $where_column ORDER BY id DESC

MySQL & PHP CMS project 'JOINS'

i have a project to build a CMS. We were giving a few functions.. on is below. I would like someone to explain to me what the 'p', 'ca', and 'cm' mean/stand for?
function getAllPosts() {
global $db;
$sql = "SELECT p.*, ca.catName, COUNT(commentID) as numComments
FROM posts p
LEFT JOIN categorys ca USING (categoryID)
LEFT JOIN comments cm USING (postID)
";
if ($_GET['catID'] != ''){
$catID = (int)$_GET['catID'];
$sql .= "WHERE categoryID = $catID ";
}
$sql .= "GROUP BY postID
ORDER BY postDate DESC";
$qry = mysqli_query($db, $sql);
$result = array();
while ($row = mysqli_fetch_assoc($qry)) {
$result[] = $row;
}
if (count($result) > 0) {
return $result;
}
return false;
}
They are a shorter way to write a query without using the whole table names. (table alias)
E.g. SELECT a.name, a.surname FROM very_long_name_of_my_table [AS] a
instead of
SELECT very_long_name_of_my_table.name, very_long_name_of_my_table.surname FROM very_long_name_of_my_table
SQL aliases are used to give a database table, or a column in a table, a temporary name.
Basically aliases are created to make column names more readable.
for more visit: http://www.w3schools.com/sql/sql_alias.asp

find relations in mysql

i have two tables in my database that store my data and their categories.my data table has one important column that specifies its last category and each category in category table has a parent category that points to a parent category and root categories parent_id is '0'
like this:
now the 'data' table row points to a row in 'categories' table that has id of '7' and it's LED that its parent id is '3' and '3' is Monitor that its parent id is '2' and '2' is Computer Accessories that its parent id is '1' and '1' is Digital stuff and it's one of roots because its parent id is 0
now if i want to find all of data that has been related to the digital stuff or computer accessories with a simple sql query what can i do ? or do you have a better solution to store my data and categories?
in your query first of fall you decide which level you want to show the hierarchy
SELECT a.id, d.name, a.title, b.title as parent_title_name
FROM data d JOIN categories a
ON d.category_id = a.id
JOIN categories b
ON a.id = b.parent_id;
in this query you show the data, its category and it's perent category
With the help of PHP you can do that by recursive function to get all categories and than a query to get data.
$host = 'localhost';
$username = 'root';
$password = 'root';
$database = 'test';
$conn = new mysqli($host, $username, $password, $database);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
function getCategories($id, $conn, &$ids=[]) {
$ids[] = $id;
$sql = "SELECT parent_id FROM categories WHERE id= $id";
$result = $conn->query($sql);
while ($row = $result->fetch_assoc()) {
$parent_id = $row['parent_id'];
if ($parent_id) {
return getCategories($parent_id, $conn, $ids);
}
}
return $ids;
}
$ids = implode(',', getCategories(7));
$sql = "SELECT * FROM data WHERE category_id in ($ids)";
$result = $conn->query($sql);
while ($row = $result->fetch_assoc()) {
print_r($row);
}
And if you want to do that using mysql than i guess you've to create procedure for that.

Simple PHP search in Database won't bring up result

I am building a recipe database with some of my friends and for that we need our users to be able to search within our site. Our database consists of 3 tables:
recipes - recipe_id (primary key), recipe_name
ingredients - ingredient_id (primary key), ingredient_name
recipe_ingredients - ingredient_id (foreign key), recipe_id (foreign key)
We want to be able to search the recipe_ingredients for a recipe or ingredient name and have our site show every ingredient connected to that recipe or every recipe connected to that ingredient. And so we made this query:
select ingredient_name, recipe_name, recipe_ingredients.*
from recipe_ingredients
inner join ingredients inner join recipes
on recipe_ingredients.ingredient_id = ingredients.ingredient_id
and recipe_ingredients.recipe_id = recipes.recipe_id
WHERE ingredient_name = 'Brød';
Which works fine for us. However, putting it into our search function in php, it gives 'There were no search results!' back every single time no matter what we searched. Here is the code. Would someone point out the mistake we made?
$output = '';
if (isset($_POST['work'])) {
$searchq = $_POST['work'];
$searchq = preg_replace("#[^0-9a-z]#i","",$searchq);
$query = mysql_query
("select ingredient_name, recipe_name, recipe_ingredients.*
from recipe_ingredients
inner join ingredients inner join recipes
on recipe_ingredients.ingredient_id = ingredients.ingredient_id
and recipe_ingredients.recipe_id = recipes.recipe_id
WHERE ingredient_name LIKE '%searchq%' or recipe_name LIKE '%searchq%'")
or die ("Could not search");
$count = mysql_num_rows($query);
if($count == 0){
$output = 'There were no search results!';
}
else{
while ($row = mysql_fetch_array($query)) {
$recipe = $row[recipe_name];
$ingredient = $row[ingredient_name];
$id = $row[ingredient_id];
$output .= '<div>'.$recipe.' '.$ingredient.'</div>';
}
}
}
We don't understand why it won't work.
You can try the following. It uses mysqli_* functions and a better structure for the query joins.
$connection = mysqli_connect('localhost', 'root', 'your_password', 'your_database');
mysqli_set_charset($connection, 'utf8');
if (!$connection) {
die("Database connection failed: " . mysqli_error());
}
$output = '';
if (isset($_POST['work'])) {
$searchq = $_POST['work'];
$searchq = preg_replace("#[^0-9a-z]#i", "", $searchq);
$sql = "
SELECT ingredient_name, recipe_name, recipe_ingredients.*
FROM recipe_ingredients
INNER JOIN ingredients
ON recipe_ingredients.ingredient_id = ingredients.ingredient_id
INNER JOIN recipes
ON recipe_ingredients.recipe_id = recipes.recipe_id
WHERE ingredient_name LIKE '%$searchq%' or recipe_name LIKE '%$searchq%'";
$result = mysqli_query($connection, $sql);
if (!$result) {
die("SQL Error: " . mysqli_error($connection);
}
$count = mysqli_num_rows($result);
if ($count == 0) {
$output = 'There were no search results!';
} else {
while ($row = mysqli_fetch_array($result)) {
$recipe = $row[recipe_name];
$ingredient = $row[ingredient_name];
$id = $row[ingredient_id];
$output .= '<div>'.$recipe.' '.$ingredient.'</div>';
}
}
}
First - it depends on what version of PHP you are using, as Jens pointed out mysql_* has been deprecated.
Second - it does not appear that you are connecting to your database. You have to connect to your database first, then execute your query.
Check out this example on PHP's website, it should help you out a lot.
Good luck!
It seems like you re searching for "searchq" all the time and you probably dont have a recipe by that name and I would advise agajnst mysql_* funcs
$output = '';
if (isset($_POST['work'])) {
$searchq = $_POST['work'];
$searchq = preg_replace("#[^0-9a-z]#
i","",$searchq);
$query = mysql_query
("select ingredient_name, recipe_name, recipe_ingredients.*
from recipe_ingredients
inner join ingredients inner join recipes
on recipe_ingredients.ingredient_id = ingredients.ingredient_id
and recipe_ingredients.recipe_id = recipes.recipe_id
WHERE ingredient_name LIKE '%
$searchq%' or recipe_name LIKE '%
$searchq%'")

Multiple Filters That Work Together Or Independently

I have a page where you can filter users by their profile information.
I had 4 different filters that were "City", "Age Above", "Age Below", and "Gender".
I made it work this way, putting every possible combination as an if statement so that all the filters could work separately or in any combination:
if (isset($ageabove)
&& empty($agebelow)
&& empty($gender)
&& empty($city)
)
{
$sql = mysqli_query($con, "select * from Users1
WHERE age >= 1
");
}
This worked, but it was a lot of combinations and I did fear that this may be an inefficient way to do it.
Now I decided that I need to add 1 more filter, making it a total of 5 filters. This would increase the amount 'if' statements exponentially and I am wondering if there is a better way to accomplish this?
If I haven't been clear enough, please let me know.
Any help much appreciated!
$query = "SELECT stuff FROM table WHERE foo=1 ";
if ($filter1) {
$query .= "AND filter1 = $val";
}
if ($filter2) {
$query .= "AND filter2 = $val";
}
// run query
Would something like that work? (if (isset($filter1) && !empty($filter1))..)
Don't store age in a database. Unless the user specifically goes in and edits it they will be whatever age they signed up as forever. Store their birthdate and calculate age on the fly with:
SELECT DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(dob, '%Y') - (DATE_FORMAT(NOW(), '00-%m-%d') < DATE_FORMAT(dob, '00-%m-%d')) AS age
I prefer to do this for dynamic conditions in SQL queries:
$query = 'SELECT * FROM table';
$conditions = array();
$parameters = array();
if( isset($_GET['cond1']) ) {
$parameters[] = $_GET['cond1'];
$conditions = 'column1 = ?';
}
if( isset($_GET['cond2']) ) {
$parameters[] = $_GET['cond2'];
$conditions = 'column2 = ?';
}
// etcetera...
if( ! empty(conditions) ) {
$query .= ' WHERE ' . implode(' AND ', $conditions);
$sth = $db->prepare($query);
$rs = $sth->(execute($parameters));
} else {
$sth = $db->prepare($query);
$rs = $sth->(execute());
}
if( ! $rs ) { /* error message */ }
// yadda yadda yadda
Which will build you a query like:
SELECT * FROM TABLE WHERE column1 = ? AND column2 = ? AND ... columnN = ?
as well as placing all of your arguments into the array in the proper order.
I might be a little squiffy on the parameterization for MySQLi, though. I'm a PDO guy.
To make your filters more dynamic, register them in the database, like that:
You can create a model_filters table (in mysql for example):
drop table if exists model_filters;
create table model_filters (
id int not null auto_increment primary key,
name varchar(80) not null,
model varchar(80) not null,
condition varchar(40) not null,
created datetime,
modified datetime,
active boolean not null default 1,
index model_filters (name)
);
So, create some filters, for specific model:
INSERT INTO model_filters VALUES
('Age Above' , 'user' ,'age <= %filter'),
('Age Below' , 'user' ,'age >= %filter'),
('City' , 'user' ,'city ="%filter"'),
('Gender' , 'user' ,'gender = "%filter"');
Then, get the filters based in your model:
SELECT id, name FROM model_filters WHERE model = 'user' AND active = 1
Iterate this values and generate a filters <select>:
<select name="filters" id="filters">
<option value="1">Age Above</option>
<option value="2">Age Below</option>
<option value="3">City</option>
<option value="4">Gender</option>
</select>
<input type="text" name="value" id="value">
And, you get this information, search for selected filter, and then execute your query
<?php
// I'm using PDO
$statment = $pdo->prepare("SELECT * FROM model_filters WHERE id = :id");
$statment->bindValue(':id', $_POST['filters']);
$status = $statment->execute();
$result = null;
if ($status == true) {
$result = $statment->fetchAll(PDO::FETCH_ASSOC);
}
if ($result == null) {
// ERROR!
}
Now, organize the values
/*
$result['condition'] is equal (for example): "age <= %filter"
After replace is = "age <= :filter"
Obs.: replace for whatever you want, for example: ":filtername, :value, :whatever"
*/
$condition = str_replace('%filter', ':filter', $result['condition']);
$statment = $pdo->prepare("SELECT * FROM Users1 WHERE $condition");
$statment->bindValue(':filter', $_POST['value']);
$status = $statment->execute();
$result = null;
if ($status == true) {
$result = $statment->fetchAll(PDO::FETCH_ASSOC);
}
Get $result, sent for your view, and iterate the filtered users.
Done!

Categories