Another connection within the try - php

Good afternoon everyone, I have a doubt.
I have a SELECT with PDO. More must be done within another SELECT WHILE to get data for that select, giving it more
Error (Error: There Is Already an active transaction).
If anyone can help me be grateful.
Example code.
try{
$this->conex->beginTransaction();
$query = $this->conex->prepare("SELECT idUser FROM usuario WHERE id = :id ORDER BY data DESC LIMIT $pagin, $paginaF");
$query->bindParam(":id", $ID, PDO::PARAM_INT, 20);
$query->execute();
while ($lista = $query->fetch()){
$idUser = $lista['idUser'];
echo "<div id='avatar'>"box::avatar($idUser)."</div>"
}
//Here he works out of WHILE. Inside it does not work...
echo box::avatar($idUser);
$this->conex->commit();
}catch (PDOException $ex) {
echo "Erro: " . $ex->getMessage();
}
public function avatar($idUser){
$idUser = (int) $idUser;
$query = $this->conex->prepare("SELECT avatar FROM login WHERE id = :id LIMIT 1");
$query->bindParam(":id", $idUser, PDO::PARAM_INT, 20);
$query->execute();
while ($avatar = $query->fetch()){
$avatar = $avatar['avatar'];
}
return $avatar;
}

You have to close the cursor before calling for a new transaction.
Besides, may I ask why are you creating transactions since you're only doing simple *select*s?

Nested Transactions are not possible (as mentioned by the error message). In the first line, you start one transaction. Within the loop, you call avatar(), that starts another transaction, which fails, because there is already one.
However, for SELECT-Queries you dont need transactions at all. Just omit it.
You may also think about JOIN, so you can handle all in just one Query (and then transactions are really useless).

May not be an answer to the problem for now but this line :
echo "<div id="avatar">".$box = box::avatar($id)."</div>"
is full of errors.
" aren't escaped.
no ; at the end.
You're trying to give a value to a variable inside an echo. This'll throw an error.
If you don't use the avatar() function elsewhere, you can do :
try{
$this->conex->beginTransaction();
$query = $this->conex->prepare("SELECT usuario.id as id, login.avatar as avatar FROM usuario, login WHERE usuario.id = :id and usuario.id ORDER BY data DESC LIMIT $pagin, $paginaF");
$query->bindParam(":id", $ID, PDO::PARAM_INT, 20);
$query->execute();
while ($lista = $query->fetch()){
$id = $lista['id'];
$avatar = $lista['avatar']
echo '<div id="avatar">'.$avatar.'</div>';
}
}catch (PDOException $ex) {
echo "Erro: " . $ex->getMessage();
}

Related

unlink doesn't seem to work in a foreach loop

So I have the following piece of code so that when I delete a row from the database I also delete the files associated with it, the code runs smoothly and I'm actually able to delete the rows from the database but somehow I'm unable to delete the files from the server directory, note that row "photo_filename" contains a name such as "photo.png" or so, also calling _ DIR _ from the file returns a path like this "...\Desktop\project/procedures", I'm not even getting any warnings I tried echoing a a string if unlink was successful and some other string if not successful, but the weird thing is I don't get any output, it is as if the loop doesn't even run, can someone point me towards the right direction on what I'm missing right here. Thank you
try {
$db->beginTransaction(); // Begin transaction
$query = "DELETE FROM properties "
. " WHERE property_id = :property_id"; // Delete requested property.
$stmt = $db->prepare($query);
$stmt->bindParam(":property_id", $property["property_id"], PDO::PARAM_INT);
$stmt->execute();
$query = "SELECT * FROM photos "
. " WHERE property_id = :property_id";
$stmt = $db->prepare($query);
$stmt->bindParam(":property_id", $property["property_id"], PDO::PARAM_INT);
$stmt->execute();
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $photo) {
try {
unlink(__DIR__ . "/../img/" . $photo["image_filename"])
} catch (Exception $e) {
throw $e;
}
}
$query = "DELETE FROM photos "
. " WHERE property_id = :property_id";
$stmt = $db->prepare($query);
$stmt->bindParam(":property_id", $property["property_id"], PDO::PARAM_INT);
$stmt->execute();
$db->commit();
} catch (Exception $e) { // If there is a problem
$db->rollBack(); //If there was a problem undo the whole attempt to insert
$session->getFlashBag()->add("error", "Hubo un problema" . $e->getMessage()); // Display a message
redirect("/show.php?id=".$property_id); // And redirect
exit;
}
I just realized my dumb mistake, so "properties" table was linked to "photos" table so when I began the transaction and deleted the property from the table the photos associated with it were also automatically deleted, so when I selected and looped through the photos table to get the files there weren't any, leaving this here just in case someone runs into something similar, thank you guys for responding.

Performance of fetching DB items individually vs looping with php

Out of curiosity, which of these segments of code would have the faster performance time when implemented on a mass scale?
Let's say we have a table members and we want to fetch their photos.
Method 1
$members = $db->query('SELECT * FROM members ORDER BY id ASC');
foreach($members as $m)
$memberIDs[] = $m['id'];
$photos = $db->query('SELECT * FROM photos WHERE member IN'.join(',', $memberIDs).' ORDER BY id ASC');
foreach($photos as $p) {
// multi_arr_search(search_val, search_column, search_array) returns parent key in multi dimensional array
$memberArrayKey = multi_arr_search($p['member'], 'id', $members);
$members[$memberArrayKey]['photos'][] = $p;
}
OR
Method 2
$members = $db->query('SELECT * FROM members ORDER BY id ASC');
foreach($members as $k=>$m)
$members[$k]['photos'] = $db->query('SELECT * FROM photos WHERE member='.$m['id'].' ORDER BY id ASC');
Method 1 would result in fewer queries being ran, but requires more PHP work.
neither. You are using 15 years old deprecated methods.
If you want to go fast, you need PDO prepared statements.
#alberto is right. I am pretty sure, you can have one and only sql to perform this but here is a way you might want to consider in case off:
$showError = true;
define("SQLHOST", "127.0.0.1");
define("SQLUSER", "login");
define("SQLPASS", "password");
define("SQLSGBD", "database");
$conn = new PDO('mysql:host=' . SQLHOST . ';dbname=' . SQLSGBD . ';charset=UTF8', SQLUSER, SQLPASS);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql1 = 'SELECT * FROM members ORDER BY id ASC';
$stmt1 = $conn->prepare($sql1);
$sql2 = 'SELECT * FROM photos WHERE member IN ? ORDER BY id ASC';
$stmt2 = $conn->prepare($sql2);
try {
$stmt1->execute();
$members = $stmt1->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
if ($showError === true) {
var_dump("error query 1:" . __LINE__ . "-------" . __FUNCTION__ . "-------" . $e->getMessage());
exit;
}
}
if (count($members) !== 0) {
$memberIDs = array();
foreach ($members as $m) {
$memberIDs[] = $m['id'];
}
$memberlist = join(',', $memberIDs);
foreach ($members as $memberArrayKey => $result1) {
$stmt2->bindParam(1, $memberlist, PDO::PARAM_STR);
try {
$stmt2->execute();
$photos = $stmt2->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
if ($showError === true) {
var_dump("error query 2:" . __LINE__ . "-------" . __FUNCTION__ . "-------" . $e->getMessage());
exit;
}
}
if (count($photos) !== 0) {
$memberArrayKey = multi_arr_search($p['member'], 'id', $members);
$members[$memberArrayKey]['photos'][] = $p;
}
}
}
Well, hard truth: none is actually scalable. If you're working with large sets of data, PHP will need quite a bit of memory to perform all the operations to link users and photos and will do it in a much more inefficient way than the DB can.
You should have the tool you have that is best at doing these kind of things, which is your DB: the DB should join the users & photos and get you that set.. anything you do differently will mean reduced performance and scalability.
1- It depends on many factors how are you working with MySQL, if you connect and disconnect connection with the DB at each call.
2- MySQL Server is in the same PHP.
Ideally, connect 1 time mysql to retrieve information with a single Query. And in your case, you can solucuonar with a JOIN. Which it is best to disconnect as quickly as possible and continue with MySQL PHP.
Another recommendation is to not use " * " in the SELECT. Only puts the fields that you go to work. This eat fewer resources because only you use is requested. It is optimal in Memory, CPU, Data via LAN

Having trouble fetching results from a MySQL table with PDO

I'm building a simple login system. What I'm having trouble with is fetching the password hash from the database.
This is what I have:
$statement = 'SELECT Pass FROM Emails WHERE Email = "?"';
$question = array($email);
try {
$DB->beginTransaction();
$preparedStatement = $DB->prepare($statement);
$preparedStatement->execute($question);
$resultArr = $preparedStatement->fetchAll();
print_r($resultArr);
$DB->commit();
} catch(\PDOException $ex) {
echo "Seriously bad error. ";
echo $ex->getMessage();
return false;
}
My problem is that $resultArr always contains no elements.
I know the SQL query itself works, as I've tested it directly in MySQL.
I believe that I have to use a prepared statement, as I'm sending user input to MySQL and have to defend against easy SQL injection attacks.
I'm using fetchAll() in order to make sure that there's only one result for a given email. Otherwise, there will be a huge problem.
What is my mistake here?
Just for sake of cleaning this extremely superfluous code
$stmt = $DB->prepare('SELECT Pass FROM Emails WHERE Email = ?');
$stmt->execute(array($email));
$pass = $stmt->fetchColumn();
these 3 lines is ALL you need to run a query and get result.
And yes, the problem is just quotes around ? mark.
To ensure there is no other email you ought to use unique index in Mysql
$query = 'SELECT Pass FROM Emails WHERE Email = :email';
try {
$DB->beginTransaction();
$preparedStatement = $DB->prepare($query);
$preparedStatement->bindParam("email", $email, PDO::PARAM_STR);
$preparedStatement->execute();
$resultArr = $preparedStatement->fetchAll();
print_r($resultArr);
$DB->commit();
} catch(\PDOException $ex) {
echo "Seriously bad error. ";
echo $ex->getMessage();
return false;
}

PHP MySQL query not returning all results

My following SQL query in PHP does not work fully. The result only contains the first row. The query works totally fine inside PHPMyadmin, which returns me all the results.
$select = "SELECT a.setID, a.setName, a.setPrimaryLanguage, a.setSecondaryLanguage
FROM Person_Set ps, Album a
WHERE ps.Person_username = :username
AND ps.Set_setID = a.setID";
try {
$stmt = $dbh->prepare($select, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$stmt->bindValue(":username", $username, PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetch();
echo json_encode($result);
unset($stmt);
} catch (Exception $e) {
echo 'Exception : ' . $e->getMessage() . "\n";
}
Besides, if I change the selection criteria to search for rows containing certain string, the result is empty (returned 'false'). Query below:
$select = "SELECT a.setID, a.setName, a.setPrimaryLanguage, a.setSecondaryLanguage
FROM Album a, Set_Card s
WHERE a.setName LIKE '%:searchText%'
AND a.setID = s.Set_setID
GROUP BY a.setID";
I have been trying different ways to connect to MySQL and get the results, like
$results = $mysqli->query($query);
instead of using PDO. However, the results are still the same. Could anyone help to point out where my mistakes are? Thank you very much!
PDOStatement::fetch — Fetches the next row from a result set
So when you just do a fetch it fetches the first row, unless you do it using a loop which changes the cursor to the next record.
You may get all the records using fetchAll method
http://php.net/manual/en/pdostatement.fetch.php
http://php.net/manual/en/pdostatement.fetchall.php
PDOStatement::fetch fetches a single row and moves pointer to the next row. You will either use $results = $stmt->fetchAll() to retrieve all results or a loop like this:
while ($result = $stmt->fetch()) {
echo json_encode($result);
}
Hi you are using fetch() function which fetch only one row instead use this code,
$select = "SELECT a.setID, a.setName, a.setPrimaryLanguage, a.setSecondaryLanguage
FROM Person_Set ps, Album a
WHERE ps.Person_username = :username
AND ps.Set_setID = a.setID";
try {
$stmt = $dbh->prepare($select, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$stmt->bindValue(":username", $username, PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetchall();
echo json_encode($result);
unset($stmt);
} catch (Exception $e) {
echo 'Exception : ' . $e->getMessage() . "\n";
}

what's wrong with this single PDO?

Here the thing, other PDO works well, but this one doesn't. I have tried with
execute(array(':t'=>$table));
with no success. Ideas?.
public function __construct($table){
try{
$pdocnx = new PDO("mysql:host=localhost;dbname=sigcat",'root','');
$stmt = $pdocnx->prepare('select * from sigcat.:t');
$stmt->bindParam(':t', urldecode($table), PDO::PARAM_STR,45);
$stmt->execute();
$row = $stmt->fetchAll(PDO::FETCH_ASSOC);
var_dump($row);
}catch(Exception $e){
echo $e->getMessage();
}
}
I got many records in 'supplies' but it returns array(0) { }. I'm getting the 'table' parameter with $_GET['table']. No exceptions though.
You can't bind table names, only values.
Maintain a list of valid names and ensure the string is present in the valid list.
If you can't build a list of valid names, you are probably doing something wrong.
You can't bind tables, so you can do a sneaky trick like this:
public function myFunction($table){
$st = "SELECT FROM `" . $table ."` ..some sql";
$statement->prepare($st);
$statement->execute();
}
Hope this helps.

Categories