What is the most efficient way to rewrite this function? - php

function get_total_adults()
{
$sql = "SELECT SUM(number_adults_attending) as number_of_adults FROM is_nfo_rsvp";
$result = mysql_query($sql) or die(mysql_error());
$array = mysql_fetch_assoc($result);
return $array['number_of_adults'];
}
I know there is a way to write this with less code. I'm just looking for the best way (without using something like ezSQL).

function get_total_adults() {
$sql = 'SELECT SUM(number_adults_attending) FROM is_nfo_rsvp';
$result = mysql_query($sql) or die(mysql_error());
// I'd throw a catchable exception (see below) rather than die with a MySQl error
return mysql_result($result, 0);
}
As to how I'd rather handle errors:
function get_total_adults() {
$sql = 'SELECT SUM(number_adults_attending) FROM is_nfo_rsvp';
$result = mysql_query($sql);
if (!$result) {
throw new Exception('Failed to get total number of adults attending');
}
return mysql_result($result, 0);
}
try {
$total_adults = get_total_adults();
} catch(Exception $ex) {
die('Whoops! An error occurred: ' . $ex->getMessage());
// or even better, add to your template and dump the template at this point
}
// continue code

You can drop the "as number_of_adults" part of the query and use mysql_result.

You could also try refactormycode.com

Related

Catch exception from inside class [duplicate]

This question already has answers here:
When to use single quotes, double quotes, and backticks in MySQL
(13 answers)
Closed 4 years ago.
I am little confused with try catch concepts.
I have this code in PHP.
<?php
while (true) {
try {
foreach ($data as $message) {
$functionToCall = new functions();
$functionToCall->remove($data);
}
} catch (Exception $e) {
echo "This is inside catch";
echo 'Message: ' . $e->getMessage();
}
}
class functions
{
public function __construct()
{
$this->dbConnection = pg_pconnect("host = $hostname port=$port dbname = $database user = $username password = $password")
or die("Can't connect to database" . pg_last_error());
}
public function remove($data)
{
$query = "UPDATE table
SET isDeleted = true;
$res = pg_query($this->dbConnection, $query);
if (!$res) {
print_r(error_get_last());
throw new Exception(error_get_last(), 1);
}
}
}
I made a slight change with code to throw an exception I added
unset($this->dbconnection);
after
$query = "UPDATE table
SET isDeleted = true;
to throw an exception. Exception is thrown but My catch is not catching this exception.
How can I catch this error?
Thanks
Looks like a syntax issue if that's the actual code, try this edit:
public function remove($data)
{
$query = "UPDATE table SET 'isDeleted'= true";
$res = pg_query($this->dbConnection, $query);
if (!$res) {
print_r(error_get_last());
throw new Exception(error_get_last(), 1);
}
}
Notice the quote mark changes around: $query = "UPDATE table SET 'isDeleted'= true";
Your exception logic was being parsed as a string it seems.
Notice your code doesn't close the string on $query ...
$query = "UPDATE table
SET \"isDeleted\" = true;
$res = pg_query($this->dbConnection, $query);
if (!$res) {
print_r(error_get_last());
throw new Exception(error_get_last(), 1);
}

PHP mysqli_fetch_assoc not doing returning correct value

I have an old PHP code that has mysql in it.
It gets an array from a SELECT statement, adds it to a JSON object, as a property and echoes the encoded JSON.
I changed it around to use mysqli, but when I try to get the rows, and create an array out of them, it just returns nothing.
Here's the old mysql code:
$con = mysql_connect('host','account','password');
if (!$con)
{
//log my error
};
mysql_select_db("database_name", $con);
mysql_set_charset('utf8');
$sql = "SELECT field1 as Field1, field2 as Field2 from table where ID = '".$parameter."'";
$query = mysql_query($sql);
$results = array();
while($row = mysql_fetch_assoc( $query ) )
{
$results[] = $row;
}
return $results;
Version1: Here's the new one that I tried writing:
$con = mysqli_connect('host','account','password','database_name');
$sql = "SELECT field1 as Field1, field2 as Field2 from table where ID = '".$parameter."'";
$results = array();
if($result=mysqli_query($con, $sql))
{
while ($row=mysqli_fetch_assoc($result))
{
$results[] = $row;
}
return $results;
}
else
{
//error
}
Version2: Second thing I tried, which only returns 1 ROW:
...same as above until $sql
if($result=mysqli_query($con,$sql))
{
$row=mysqli_fetch_assoc($result);
return $row;
}
Version3: Or I tried to completely mirror the mysql structure like this:
$sql = "SELECT ...";
$query = mysqli_query($con, $sql);
$results = array();
while($row = mysqli_fetch_assoc( $query ) )
{
$results[] = $row;
}
return $results;
Wrapping the resulting array into the JSON:
$obj = new stdClass();
$obj->Data = $results;
$obj->ErrorMessage = '';
die(json_encode($obj)); //or echo json_encode($obj);
None of the mysqli version are working, so I was thinking there might be an important change in the way these arrays are created.
Any tips on what could be wrong on the first mysqli example?
With Version2 I can tell that the SQL connection is there, and I can at least select a row. But it's obviously only one row, than it returns it. It makes me think, that building up the array is the source of the problem, or it's regarding the JSON object...
LATER EDIT:
OK! Found a working solution.
ALSO, I played around with the data, selected a smaller chunk, and it suddenly worked. Lesson from this: the function is not responding the same way for 40 rows or for 5 rows. Does it have something to do with a php.ini setting? Or could there be illegal characters in the selection? Could it be that the length of a 'Note' column (from the db) is too long for the array to handle?
Here's the working chunk of code, that selects some rows from the database, puts them into an array, and then puts that array into an object that is encoded into JSON at the end, with a statusmessage next to it. Could be improved, but this is just for demo.
$con = mysqli_connect('host','username','password','database_name');
if (!$con)
{
$errorMessage = 'SQL connection error: '.$con->connect_error;
//log or do whatever.
};
$sql = "SELECT Field1 as FieldA, field2 as FieldB, ... from Table where ID='something'";
$results = array();
if($result = mysqli_query($con, $sql))
{
while($row = mysqli_fetch_assoc($result))
{
$results[] = $row;
}
}
else
{
//log if it failed for some reason
die();
}
$obj->Data = $results;
$obj->Error = '';
die(json_encode($obj));
Question is: how can I overcome the issue regarding the size of the array / illegal characters (if that's the case)?
Your "Version 1" seems to be correct from a PHP perspective, but you need to actually handle the errors - both when connecting and when performing the query. Doing so would have told you that you don't actually query a table, you're missing FROM tablename in the query.
Use mysqli_connect_error() when connecting, and mysqli_error($con) when querying to get back the actual errors. General PHP error-reporting might also help you.
The code below assumes that $parameter is defined prior to this code.
$con = mysqli_connect('host','account','password','database_name');
if (mysqli_connect_errno())
die("An error occurred while connecting: ".mysqli_connect_error());
$sql = "SELECT field1 as Field1, field2 as Field2
FROM table
WHERE ID = '".$parameter."'";
$results = array();
if ($result = mysqli_query($con, $sql)) {
while ($row = mysqli_fetch_assoc($result)) {
$results[] = $row;
}
return $results;
} else {
return mysqli_error($con);
}
Error-reporing
Adding
error_reporting(E_ALL);
ini_set("display_errors", 1);
at the top of your file, directly after <?php would enable you to get the PHP errors.
NOTE: Errors should never be displayed in a live environment, as it might be exploited by others. While developing, it's handy and eases troubleshooting - but it should never be displayed otherwise.
Security
You should also note that this code is vulnerable to SQL-injection, and that you should use parameterized queries with placeholders to protect yourself against that. Your code would look like this with using prepared statements:
$con = mysqli_connect('host','account','password','database_name');
if (mysqli_connect_errno())
die("An error occurred while connecting: ".mysqli_connect_error())
$results = array();
if ($stmt = mysqli_prepare("SELECT field1 as Field1, field2 as Field2
FROM table
WHERE ID = ?")) {
if (mysqli_stmt_bind_param($stmt, "s", $parameter)) {
/* "s" indicates that the first placeholder and $parameter is a string */
/* If it's an integer, use "i" instead */
if (mysqli_stmt_execute($stmt)) {
if (mysqli_stmt_bind_result($stmt, $field1, $field2) {
while (mysqli_stmt_fetch($stmt)) {
/* Use $field1 and $field2 here */
}
/* Done getting the data, you can now return */
return true;
} else {
error_log("bind_result failed: ".mysqli_stmt_error($stmt));
return false;
}
} else {
error_log("execute failed: ".mysqli_stmt_error($stmt));
return false;
}
} else {
error_log("bind_param failed: ".mysqli_stmt_error($stmt));
return false;
}
} else {
error_log("prepare failed: ".mysqli_stmt_error($stmt));
return false;
}
References
http://php.net/mysqli.prepare
How can I prevent SQL injection in PHP?

Cannot display results from query with PDO

I am trying to get the results from a query which should get multiple results and display them all on the page. However it is not displaying any of the content. My guess is a mistake in my syntax for me loop. But I am unsure.
//query to find comments about this map
$query = "
SELECT
user_id,
comment
FROM map_comments
WHERE
map_id = :mapID
";
//query parameters
$query_params = array(
':mapID' => $_SESSION['mapID']
);
try
{
//execute query
$statement = $db->prepare($query);
$result = $statement->execute($query_params);
//get all results
$comments = $result->fetchAll;
if($result === FALSE)
{
die(mysql_error()); // TODO: better error handling
}
}
catch(PDOException $e)
{
die("failed to find comments");
}
foreach($comments as &$comment)
{
echo $comment;
}
You need parentheses after a function to call it.
$comments = $result->fetchAll;
should be:
$comments = $statement->fetchAll();
Also, the check for if ($result == FALSE) should be before this line. And you can't use mysql_error() if you're using PDO, you should use $statement->errorInfo(). Or you should enable PDO::ERRMODE_EXCEPTION on the connection, and the catch block will be invoked. You should then use $db->errorInfo() in the error message that it prints.

How to get a list of databases?

I was wondering if there's a way in PHP to list all available databases by usage of mysqli. The following works smooth in MySQL (see php docs):
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
$db_list = mysql_list_dbs($link);
while ($row = mysql_fetch_object($db_list)) {
echo $row->Database . "\n";
}
Can I Change:
$db_list = mysql_list_dbs($link); // mysql
Into something like:
$db_list = mysqli_list_dbs($link); // mysqli
If this is not working, would it be possible to convert a created mysqli connection into a regular mysql and continue fetching/querying on the new converted connection?
It doesn't appear as though there's a function available to do this, but you can execute a show databases; query and the rows returned will be the databases available.
EXAMPLE:
Replace this:
$db_list = mysql_list_dbs($link); //mysql
With this:
$db_list = mysqli_query($link, "SHOW DATABASES"); //mysqli
I realize this is an old thread but, searching the 'net still doesn't seem to help. Here's my solution;
$sql="SHOW DATABASES";
$link = mysqli_connect($dbhost,$dbuser,$dbpass) or die ('Error connecting to mysql: ' . mysqli_error($link).'\r\n');
if (!($result=mysqli_query($link,$sql))) {
printf("Error: %s\n", mysqli_error($link));
}
while( $row = mysqli_fetch_row( $result ) ){
if (($row[0]!="information_schema") && ($row[0]!="mysql")) {
echo $row[0]."\r\n";
}
}
Similar to Rick's answer, but this is the way to do it if you prefer to use mysqli in object-orientated fashion:
$mysqli = ... // This object is my equivalent of Rick's $link object.
$sql = "SHOW DATABASES";
$result = $mysqli->query($sql);
if ($result === false) {
throw new Exception("Could not execute query: " . $mysqli->error);
}
$db_names = array();
while($row = $result->fetch_array(MYSQLI_NUM)) { // for each row of the resultset
$db_names[] = $row[0]; // Add db name to $db_names array
}
echo "Database names: " . PHP_EOL . print_r($db_names, TRUE); // display array
Here is a complete and extended solution for the answer, there are some databases that you do not need to read because those databases are system databases and we do not want them to appear on our result set, these system databases differ by the setup you have in your SQL so this solution will help in any kind of situations.
first you have to make database connection in OOP
//error reporting Procedural way
//mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
//error reporting OOP way
$driver = new mysqli_driver();
$driver->report_mode = MYSQLI_REPORT_ALL & MYSQLI_REPORT_STRICT;
$conn = new mysqli("localhost","root","kasun12345");
using Index array of search result
$dbtoSkip = array("information_schema","mysql","performance_schema","sys");
$result = $conn->query("show databases");
while($row = $result->fetch_array(MYSQLI_NUM)){
$print = true;
foreach($dbtoSkip as $key=>$vlue){
if($row[0] == $vlue) {
$print=false;
unset($dbtoSkip[$key]);
}
}
if($print){
echo '<br/>'.$row[0];
}
}
same with Assoc array of search result
$dbtoSkip = array("information_schema","mysql","performance_schema","sys");
$result = $conn->query("show databases");
while($row = $result->fetch_array(MYSQLI_ASSOC)){
$print = true;
foreach($dbtoSkip as $key=>$vlue){
if($row["Database"] == $vlue) {
$print=false;
unset($dbtoSkip[$key]);
}
}
if($print){
echo '<br/>'.$row["Database"];
}
}
same using object of search result
$dbtoSkip = array("information_schema","mysql","performance_schema","sys");
$result = $conn->query("show databases");
while($obj = $result->fetch_object()){
$print = true;
foreach($dbtoSkip as $key=>$vlue){
if( $obj->Database == $vlue) {
$print=false;
unset($dbtoSkip[$key]);
}
}
if($print){
echo '<br/>'. $obj->Database;
}
}

Convert if else to try catch

Can somebody help me in converting the following code written using if-else to try/catch. Also let me know is trycatch needed in this case or if-else is apt
$results = mysql_query($query);
if(mysql_num_rows($results)!=0)
{
while(($result = mysql_fetch_row($results))!=FALSE)
{
$res ="DELETE FROM table1 WHERE id ='".$result['id']."'";
if(mysql_query($res)==false)
{
echo mysql_error();
exit;
}
}
echo $res ="DELETE FROM table2 WHERE id ='".$id."'";
if(mysql_query($res)!==false)
{
header("Location:list.php?m=4");
}
else
{
echo mysql_error();
exit;
}
}
else
{
echo "Error";
}
try...catch only makes any sense if your functions are throwing exceptions. If they don't, there's nothing to catch. I'd start with this as a refactoring:
$results = mysql_query($query);
if (!mysql_num_rows($results)) {
echo 'No results!';
exit;
}
$ids = array();
while (($result = mysql_fetch_row($results)) !== false) {
$ids[] = $result['id'];
}
$ids = array_map('mysql_real_escape_string', $ids);
$query = "DELETE FROM table1 WHERE id IN ('" . join("','", $ids) . "')";
if (!mysql_query($query)) {
echo mysql_error();
exit;
}
$query = "DELETE FROM table2 WHERE id = '$id'";
if (!mysql_query($query)) {
echo mysql_error();
exit;
}
header("Location: list.php?m=4");
exit;
This can still be improved a lot, but it's already an improvement over your spaghetti logic. If you're seriously interested in properly using exceptions, you should first move on to properly using functions for repetitive tasks (like the error, exit parts), then possibly restructure the whole thing into classes and objects, and lastly use exceptions to communicate between the now nested layers. Maybe start using a PHP framework to get a feeling for the whole thing.
Putting exceptions into the above code would be hardly more than a goto, but just for illustrative purposes:
try {
$results = mysql_query($query);
if (!mysql_num_rows($results)) {
throw new Exception('No results!');
}
$ids = array();
while (($result = mysql_fetch_row($results)) !== false) {
$ids[] = $result['id'];
}
$ids = array_map('mysql_real_escape_string', $ids);
$query = "DELETE FROM table1 WHERE id IN ('" . join("','", $ids) . "')";
if (!mysql_query($query)) {
throw new Exception(mysql_error());
}
$query = "DELETE FROM table2 WHERE id = '$id'";
if (!mysql_query($query)) {
throw new Exception(mysql_error());
}
header("Location: list.php?m=4");
exit;
} catch (Exception $e) {
echo 'ERROR: ' . $e->getMessage();
exit;
}
from the sound of it, it seems you think try/catch and if-else as the same behaviour. That is not the case. Try catch is used to prevent an exception from making the application crash or to handle exceptions gracefully, and to perform logging and giving user feedback. If-else (else if) is used to check the internal state of your application, and perform different actions accordingly.
Generally, a try-catch is less efficient than if there is a switch-case or else-if approach to the problem.

Categories