I am currently working on a job claiming system and currently struggling with users being able to claim a piece of available work in my jobs table.
When replacing parts of the update query called by the update button it seems to be the order_id which is not being passed to the query properly from the original query.
I am very new to this so any other comments or direction would be very helpful
<?php
session_start();
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "dbname";
echo "You are currently logged in as " . $_SESSION["login_user"] . ".<br>";
echo "<table style='border: solid 1px black;'>";
echo "<tr><th>Order ID</th><th>Status</th><th>Service</th><th>Document Type</th><th>Word Count</th><th>Other Considerations</th><th>Date Received</th><th>Claim</th></tr>";
class TableRows extends RecursiveIteratorIterator {
function __construct($it) {
parent::__construct($it, self::LEAVES_ONLY);
}
function current() {
return "<td style='width:150px;border:1px solid black;'>" . parent::current(). "</td>";
}
function beginChildren() {
echo "<tr>";
}
function endChildren() {
echo '<td><form id="view_admin" method="post">
<input type="submit" name="username" value="Accept"></td>';
echo "</tr>" . "\n";
}
}
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare("SELECT `Order_ID`,`Status`,`Service`,`Document_Type`,`Word_Count`,`Other_Considerations`,`Receive_Date`
FROM `PRW_JOBS` where `staff_username` is null");
$stmt->execute();
// set the resulting array to associative
$result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
foreach(new TableRows(new RecursiveArrayIterator($stmt->fetchAll())) as $k=>$v) {
echo $v;
}
}
catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
echo "</table>";
if($_POST && isset($_POST['username'])){
$sql = "update `PRW_JOBS` set `staff_username` = :staff_username where `Order_ID`= :Order_ID and `staff_username` is NULL";
$stm = $conn->prepare($sql);
$stm->bindParam(':Order_ID', $result['Order_ID'], PDO::PARAM_INT);
$stm->bindParam(':staff_username', $_SESSION["login_user"], PDO::PARAM_STR);
$stm->execute();
}
$conn = null;
?>
Your problem arises because you're using setFetchMode() in a wrong way. setFetchMode() returns a boolean (true or false), not a $result. fetchAll() returns a $result! So, instead of using this:
$result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
use this:
$assigned = $stmt->setFetchMode(PDO::FETCH_ASSOC);
$result = $stmt->fetchAll();
Then it will work properly.
I'd recommend you to use them like this:
$fetchedData = $selectStatement->fetchAll(PDO::FETCH_ASSOC);
I also recommend you to ALWAYS look into the php.net docs for each function you are using: parameters list, return value and especially which kind of errors/exceptions it throws. Therefore: always use exception handling. As you already did. But for example, a PDO::prepare function can not only throw a 'PDOexception', but it can also return false. This case must also be covered. See this: PDO::prepare (the "Return values" part).
I prepared for you a complete php solution for your question code. I did it to show you how to separate HTML output from php and to show you how to cover ALL data access functionality and the exception handling.
There are four pages: the main page (index.php), the TableRows.php containing your table rows class, a DataAccess.php for data access and a Printer.php with printing function(s).
I recommend you to ALWAYS save a class in its own php page, which has the same name as the class name.
I used functions in those files. But you can, of course, use OOP, e.g classes, instead. For example a Connection class to handle all db connectivity, a Printer class for printing functionality, etc.
Notice how I "relaxed" the html code and the handling of the whole php in one place. You see how slim is the html code now?
And notice that I don't bring functions like fetchAll() around the page. I call all data access functions in one place, I fetch the data and with THIS $fetchedData I can do what I want around the page. It's safe to close a db connection as soon as possible in code.
Nota bene, for development, not for production (!): if you think that you need to see the whole, detailed exceptions instead of your custom exception messages, just replace these:
printData($pdoException->getMessage());
printData($exception->getMessage());
with these:
printData($pdoException);
printData($exception);
Good luck!
Printer.php
<?php
/**
* Print data on screen in a preformatted way.
*
* #param mixed $data Data to print.
* #return void
*/
function printData($data) {
echo '<pre>' . print_r($data, true) . '</pre>';
}
DataAccess.php
<?php
/**
* Create a new db connection.
*
* #param string $dsn Connection DSN.
* #param string $username Username.
* #param string $password Password.
* #param array $options [optional] Driver options.
* #return PDO Db connection.
*/
function createConnection($dsn, $username, $password, $options = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_PERSISTENT => true,
)) {
$connection = new PDO($dsn, $username, $password);
foreach ($options as $key => $value) {
$connection->setAttribute($key, $value);
}
return $connection;
}
/**
* Close a db connection.
*
* #param PDO $connection Db connection.
* #return void
*/
function closeConnection($connection) {
$connection = NULL;
}
/**
* Get the data type of a binding value.
*
* #param mixed $value Binding value.
* #return mixed Data type of the binding value.
*/
function getInputParameterDataType($value) {
$dataType = PDO::PARAM_STR;
if (is_int($value)) {
$dataType = PDO::PARAM_INT;
} elseif (is_bool($value)) {
$dataType = PDO::PARAM_BOOL;
}
return $dataType;
}
TableRows.php:
<?php
use RecursiveIteratorIterator;
/*
* Table rows class.
*/
/**
* Table rows class.
*
*/
class TableRows extends RecursiveIteratorIterator {
function __construct($iterator) {
parent::__construct($iterator, self::LEAVES_ONLY);
}
function current() {
return "<td style='width:150px;border:1px solid black;'>" . parent::current() . "</td>";
}
function beginChildren() {
echo "<tr>";
}
function endChildren() {
echo '<td>';
echo '<form id="view_admin" method="post">';
echo '<input type="submit" name="username" value="Accept">';
echo '</td>';
echo '</tr>' . '\n';
}
}
index.php:
<?php
include 'TableRows.php';
include 'DataAccess.php';
include 'Printer.php';
session_start();
$servername = 'localhost';
$dbname = 'dbname';
$username = 'username';
$password = 'password';
$loginUser = isset($_SESSION['login_user']) ? $_SESSION['login_user'] : '';
try {
// Create db connection.
$connection = createConnection('mysql:host=' . $servername . ';dbname=' . $dbname, $username, $password);
// Define sql statement.
$sql = 'SELECT
`Order_ID`,`Status`,`Service`,`Document_Type`,
`Word_Count`,`Other_Considerations`,`Receive_Date`
FROM `PRW_JOBS`
WHERE `staff_username` IS NULL';
// Prepare and check sql statement (returns PDO statement).
$selectStatement = $connection->prepare($sql);
if (!$selectStatement) {
throw new Exception('The SQL statement can not be prepared!');
}
// Execute and check PDO statement.
if (!$selectStatement->execute()) {
throw new Exception('The PDO statement can not be executed!');
}
// Fetch all data.
$fetchedData = $selectStatement->fetchAll(PDO::FETCH_ASSOC);
// Get rows collection.
$tableRows = new TableRows(new RecursiveArrayIterator($fetchedData));
// Upon form submission by 'Accept' button.
if (isset($_POST['username'])) {
// Define sql statement.
$sql = 'UPDATE `PRW_JOBS`
SET `staff_username` = :staff_username
WHERE `Order_ID` = :Order_ID AND `staff_username` IS NULL';
// Prepare and check sql statement (returns PDO statement).
$updateStatement = $connection->prepare($sql);
if (!$updateStatement) {
throw new Exception('The SQL statement can not be prepared!');
}
// Bind values to sql statement parameters.
$updateStatement->bindValue(':Order_ID', $fetchedData['Order_ID'], getInputParameterDataType($fetchedData['Order_ID']));
$updateStatement->bindValue(':staff_username', $loginUser, getInputParameterDataType($loginUser));
// Execute and check PDO statement.
if (!$updateStatement->execute()) {
throw new Exception('The PDO statement can not be executed!');
}
}
closeConnection($connection);
} catch (PDOException $pdoException) {
printData($pdoException->getMessage());
exit();
} catch (Exception $exception) {
printData($exception->getMessage());
exit();
}
?>
<span>
You are currently logged in as <?php echo $loginUser; ?>
</span>
<br>
<table style="border: solid 1px black;">
<tr>
<th>Order ID</th>
<th>Status</th>
<th>Service</th>
<th>Document Type</th>
<th>Word Count</th>
<th>Other Considerations</th>
<th>Date Received</th>
<th>Claim</th>
</tr>
<?php
foreach ($tableRows as $row) {
echo $row;
}
?>
</table>
Related
I would like to know how can I insert multiple values in an array via prepared statements. I've looked at these two (this question and this other one ) questions but they don't seem to do what I'm trying. This is what I have:
$stmt = $this->dbh->prepare("INSERT INTO
t_virtuemart_categories_en_gb
(category_name, virtuemart_category_id)
VALUES
(:categoryName, :categoryId)
;");
foreach($this->values as $insertData){
$categoryName = $insertData['categoryName'];
$categoryId = $insertData['categoryId'];
$stmt->bindParam(':categoryName', $categoryName);
$stmt->bindParam(':categoryId', $categoryId);
$stmt->execute();
}
I tried placing the prepare line inside the foreach loop and outside, but it only adds the first key in the array, and I don't understand why.
This is my Connection.php file:
<?php
$hostname = 'localhost';
$username = 'root';
$password = '';
function connectDB ($hostname, $username, $password){
$dbh = new PDO("mysql:host=$hostname;dbname=test", $username, $password);
return $dbh;
}
try {
$dbh = connectDB ($hostname, $username, $password);
} catch(PDOException $e) {
echo $e->getMessage();
}
And my Import.php file:
<?php
class Import{
public function __construct($dbh, $values) {
$this->dbh = $dbh;
$this->values = $values;
}
public function importData() {
$stmt = $this->dbh->prepare("INSERT INTO
t_virtuemart_categories_en_gb
(category_name, virtuemart_category_id)
VALUES
(:categoryName, :categoryId)
;");
foreach($this->values as $insertData){
$categoryName = $insertData['categoryName'];
$categoryId = $insertData['categoryId'];
$stmt->bindParam(':categoryName', $categoryName);
$stmt->bindParam(':categoryId', $categoryId);
$stmt->execute();
}
}
}
Working principle:
Use only one INSERT sql statement to add multiple records, defined by your values pairs. In order to achieve this you have to build the corresponding sql statement in the form
INSERT INTO [table-name] ([col1],[col2],[col3],...) VALUES (:[col1],:[col2],:[col3],...), (:[col1],:[col2],:[col3],...), ...
by iterating through your values array.
Notes:
I hope you'll understand all. I commented as much as I could. I
didn't test it, but it should work. Maybe an answer I wrote a
short time ago will give you further ideas regarding structuring of
data access classes/functions as well.
Never use ";" at the end of the sql statements when you define them in PHP.
Never use one input marker to bind multiple values. For each value to bind use a unique named input marker.
Good luck.
Connection.php
<?php
$hostname = 'localhost';
$username = 'root';
$password = '';
$port = 3306;
try {
// Create a PDO instance as db connection to a MySQL db.
$connection = new PDO(
'mysql:host='. $hostname .';port='.$port.';dbname=test'
, $username
, $password
);
// Assign the driver options to the db connection.
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
$connection->setAttribute(PDO::ATTR_PERSISTENT, TRUE);
} catch (PDOException $exc) {
echo $exc->getMessage();
exit();
} catch (Exception $exc) {
echo $exc->getMessage();
exit();
}
Import.php:
<?php
class Import {
/**
* PDO instance as db connection.
*
* #var PDO
*/
private $connection;
/**
*
* #param PDO $connection PDO instance as db connection.
* #param array $values [optional] Values list.
*/
public function __construct(PDO $connection, array $values = array()) {
$this->connection = $connection;
$this->values = $values;
}
/**
* Import data.
*
* #return int Last insert id.
* #throws PDOException
* #throws UnexpectedValueException
* #throws Exception
*/
public function importData() {
/*
* Values clauses list. Each item will be
* later added to the sql statement.
*
* array(
* 0 => '(:categoryName0, :categoryId0)',
* 1 => '(:categoryName1, :categoryId1)',
* 2 => '(:categoryName2, :categoryId2)',
* )
*/
$valuesClauses = array();
/*
* The list of the input parameters to be
* bound to the prepared statement.
*
* array(
* :categoryName0 => value-of-it,
* :categoryId0 => value-of-it,
* :categoryName1 => value-of-it,
* :categoryId1 => value-of-it,
* :categoryName2 => value-of-it,
* :categoryId2 => value-of-it,
* )
*/
$bindings = array();
/*
* 1) Build a values clause part for each array item,
* like '(:categoryName0, :categoryId0)', and
* append it to the values clauses list.
*
* 2) Append each value of each item to the input
* parameter list.
*/
foreach ($this->values as $key => $item) {
$categoryName = $item['categoryName'];
$categoryId = $item['categoryId'];
// Append to values clauses list.
$valuesClauses[] = sprintf(
'(:categoryName%s, :categoryId%s)'
, $key
, $key
);
// Append to input parameters list.
$bindings[':categoryName' . $key] = $categoryName;
$bindings[':categoryId' . $key] = $categoryId;
}
/*
* Build the sql statement in the form:
* INSERT INTO [table-name] ([col1],[col2],[col3]) VALUES
* (:[col1],:[col2],:[col3]), (:[col1],:[col2],:[col3]), ...
*/
$sql = sprintf('INSERT INTO t_virtuemart_categories_en_gb (
category_name,
virtuemart_category_id
) VALUES %s'
, implode(',', $valuesClauses)
);
try {
// Prepare the sql statement.
$statement = $this->connection->prepare($sql);
// Validate the preparing of the sql statement.
if (!$statement) {
throw new UnexpectedValueException('The sql statement could not be prepared!');
}
/*
* Bind the input parameters to the prepared statement
* and validate the binding of the input parameters.
*
* -----------------------------------------------------------------------------------
* Unlike PDOStatement::bindValue(), when using PDOStatement::bindParam() the variable
* is bound as a reference and will only be evaluated at the time that
* PDOStatement::execute() is called.
* -----------------------------------------------------------------------------------
*/
foreach ($bindings as $key => $value) {
// Read the name of the input parameter.
$inputParameterName = is_int($key) ? ($key + 1) : (':' . ltrim($key, ':'));
// Read the data type of the input parameter.
if (is_int($value)) {
$inputParameterDataType = PDO::PARAM_INT;
} elseif (is_bool($value)) {
$inputParameterDataType = PDO::PARAM_BOOL;
} else {
$inputParameterDataType = PDO::PARAM_STR;
}
// Bind the input parameter to the prepared statement.
$bound = $statement->bindValue($inputParameterName, $value, $inputParameterDataType);
// Validate the binding.
if (!$bound) {
throw new UnexpectedValueException('An input parameter could not be bound!');
}
}
// Execute the prepared statement.
$executed = $statement->execute();
// Validate the prepared statement execution.
if (!$executed) {
throw new UnexpectedValueException('The prepared statement could not be executed!');
}
/*
* Get the id of the last inserted row.
*/
$lastInsertId = $this->connection->lastInsertId();
} catch (PDOException $exc) {
echo $exc->getMessage();
// Only in development phase !!!
// echo '<pre>' . print_r($exc, TRUE) . '</pre>';
exit();
} catch (Exception $exc) {
echo $exc->getMessage();
// Only in development phase !!!
// echo '<pre>' . print_r($exc, TRUE) . '</pre>';
exit();
}
return $lastInsertId;
}
}
I think the statements have to be prepared and bound separately for each iteration:
if($stmt = $this->dbh->prepare("INSERT INTO t_virtuemart_categories_en_gb (category_name, virtuemart_category_id) VALUES (:categoryName, :categoryId);")){
foreach($this->values as &$insertData){
$stmt->bindParam(':categoryName', $insertData['categoryName']);
$stmt->bindParam(':categoryId', $insertData['categoryId']);
$stmt->execute();
$stmt->close();
}
}
I would suggest this, using a $dbh = mysqli_connect():
<?php
class Import{
public function __construct($dbh, $values) {
$this->dbh = $dbh;
$this->values = $values;
}
public function importData() {
$stmt = $this->dbh->prepare("INSERT INTO t_virtuemart_categories_en_gb
(category_name, virtuemart_category_id)
VALUES
(?, ?)");
$catetoryName = ''; $categoryId = '';
$stmt->bind_param('ss', $categoryName, $categoryId);
foreach($this->values as $insertData){
$categoryName = $insertData['categoryName'];
$categoryId = $insertData['categoryId'];
$stmt->execute();
}
}
}
In this way you create a reference and bind that variable to the execution of the prepared statement.
You should be careful about it when passing an array, the trick is commented in the php.net page ( http://php.net/manual/it/mysqli.prepare.php )
A code that work is:
$typestring = 'sss'; //as many as required: calc those
$stmt = $dbconni->prepare($ansqlstring);
$refs = [$typestring];
// if $source is an array of array [ [f1,f2,...], [f1,f2,...], ...]
foreach($source as $data) {
if (count($refs)==1) {
foreach ($data as $k => $v) {
$refs[] = &$data[$k];
}
$ref = new \ReflectionClass('mysqli_stmt');
$method = $ref->getMethod("bind_param");
$method->invokeArgs($stmt, $refs);
$r = $stmt->execute();
} else {
// references are maintained: no needs to bind_param again
foreach ($data as $k => $v) {
$refs[$k+1] = $v;
}
$r = $stmt->execute();
}
}
this spare resources and is more performant, but you have to make benchmark to be sure about my words.
this is one of the case where prepared statement make sense, see
https://joshduff.com/2011-05-10-why-you-should-not-be-using-mysqli-prepare.md
Normally PDO emulate prepared statement, see PDO::ATTR_EMULATE_PREPARES
EDIT: specify it is using mysqli, and correct the code.
I am having some problem when retrieving data from my database using jquery.
This is my client.js
function get_sede_data(client) {
$('#client-detail-co').load('client.php?name='+client);
}
This is my client.php file
<?php
$name = $_GET['name'];
$sql_name = "select * from client where c_name = $name";
$re_sql_name = mysqli($con, $sql_name);
if (mysqli_num_rows($re_sql_name) > 0) {
while ($row = mysqli_fetch_assoc($re_sql_name)) {
echo
"<h1>Client details: {$row['c_name']}</h1>";
}
} else {
echo "ERROR" . mysqli_error($con);
}
mysqli_close($conexion);
?>
This normally works with clients with only one name (ex: George) but with a client with two names (ex: Mary Ann) it doesnt work. Any idea why it's not retreiving names with spaces?
To fix your issue, you need to enclose your variable with singlequotes, as it's a string and not an integer.
$name = $_GET['name'];
$sql_name = "select * from `client` where `c_name`='$name'";
$re_sql_name = mysqli($con, $sql_name);
if(mysqli_num_rows($re_sql_name) > 0) {
while($row = mysqli_fetch_assoc($re_sql_name)) {
echo "<h1>Client details: {$row['c_name']}</h1>";
}
} else {
echo "ERROR" . mysqli_error($con);
}
//you had this as "conexion" but you used "con" above, so I changed this to "con"
mysqli_close($con);
You should also convert to using prepared statements:
MySQLi Prepared Statements
$name = $_GET['name'];
/* prepare statement */
if ($stmt = $mysqli->prepare("select `c_name` from `client` where `c_name`= ?")) {
/* bind parameters for markers */
$stmt->bind_param("s", $name);
/* execute query */
$stmt->execute();
/* bind variables to prepared statement */
$stmt->bind_result($c_name);
/* if num_rows > 0 then fetch values */
if($stmt->num_rows > 0) {
while ($stmt->fetch()) {
echo "<h1>Client details: {$c_name}</h1>";
}
} else {
//error reporting
}
/* close statement */
$stmt->close();
}
/* close connection */
$mysqli->close();
PDO Prepared Statements
This is what I personally recommend, as I find it easier than mysqli.
First, you're connection handler needs to be changed to this:
$host = 'localhost';
$db = '';
$user = '';
$pass = '';
$charset = 'utf8';
$dsn = "mysql:host={$host};dbname={$db};charset={$charset}";
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = new PDO($dsn, $user, $pass, $opt);
Note: We edit some of the default database connection stuff here, most notibly ATTR_EMULATE_PREPARES. When this is true, prepared statements are emulated which could be only as safe as string concatenation
Then, your query will look like this:
stmt = $pdo->prepare("SELECT * FROM `client` WHERE `c_name`= ?");
$stmt->execute([$name]);
$results = $stmt->fetchAll();
if($results > 0) {
foreach($results as $result) {
echo "<h1>Client details: {$result['c_name']}</h1>";
}
} else {
//error reporting
}
I'm tinkering with a class that 'should' allow me to easily execute a fetchall query and display the results within a foreach statement. I assume all is working correctly as I have no errors. As for the foreach - this must be the problem? How would I foreach the results gained from the $connect->query()? I'm new to using any database OOP framework in my functions so I could be along the wrong lines completely.
<?
error_reporting(1);
class dbconnect {
private $host;
private $database;
private $username;
private $password;
private $pdo;
private $error;
public function __construct() {
$this->host = "localhost"; // Host
$this->database = "images"; // Database Name
$this->username = "*"; // Username
$this->password = "*"; // Password
$options = array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
);
try {
$this->pdo = new PDO("mysql:host={$this->host};dbname={$this->dbname};charset=utf8", $this->username, $this->password, $options);
}
catch(PDOException $e) {
$this->error = $e->getMessage();
}
}
public function query($query) {
try {
$stmt = $this->pdo->prepare($query);
$stmt->execute();
} catch(PDOException $ex) {
die("Failed to run query: " . $ex->getMessage());
}
$rows = $stmt->fetchAll();
return $rows;
}
}
$connect = new dbconnect;
$rows = $connect->query("select * from photos");
foreach($rows as $row):
print $row['id'];
endforeach;
?>
The $rows variable you're declaring inside query is not accessible to the outside, it is local to that function. Most likely, you simply want to return those results to the caller:
$rows = $stmt->fetchAll();
return $rows; // return value from function...
and have the caller capture that return value in its own variable:
$rows = $connect->query("select * from images"); // ... is received by caller
foreach($rows as $row):
Also check out dougjore's answer, you're mixing $this->stmt and $stmt inside your query method.
Pretty sure you aren't ever actually executing the query:
$this->stmt = $this->pdo->prepare($query);
$stmt->execute();
I believe (I could be wrong, I'm rather new to PDO myself and I haven't built a class for it), that you need to say $this->stmt->execute();
You could do
//PDO::FETCH_ASSOC: returns an array indexed by column name as returned in your result set
$this->stmt = $this->pdo->prepare($query);
$this->stmt->execute();
while ($result = $this->stmt->fetch(PDO::FETCH_ASSOC))
{
//do something with the result
}
Have a look here for more options to fetch PDO query results:
http://php.net/manual/en/pdostatement.fetch.php
$connect = new dbconnect;
$sql="select * from photos";
$stmt=$connect->pdo->prepare($sql);
$stmt->execute();
$result=$stmt->fetch(PDO::FETCH_ASSOC);
foreach($result as $key => $value) {
echo $key . "-" . $value . "<br/>";
}
I know I can close a PDO SQL connection setting the handler to NULL.
But if I don't do that, does PHP close the connection at the end of the script?
Fore example, can I use
$db = new PDO('sqlite:db.sqlite');
/* Code */
if ($cond1) { exit; }
/* More code */
if ($cond2) { exit; }
/* ... */
$db = NULL;
/* Code not related to the database */
... or should I use this:
$db = new PDO('sqlite:db.sqlite');
/* Code */
if ($cond1) {
$db = NULL;
exit;
}
/* More code */
if ($cond2) {
$db = NULL;
exit;
}
/* ... */
$db = NULL;
/* Code not related to the database */
According to the docs:
The connection remains active for the lifetime of that PDO object. To
close the connection, you need to destroy the object by ensuring that
all remaining references to it are deleted--you do this by assigning
NULL to the variable that holds the object. If you don't do this
explicitly, PHP will automatically close the connection when your
script ends.
EXAMPLE.
This is your dbc class
<?php
class dbc {
public $dbserver = 'server';
public $dbusername = 'user';
public $dbpassword = 'pass';
public $dbname = 'db';
function openDb() {
try {
$db = new PDO('mysql:host=' . $this->dbserver . ';dbname=' . $this->dbname . ';charset=utf8', '' . $this->dbusername . '', '' . $this->dbpassword . '');
} catch (PDOException $e) {
die("error, please try again");
}
return $db;
}
function getAllData($qty) {
//prepared query to prevent SQL injections
$query = "select * from TABLE where qty = ?";
$stmt = $this->openDb()->prepare($query);
$stmt->bindValue(1, $qty, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $rows;
}
?>
your PHP page:
<?php
require "dbc.php";
$getList = $db->getAllData(25);
foreach ($getList as $key=> $row) {
echo $row['columnName'] .' key: '. $key;
}
Your connection will be closed as soon as the results are returned
According to the docs When you call exit:
Terminates execution of the script. Shutdown functions and object destructors will always be executed even if exit is called.
This means your PDO connection will be closed. It's always good practice to close it yourself though.
New to PDO. Here is my function. We are connected to the database and everything is working but this function when called is killing off the rest of PHP to be executed. Obviously something is wrong with it.
$dbh = new PDO("mysql:host=$host;dbname=$database", $username, $password);
global $dbh;
/*** set the error reporting attribute ***/
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
function selectall($table){
$stmt = $dbh->prepare("SELECT * FROM :table");
$stmt->bindParam(':table', $table, PDO::PARAM_STR,20);
$stmt->execute();
$result = $stmt->fetchAll();
return $result;
}
Called on a page like this:
<?php $telephones = selectall('telephone'); foreach($telephones as $telephones) { echo $telephone['title'].', '; } ?>
/// EDIT - I have tried all of your methods and the function is still breaking when called on the page. Here is the entire code. Slightly modified for testing purposes.
try {
$dbh = new PDO("mysql:host=$host;dbname=$database", $username, $password);
/*** set the error reporting attribute ***/
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM system";
foreach ($dbh->query($sql) as $row)
{
$url = $row['url'];
$election = $row['election'];
$election_date = $row['election_date'];
$sitename = $row['sitename'];
}
//FUNCTION
function selectall($table){
global $dbh;
$sql = "SELECT * FROM telephone";
foreach ($dbh->query($sql) as $row){
print $row['title'] .' - '. $row['name'] . '<br />';
}
}
/** close database connections **/
$dbh = null;
}
catch(PDOException $e) {
echo $e->getMessage();
}
The code outside the function ie. the one reflecting the table system is working perfectly Yet the one inside the function when called as a function later is killing off everything after it is called and is not executing.
Your second line generates a fatal error, when you're trying to use an undefined variable ($dbh) as an object.
You need to import it from the global scope like this:
global $dbh;
or pass it as a parameter to the function.
After you fix this, your code still won't work, as you cannot use parameters for identifiers (table or column names, or even in limit and offset). Unfortunately you have to resort to string concatenation there.
I think the problem is: $telephones as $telephones
Try this:
$telephones = selectall('telephone'); foreach($telephones as $telephone) { echo $telephone['title'].', '; }