MySQL WHERE 'all' when no value supplied - php

I am writing a tool to search through different records in my database, where you have to specify the year. However, if no year value is entered, or is equal to zero, I want to be able to select all records.
$stmt = $mysqli->prepare("SELECT * FROM performances WHERE year = ?");
$stmt->bind_param("i", $year);
I have tried to do if statements, but they fail because then there are more parameters in bind_param than spaces in the query, m.sh:
$stmt = $mysqli->prepare("SELECT *
FROM performances
. (($year != 0) ? " WHERE year = ? " : " ")
. "");
$stmt->bind_param("i", $year);
Thanks

You can achieve this in different ways, like:
$stmt = $mysqli->prepare("SELECT * FROM performances WHERE year = :year or 0 = :year");
$stmt->bind_param("year", $year);

ShyForNow has a pretty good answer. I'd also recommend to validate inputs going into SQL:
$year = sprintf("%d", $year); -- or even throw exception if $year is not numeric
if ($year > 0) -- or could also write if ($year >= $minAcceptableYear and $year <= $maxAcceptableYear)
{
$stmt = $mysqli->prepare("SELECT * FROM performances WHERE year = ?");
$stmt->bind_param("i", $year);
}
else
{
$stmt = $mysqli->prepare("SELECT * FROM performances");
}

Related

How to LOOP a SELECT query until it finds a data on database (PHP to MySQL)

I wanted to select a row in the database, but if row is not in the database, it should loop until it finds the
This line
$prev_date = date('M d, Y', strtotime($macrodate .' -1 day')); transforms the currentdate to one down (lets say Jun 15, it will transform to Jun 14). And use that date to check if the date is in the database, it not, it will loop and go to Jun 13. Until it could find the date.
How do I do this? What loop should I use?
$query = "SELECT * FROM users_macros WHERE userid = '$userid' AND `date` = '$macrodate'";
$result = mysqli_query($con, $query);
if (mysqli_num_rows($result) == 0) {
while(1) {
$prev_date = date('M d, Y', strtotime($macrodate .' -1 day'));
$query2 = "SELECT * FROM users_macros WHERE userid = '$userid' AND `date` = '$prev_date'";
$result2 = mysqli_query($con, $query2);
if (mysqli_num_rows($result2) != 0) {
$row2 = mysqli_fetch_assoc($result2);
$targetcarbs = $row2['carbs'];
$targetproteins = $row2['proteins'];
$targetfats = $row2['fats'];
$con->query("INSERT INTO users_macros VALUES('','$userid','$targetproteins','$targetfats','$targetcarbs','$macrodate')");
break;
}
}
}
Don't use a loop. Just use a query that returns the row with the highest date lower than $macrodate. And you can combine that with the INSERT query.
And add a NOT EXISTS criteria to make it select nothing if the given date is already in the table.
Also, use a prepared statement to prevent SQL injection.
$stmt = mysqli_prepare($con, "
INSERT INTO users_macros
SELECT '', userid, proteins, fats, carbs, ? FROM users_macros
FROM users_macros
WHERE userid = ? AND date < ?
AND NOT EXISTS (
SELECT 1 FROM users_macros
WHERE userid = ? AND date = ?
)
ORDER BY date DESC
LIMIT 1");
mysqli_stmt_bind_param($stmt, "sss", $macrodate, $userid, $macrodate, $userid, $macrodate);
mysqli_stmt_execute($stmt);

Using a GET variable in a MySQL/PHP query

I'm working with a mysql date column called 'class_of' that has dates ranging from 2014-08-01 to 2019-08-01, all formatted as a date. These dates coincide to what year an article was written.
I have set up my php execution page to grab the year through a url action.
for example - www.mywebsite.com/mypage.php?action=2016
$classOf = ($_GET["action"]);
I now need to somehow use said variable within a mysql query so my php while loop will only echo dates that have for example 2016 within the date.
This is what I have tried
This works, but I need the year to be a variable
$query = 'SELECT * FROM news_content
WHERE
hot = "false"
AND trash="false"
AND class_of = DATE("2020-08-01")
ORDER BY article_id DESC';
I have tried the below, but with no success
$query = 'SELECT * FROM news_content
WHERE
hot = "false"
AND trash="false"
AND class_of = DATE("<?php echo $classOf ?>-08-01")
ORDER BY article_id DESC';
And
$query = 'SELECT * FROM news_content
WHERE
hot = "false"
AND trash="false"
AND class_of = "<?php echo $classOf ?>" ORDER BY article_id DESC';
And
$query = 'SELECT * FROM news_content
WHERE
hot = "false" AND trash="false"
AND class_of
LIKE "%<?php echo $classOf ?>%" ORDER BY article_id DESC
And
$query = 'SELECT *
FROM news_content
WHERE
hot = "false" AND trash="false"
AND class_of =
"<?php date("echo $classOf-08-01")?>" ORDER BY article_id DESC';
All of the above no success.
Use PHP DateTime class to get the full date and then prepared statements to pass the value to SQL.
$date = (new DateTime ($_GET['action'] . '08-01'))->format('Y-m-d');
$stmt = $mysqli->prepare ('SELECT * FROM news_content WHERE hot = "false" AND trash="false" AND class_of=? ORDER BY article_id DESC');
$stmt->bind_param('s', $date);
$stmt->execute();
$result = $stmt->get_result();
If you want to get all records from a matching year then create 2 PHP dates, dateFrom and dateTo, and then use BETWEEN in MySQL query
$dateFrom = (new DateTime ($_GET['action'] . '01-01'))->format('Y-m-d');
$dateTo = (new DateTime ($_GET['action'] . '12-31'))->format('Y-m-d');
$stmt = $mysqli->prepare ('SELECT * FROM news_content WHERE hot = "false" AND trash="false" AND class_of BETWEEN ? AND ? ORDER BY article_id DESC');
$stmt->bind_param('ss', $dateFrom, $dateTo);
$stmt->execute();
$result = $stmt->get_result();

updating a datetime sql value by exactly a year

im trying to get a datetime variable (example: 2019-02-10 03:13:33) to update exactly a year. i read that datetime is written as a string so i tried to subtract by itself and add +365.
the code works if i take out all "expirationdate" including the bind value. also for some reason, i have to keep my UPDATEs encased in single quotations because theres no changes in my database if they are inside double quotes.
$stmt = $db->prepare('UPDATE usr_customer_profile SET packageid = 3, expirationdate = .'$oneyear'. WHERE usrcustomerid = :usrcustomerid');
$stmt->bindValue(':expirationdate', $_SESSION['expirationdate'], PDO::PARAM_STR);
$stmt->bindValue(':usrcustomerid', $_SESSION['usrcustomerid'], PDO::PARAM_INT);
$oneyear = (':expirationdate' - ':expirationdate') + 365;
$stmt->execute();
You can do this in PHP or SQL. In PHP you can use strtotime or (preferably) the DateTime class to add one year to the value in $_SESSION['expirationdate']:
// using strtotime
$expirationdate = date('Y-m-d H:i:s', strtotime($_SESSION['expirationdate'] . ' + 1 year'));
// using DateTime
$expiration = new DateTime($_SESSION['expiration_date']);
$expiration->add(new DateInterval('P1Y'));
$expirationdate = $expiration->format('Y-m-d H:i:s');
// do the query
$stmt = $db->prepare('UPDATE usr_customer_profile
SET packageid = 3,
expirationdate = :expirationdate
WHERE usrcustomerid = :usrcustomerid');
$stmt->bindValue(':expirationdate', $expirationdate, PDO::PARAM_STR);
$stmt->bindValue(':usrcustomerid', $_SESSION['usrcustomerid'], PDO::PARAM_INT);
$oneyear = (':expirationdate' - ':expirationdate') + 365;
$stmt->execute();
In SQL use + INTERVAL 1 YEAR to add 1 year to the expiration date:
$stmt = $db->prepare('UPDATE usr_customer_profile
SET packageid = 3,
expirationdate = :expirationdate + INTERVAL 1 YEAR
WHERE usrcustomerid = :usrcustomerid');
$stmt->bindValue(':expirationdate', $_SESSION['expirationdate'], PDO::PARAM_STR);
$stmt->bindValue(':usrcustomerid', $_SESSION['usrcustomerid'], PDO::PARAM_INT);
$oneyear = (':expirationdate' - ':expirationdate') + 365;
$stmt->execute();

Between clause is returning 0 records

I have 3 records in the database matching the criteria but when I run query with between clause it is getting 0 records.
$current_date = date('m-d-Y', strtotime('monday this week'));
$upcoming_date = date('m-d-Y', strtotime('monday next week'));
$sql = mysqli_query($connection, "SELECT * FROM result WHERE test_date BETWEEN $current_date AND $upcoming_date AND login = '".$_SESSION['uid'] ."'");
$total_check = mysqli_num_rows($sql);
Here is my database
result_id`, `login`, `test_id`, `test_date`,
(1, '2', 6, '08-03-2016',
(2, '2', 5, '08-03-2016',
(3, '2', 3, '08-03-2016',
Please let me know where and what I am doing wrong as I am getting 0 results and $_SESSION['uid'] is 2
You should use ' for $current_date AND $upcoming_date
"SELECT * FROM result WHERE test_date BETWEEN '$current_date' AND '$upcoming_date' AND login = '".$_SESSION['uid'] ."'"
Use prepare statement like below to avoid SQL Injection
$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->bind_param('s', $name);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// do something with $row
}
You are storing your dates incorrectly if you want to use them in range searches like BETWEEN. You must store them in DATE columns. Storing them in VARCHAR() columns is a bad idea.
You could use something like this, using STR_TO_DATE() to work around your misdesigned table.
$current_date = date('Y-m-d', strtotime('monday this week'));
$upcoming_date = date('Y-m-d', strtotime('monday next week'));
$sql = mysqli_query($connection, "SELECT * FROM result WHERE STR_TO_DATE(test_date,'%d-%m-%Y') BETWEEN '$current_date' AND '$upcoming_date' AND login = '".$_SESSION['uid'] ."'");
To ask MySQL to compare the strings 01-01-2016 and 12-31-2015, and determine that the latter comes before the former is unreasonable. String comparison is lexical. However, 2015-12-31 obviously comes before 2016-01-01.
This is a little tricky to get right, because the text string 08-08-2016 does come before 08-15-2016, by accident. But at the end of year, things collapse.

Problems with using PDO to perform an advanced search query

I have the following code and all of the search functions work except for the title field. So I can search by genre, date, location etc... but not by title. When attempting to search by title nothing is returned at all. Can anyone help me with this?
Also, is there a more efficient way to count all the fields before limiting it for use in pagination later on?
$today = date("Y-m-d");
$query = "SELECT * FROM TABLE_NAME WHERE Date >= '$today'";
$bind = Array();
if ($_GET["Title"] && $_GET["Title"] != "") {
$query .= " and Title like %?%";
$bind['Title'] = $_GET['Title'];
}
if ($_GET["Genre"] && $_GET["Genre"] != "") {
$query .= " and Genre like %?%";
$bind['Genre'] = $_GET['Genre'];
}
if ($_GET["Location"] && $_GET["Location"] != "") {
$query .= " and Location like %?%";
$bind['Location'] = $_GET['Location'];
}
if ($_GET["Date"] && $_GET["Date"] != "") {
$query .= " and Date = %?%";
$bind['Date'] = $_GET['Date'];
}
$stmt = $db->prepare($query);
$stmt->execute($bind);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
$num = count($rows);
$query .= " ORDER BY Date LIMIT $limit, 9";
$stmt = $db->prepare($query);
$stmt->execute($bind);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
Edit: After everyone's help I thought I would post my now revised code for future reference. It turns out the other fields were not working, but instead due to the if statement all this was nested in the code simply wasn't being executed.
$today = date("Y-m-d");
$query = "SELECT * FROM TABLE_NAME WHERE Date >= '$today'";
$countq = "SELECT count(*) FROM TABLE_NAME WHERE Date >= '$today'";
$bind = Array();
if ($_GET["Title"] && $_GET["Title"] != "") {
$query .= " and Title like :title";
$countq .= " and Title like :title";
$bind[':title'] = "%{$_GET['Title']}%";
}
if ($_GET["Genre"] && $_GET["Genre"] != "") {
$query .= " and Genre like :genre";
$countq .= " and Genre like :genre";
$bind[':genre'] = "%{$_GET['Genre']}%";
}
if ($_GET["Location"] && $_GET["Location"] != "") {
$query .= " and Location like :loc";
$countq .= " and Location like :loc";
$bind[':loc'] = "%{$_GET['Location']}%";
}
if ($_GET["Date"] && $_GET["Date"] != "") {
$query .= " and Date = :date";
$countq .= " and Date = :date";
$bind[':date'] = "{$_GET['Date']}";
}
$stmt = $db->prepare($countq);
$stmt->execute($bind);
$rows = $stmt->fetchAll();
$num = count($rows);
$query .= " ORDER BY Date LIMIT $limit, 9";
$stmt = $db->prepare($query);
$stmt->execute($bind);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
all of the search functions work
With the given query it is not true
From PDO tag wiki:
placeholders cannot represent an arbitrary part of the query, but a complete data literal only. Neither part of literal, nor whatever complex expression or a syntax keyword can be substituted with prepared statement.
Prepare FULL literal first: $name = "%$name%"; and then bind it.
As for the "more" efficient method for pagination - yes, oh yes.
With your current way of counting data you don't actually need other queries. as you have ALL the data already and can paginate it as well.
But of course it will pollute all the memory soon. So, if you want to get a count of rows from database, get the very count: run the same query but instead of SELECT * make it "SELECT count(*)
There are not any errors returned, that's why I am so confused
From PDO tag wiki again:
It is essential to set ERRMODE_EXCEPTION as a connection option as it will let PDO throw exceptions on connection errors. And this mode is the only reliable way to handle PDO errors.

Categories