Getting undefined variable: pdo in index.php - php

I am creating a recipe's database and after adding 'add' and 'delete' functionality, the system throws an error:
Notice: Undefined variable: pdo in C:\xampp\htdocs\COMP1321\recipes\index.php on line 52
Fatal error: Uncaught Error: Call to a member function query() on null in C:\xampp\htdocs\COMP1321\recipes\index.php:52 Stack trace: #0 {main} thrown in C:\xampp\htdocs\COMP1321\recipes\index.php on line 52
Index.php
try // selection block
{
$sql = 'SELECT * FROM recipe';
$result = $pdo->query($sql);
}
Databaseconnection.inc.php
<?php
try
{
//new PDO('mysql:host=mysql.cms.gre.ac.uk; dbname=mdb_', '', '');
$pdo = new PDO('mysql:host=localhost; dbname=mdb_recipes', 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('SET NAMES "utf8"');
} catch (PDOException $e) {
$error = 'Unable to connect to database server';
include 'error.html.php';
exit();
}
I have been trying to solve this problem for 3 hours already. Some help would be appreciated!
Full Index.php
<?php
if(isset($_GET['addrecipe'])) {
include 'form.html.php';
exit();
}
//insert block
if (isset($_POST['recipename'])) {
include 'admin/includes/db.inc.php';
try
{
//prepared statement
$sql = 'INSERT INTO recipe SET
recipename = :recipename,
recipedate = CURDATE()';
$s = $pdo->prepare($sql);
$s->bindValue(':recipename', $_POST['recipename']);
$s->execute();
} catch (PDOException $e) {
$error = 'Error adding submitted recipe' . $e->getMessage();
include 'error.html.php';
exit();
}
header('Location: .');
exit();
}
//delete block
if(isset($_GET['deleterecipe']))
{
include '../includes/db.inc.php';
try
{
$sql = 'DELETE FROM recipe WHERE id = :id';
$s = $pdo->prepare($sql);
$s->bindValue(':id', $_POST['id']);
$s->execute();
}
catch (PDOException $e)
{
$error = 'Error deleting recipe' . $e->getMessage();
include 'error.html.php';
exit();
}
header('Location: .');
exit();
}
try // selection block
{
$sql = 'SELECT * FROM recipe';
$result = $pdo->query($sql);
}
catch (PDOException $e) {
$error = 'Error fetching recipes' . $e->getMessage();
include 'error.html.php';
exit();
}
foreach ($result as $row) {
$recipes[] = array(
'id' => $row['id'],
'recipename' => $row['recipename'],
'time' => $row['time'],
'ingredients' => $row['ingredients'],
'recipetext' => $row['recipetext'],
'servings' => $row['servings'],
'nutritionfacts' => $row['nutritionfacts'],
'recipedate' => $row['recipedate'],
'image' => $row['image'],
);
}
include 'recipes.html.php';

Looks like you never include the database connection file.
If $_POST['recipename'] is not set, and $_GET['deleterecipe'] is not set, then when you get to that line, db.inc.php has never been included, so $pdo is not defined.

You need to move your include 'admin/includes/db.inc.php'; line to be right below the form.html.php include.
This will make it available for the entire page as it is required regardless of whether or not you are inserting or deleting a recipe since you need it for the selection block at the bottom.
You only need to include the file once per page and I would normally use require_once() at the top of the file for the DB and other global dependencies like this, rather than trying to include it each place you need it 3+ times per file and then end up unnecessarily including the file and possibly generating warnings or errors. Generally it just makes your code more complicated. It's a shared resource, let it be shared. Or create a singleton to creates or retrieve the PDO instance for you in a standard way so you only have 1 PDO connection instead of potentially multiple per request.

Related

Prevent submission of words already stored in database and echo an alert notifying user that his submission already exists

Everything works with my site and database.
I've submitted a snippet of code where I think the PHP to prevent duplicate submissions needs to be inserted.
{
$pdo = new PDO('mysql:host=localhost;dbname=', '', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('SET NAMES "utf8"');
}
catch (PDOException $e)
{
$error = 'Unable to connect to the database server.';
include 'error.html.php';
exit();
}
if (isset($_POST['profanetext']))
{
try
{
$sql = 'INSERT INTO profane SET
profanetext = :profanetext,
profanedate = CURDATE()';
$s = $pdo->prepare($sql);
$s->bindValue(':profanetext', $_POST['profanetext']);
$s->execute();
}
catch (PDOException $e)
{
$error = 'Error adding submitted profanity: ' . $e->getMessage();
include 'error.html.php';
exit();
}
header('Location: .');
exit();
}
You do a select where query to see if the value exist first.
Also you can make the actual profane text database column UNIQUE. This will prevent insertion of duplicate value and will produce an db error if trying to do so.
Well, I figured out a way to make it work. After changing the profanetext column from TEXT type to VARCHAR(255) -- which allowed me to make the column UNIQUE -- I added this to my php to make the db error message display as an alert:
catch (PDOException $e)
{
$error = 'Error adding submitted profanity: ' . $e->getMessage();
echo '<script language="javascript">';
echo 'alert("That profanity has already been submitted")';
echo '</script>';
exit();
}

PHP PDO - There is no active transaction

I am having problem with transactions in php script. I would like to make multiply queries and be able to recall them all, if at least one of them fails. Below you can find a simple example of the script I am using:
$tags_input = array(6,4,5);
$conn = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8',
DB_USER, DB_PASSW, array(
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));
$conn->beginTransaction();
$sql = "INSERT INTO projects (id, pr_id, enabled) VALUES ( :val0, :val1, :val2)";
$stmt = $conn->prepare($sql);
if(count($tags_input)>0){
for($i = 0;$i<count($tags_input);$i++){
$stmt->bindValue(':val0', 57);
$stmt->bindValue(':val1', $tags_input[$i]);
$stmt->bindValue(':val2', 'Y');
$result = $stmt->execute();
}
}
$res1 = $conn->commit();
$conn->rollBack();
Now, this example generates an error:
Uncaught exception 'PDOException' with message 'There is no active
transaction'
If I erase the line $conn->rollBack();, the error disappears. Therefore I cannot understand, why pdo object can't see open transaction (begintransaction and commit do not generate any errors). I also tried putting rollBack() inside the transaction, but made no difference. I was still getting an error 'There is no active transaction'.
I am running PHP 5.6 and Mysql tables on InnoDB.
Wrap your transaction code inside a try-catch statement.
//try {
$tags_input = array(6,4,5);
$conn = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8',
DB_USER, DB_PASSW, array(
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));
} catch (Exception $e) {
die("Unable to connect: " . $e->getMessage());
}
try {
$conn->beginTransaction();
$sql = "INSERT INTO projects (id, pr_id, enabled) VALUES ( :val0, :val1, :val2)";
$stmt = $conn->prepare($sql);
if(count($tags_input)>0){
for($i = 0;$i<count($tags_input);$i++){
$stmt->bindValue(':val0', 57);
$stmt->bindValue(':val1', $tags_input[$i]);
$stmt->bindValue(':val2', 'Y');
$result = $stmt->execute();
}
}
$res1 = $conn->commit();
} catch (Exception $e) {
$conn->rollBack();
echo "Failed: " . $e->getMessage();
}
EDIT
A really well-based and straight-forward explanation of the answer was provided by Richard as a comment.
The reason you got error is because you were trying to close a transaction when it was already closed. beginTransaction opens one, and EITHER rollBack OR commit closes it. You have to avoid doing BOTH actions, meaning commit/rollback, for a single beginTransaction statement, or you'll get an error. The above try/catch code ensures that only one closing statement is executed.
Peter and Richards answers are already correct, but there is one little mistake in the code from the transaction structure (and i can't add a comment).
The $connection->beginTransaction() must be outside of the try-catch block. When you're start the beginTransaction() in the try-block and your Database Operations throws an exception, the catch-block doesn't know something from an active transaction. So, you get the same error:
"There is no active transaction".
So the structure should be as well:
Get the Connection.
Start the Transaction with $connection->beginTransaction()
Open the try-catch block.
The try-block contains the $connection->commit() after DB Operations.
The catch-block contains the $connection->rollback() before a throw Exception.
So your code should look like this:
$tags_input = array(6,4,5);
$conn = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8',
DB_USER, DB_PASSW, array(
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));
} catch (Exception $e) {
die("Unable to connect: " . $e->getMessage());
}
//Begin Transaction
$conn->beginTransaction();
try {
$sql = "INSERT INTO projects (id, pr_id, enabled) VALUES ( :val0, :val1, :val2)";
$stmt = $conn->prepare($sql);
if(count($tags_input)>0){
for($i = 0;$i<count($tags_input);$i++){
$stmt->bindValue(':val0', 57);
$stmt->bindValue(':val1', $tags_input[$i]);
$stmt->bindValue(':val2', 'Y');
$result = $stmt->execute();
}
}
$res1 = $conn->commit();
} catch (Exception $e) {
$conn->rollBack();
echo "Failed: " . $e->getMessage();
}

Cannot update MySQL using PDO::PARAM_LOB on a serialized array.No error is being thrown

I am running a test to serialize an array using PHP, in order to update my database I use the PDO extension. I have tried changing the code a bit, but there is no error to be catched by the try block. I have other functions where I successfully updated other tables, the only diferense here is the PDO::PARAM_LOB line. Any help is greatly appreciated.
<?php
require("database.php");
try {
$test = array('15525');
array_push($test, '12345');
var_dump($test);
$stest = serialize($test);
var_dump($stest) ;
$dapartmentToUpdate = 3;
$result = $db->prepare("
UPDATE departments_employees
SET employee_id = ?
WHERE department_id = ?
");
$result ->bindParam(1,$stest,PDO::PARAM_LOB);
$result ->bindParam(2,$departmentToUpdate,PDO::PARAM_INT);
$result -> execute();
} catch (Exception $e) {
echo "Could not write to database for some odd reason";
exit;
}
?>
I must add that by taking the query directly to SQL makes it run just fine, so I must be missing something. The statement on SQL looks like
UPDATE departments_employees
SET employee_id = 'a:2:{i:0;s:5:"15525";i:1;s:5:"12345";}'
WHERE department_id = 3
config.php are just some environment constants, user, password and some other private stuff, database.php looks like this:
<?php
require_once ('config.php');
try {
$db = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME .";port=" . DB_PORT,DB_USER,DB_PASS);
$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
$db->exec("SET NAMES 'utf8'");
} catch (Exception $e) {
echo "Could not connect to the database.";
exit;
}

PDO Can't catch exception which is thrown

Ok so I can't catch the exeption:
require_once 'config/config.php';
try {
$dbh = new PDO('mysql:host='.DB_HOST.';dbname='.DB_DATABASE, DB_USER, DB_PASS,array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));
} catch (PDOException $e) {
print "Unable to connect!: " . $e->getMessage() . BR;
die();
}
try {
$stmt = $dbh->prepare("SELECT id,email FROM no_table ORDER BY id DESC LIMIT 5");
$stmt->execute();
$stmt->bindColumn(1, $id, PDO::PARAM_INT);
$stmt->bindColumn('email', $email, PDO::PARAM_STR);
while ($row = $stmt->fetch(PDO::FETCH_BOUND)) {
echo $id . "\t" . $email . BR;
}
} catch (PDOException $e) {
echo "Failed: " . $e->getMessage();
}
Ok I connect I have an error in the syntax (there isn't any no_table) it throws the exception but i can't catch it. In browser I see this:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42S02]:
Base table or view not found: 1146 Table 'no_table' doesn't exist' in 'somepath'
PDOStatement->execute() #1 {main} thrown in some.php on line 15
The exception is thrown and i can't catch it, but if I put another try catch between $stmt->execute(); it catches it.
My php version 5.3.14
Have you been using namespaced classes in this project maybe?
If so, please try to use
\PDOException
instead of
PDOException
in your "catch" statement.
I just got similar problem and this move helped.

PDO connection try catch include

I'm new to PDO and I wanna do it right from the beginning - I'm going to replace my old mysql_ functions on a site.
Have I got it right?:
Should I put the connection code in a try/catch and save it to a file, and include it on top of the page. Then put the queries in try/catch as well.
Or:
Should I put the connection code in a file and include it in the in the top of the try/catch statement above the query?
ver1:
include('pdo.php'); // try/catch in file
try {
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
$stmt->execute(array('id' => $id));
while($row = $stmt->fetch()) {
print_r($row);
}
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
ver2:
try {
include('pdo.php'); // no try/catch in file
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
$stmt->execute(array('id' => $id));
while($row = $stmt->fetch()) {
print_r($row);
}
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
Or should I put the try/catch in both places?
You should do both and even more :
Set an error handler that displays a message to the user and stops the PHP (see set_error_handler)
When you initiate the connexion, add a try/catch and throw an error if you catch an exception. Your website won't run without database connection i guess.
Do a try/catch around your queries to recover gracefully from error (when you can)

Categories