mysql pdo hit counter - php

I can't make the counter add 1 into the DB and the value increment every time when somebody go to the page... only works when is reloaded.
Where is the error in my code? Can you help me with this issue?
I don't know if you need my entire html page, if you want I page it. the url have the id is show like this: post.php?id_blog=4
THe code:
<?php
try {
$query = "SELECT id_blog, blog_titulo, blog, vistoblog FROM BLOG WHERE id_blog = ?";
$stmt = $conn->prepare( $query );
$stmt->bindParam(1, $_REQUEST['id_blog']);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$id_blog = $row['id_blog'];
$blog_titulo = $row['blog_titulo'];
$blog = $row['blog'];
$vistoblog = $row['vistoblog'];
}catch(PDOException $exception){
echo "Error: " . $exception->getMessage();
}
try{
$visto = $vistoblog + 1;
$sql = "UPDATE BLOG SET
vistoblog = :vistoblog
WHERE id_blog = :id_blog";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':vistoblog', $visto, PDO::PARAM_STR);
$stmt->bindParam(':id_blog', $id_blog, PDO::PARAM_INT);
$stmt->execute();
}catch(PDOException $exception){
echo "Error: " . $exception->getMessage();
}
?>

I recommend making your SQL just like this:
UPDATE BLOG SET
vistoblog = vistoblog + 1
WHERE id_blog = :id_blog
The reason is to avoid a race condition. What if two people visit the page simultaneously, and both PHP threads read vistoblog value 123, add 1, and both try to increment it to value 124?
By using the expression above, you don't have to read the current value, and you avoid the chance of a race condition like that.

Related

How to use CONCAT and NOT LIKE in an SQL Update in PHP request

Hi i am creating an android app which i am currently at a halt because my sql skills are not up to scratch. I am using json.response to run the following php.
Situation: I am checking the table column (users_watched) to see if the user_id exists inside it based on title_text, since its a number i am using ,1,(example) commas around the number so it doesn't get confused with something like 101, and returns that value. If the user_id is not in the row, then add it to the end of the string.
Text Data: user_id = '10,' - watched_title = 'video_title' - temp_user_id = ',10,'
$user_id = $_POST["user_id"];
$watched_title = $_POST["watched_title"];
$temp_user_id = $_POST["temp_user_id"];
$like_input = "'%".$temp_user_id."%'";
$statement = mysqli_prepare($con, "UPDATE videos SET users_watched = CONCAT(users_watched, '?') WHERE users_watched NOT LIKE ? AND title_text = ?");
mysqli_stmt_bind_param($statement, "sss", $user_id, $like_input, $watched_title);
mysqli_stmt_execute($statement);
Result: It is not adding the value to the end of the appropriate string.
Expected Output Add user_id = 10, to the end of the string based on videos_watched
<?php
$user_id = $_POST["user_id"];
$watched_title = $_POST["watched_title"];
$temp_user_id = $_POST["temp_user_id"];
$like_input = "%".$temp_user_id."%";
try {
$con = new PDO('mysql:host=$host;dbname=$dbname','$username', '$pass');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $con->prepare("UPDATE videos SET users_watched = CONCAT(users_watched, :userid) WHERE users_watched NOT LIKE :like_input AND title_text = :watched_title");
$stmt->bindParam(':userid', $userid);
$stmt->bindParam(':like_input', $like_input);
$stmt->bindParam(':watched_title', $watched_title);
$stmt->execute();
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
?>

How do I call a SQL Server stored procedure from PHP using PDO_SQLSRV that returns a value?

I have a stored procedure in SQL Server 2014 that takes two integers as input and returns an integer. Below is the code to create the stored procedure:
CREATE PROCEDURE [dbo].[p_MergePerson_AuditLog_CheckLogForDuplicate]
#Person1_ID INT,
#Person2_ID INT,
#RowCount INT OUTPUT
AS
SET NOCOUNT ON
SELECT
#RowCount = COUNT(mpal.Transaction_ID)
FROM
MergePersonAuditLog mpal
WHERE
#Person1_ID = #Person2_ID
AND #Person2_ID = #Person1_ID
RETURN #RowCount
Basically, it just takes two ids and sees if a comparison has been made before, just in a different order. Below is the PHP code:
// Connecting to DB
try {
$conn = new PDO("sqlsrv:server=IP;Database=DB", "user", "pwd");
}
catch(PDOException $e) {
die("Error connecting to server $e");
}
// Arrays that will hold people IDs
$person1Array = array();
$person2Array = array();
// Holds the row count used to see if a comparison has already been performed
$rowcount = 5; // Setting to 5 to make sure the stored procedure is actually setting the value.
// Query to get the people that will be compared
$query = "SELECT p.PersonID
FROM Person p
WHERE (p.StudentNumber IS NULL OR p.StudentNumber = '')
AND (p.StaffNumber IS NULL OR p.StaffNumber = '')
ORDER BY
p.PersonID";
$stmt = $conn->query($query);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
foreach ($row as $key => $value) {
$person1Array[] = $value;
}
}
$person2Array = $person1Array;
// Begin the comparisons
print "Beginning the comparisons <br>";
foreach ($person1Array as $person1id) {
foreach ($person2Array as $person2id) {
print "Checking $person1id and $person2id <br>";
if ($person1id != $person2id) {
print "Not the same. Continuing.<br>";
// Checking to see if the comparison has already been made
$query = "{? = call p_MergePerson_AuditLog_CheckLogForDuplicate(?, ?)}";
$stmt = $conn->prepare($query);
$stmt->bindParam(1, $rowcount, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT,4);
$stmt->bindParam(2, $person1id, PDO::PARAM_INT);
$stmt->bindParam(3, $person2id, PDO::PARAM_INT);
$stmt->execute();
print $rowcount . "<br>";
}
}
}
print "FINISHED! <br>";
$stmt = null;
$conn = null;
?>
When I run this code, 5 is still being printed for $rowcount even though it should be set to 0 by the stored procedure. If the value is 0, more code will be executed that I didn't include, but I want to get this part right first. Running the procedure in management studio works fine. Can someone tell me why $rowcount is not getting updated? I am running php 5.6 on Windows 10.
Ok, I found an answer that worked for me. I read https://msdn.microsoft.com/en-us/library/cc626303(v=sql.105).aspx which doesn't have anything to do with PDO_SQLSRV, but with sqlsrv_connect(). In that article, it stated the last parameter was the output parameter. I changed my code to look like this:
// Checking to see if the comparison has already been made
$query = "{call p_MergePerson_AuditLog_CheckLogForDuplicate(?, ?, ?)}";
$stmt = $conn->prepare($query);
$stmt->bindParam(1, $person1id, PDO::PARAM_INT);
$stmt->bindParam(2, $person2id, PDO::PARAM_INT);
$stmt->bindParam(3, $rowcount, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT,4);
$stmt->execute();
print $rowcount . "\n";
Basically, I moved the "?" From the beginning of the call statement to the end and moved the bindParam to the end as well. That seems to have done the trick.
You could get the return value via a select statement:
$query = "select p_MergePerson_AuditLog_CheckLogForDuplicate(?, ?)";
$stmt = $conn->prepare($query);
$stmt->bindParam(1, $person1id, PDO::PARAM_INT);
$stmt->bindParam(2, $person2id, PDO::PARAM_INT);
$stmt->execute();
$result = $stmt->fetchColumn();

PHP updating large database

I have a large database (28k entries in this particular table one table) and I need to append some HTML tags to the front and back of every column in a table.
Here is my code:
try
{
$conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
if(!$conn)
{
echo "Error in connecting to the database.";
}
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$query = $conn->query("SELECT `id`, `introtext` FROM *TABLE* WHERE id >= 41155");
$query->setFetchMode(PDO::FETCH_OBJ);
//For each row in the table
while($row = $query->fetch())
{
$introtext = '<span class="*SPAN CLASS*">' . $row->introtext . '</span>';
$update_query = $conn->prepare("UPDATE *TABLE* SET introtext = ? WHERE id = ?");
if ($query->execute(array($introtext, $row->id)))
echo $row->id . " Done <br>";
else
echo $row->id . " Err<br>";
}
} catch(PDOexception $e) {
echo $e->getMessage();
}
$conn = null;
When I run the script, it outputs 41155 Done 4132 times. I'm not sure the logic here, but any help to get this working is appreciated.
I agree with Dagon that the database is not the place for that (what if tomorrow you decide that <span> should wrap another HTML tag?).
Anyway, it sounds like a one-time operation, so I wouldn't use PHP. Just run a MySQL client (the command line mysql, or Workbench, and use a query like this:
UPDATE *TABLE*
SET introtext = CONCAT('<span class="*SPAN CLASS*">', introtext, '</span>')
WHERE id >= 41155
One note about your current code: you're never executing the UPDATE query! You just prepare the statement, then instead of executing $update_query, you're executing $query again! That's why you're always printing the same id.

Why am I receiving a PDO query error?

Apologies in advance because I'm really unsure how to ask this question so if you need to know anything then please comment rather than downvote and I will edit.
I have teaser links on my main page which when clicked open up a window with the full article. I'm currently converting my MySQL code over to PDO and have gotten a little stuck.
In MySQL I used to be doing the following (Here, $foo_query is the query from the first page):
$id = $_GET['id'];
$sql = "SELECT id, postdate, title, body FROM FooBarTable WHERE id = $id";
if ($foo_query = mysql_query($sql)) {
$r = mysql_fetch_assoc($foo_query);
$title = $r["title"];
$body = $r["body"];
}
Which is simple to understand to me. I've been trying to convert this using what I know, and it turns out I don't know very much. So far I have the following:
$id = $_GET['id'];
$sql = $DBH->prepare("SELECT id, postdate, title, body FROM FooBarTable WHERE id = :id OR id = $id");
$sql->bindParam(':id', $_REQUEST['id'], PDO::PARAM_INT);
if ($foo_query = $DBH->query($sql)) {
$r->setFetchMode(PDO::FETCH_ASSOC);
$r = $foo_query->fetch();
$title = $r["title"];
$body = $r["body"];
}
$sql->execute();
This brings up an error of 'PDO::query() expects parameter 1 to be string'. This is for the 'if' line.
Have I even written any of that PDO correctly? What would I need to do from here? A friend has recently taught me MySQL, but he doesn't know PDO at all which means I can't ask his advice (not all that helpful...)
This is the correct way, with comments:
try {
//Connect to the database, store the connection as a PDO object into $db.
$db = new PDO("mysql:host=localhost;dbname=database", "user", "password");
//PDO will throw PDOExceptions on errors, this means you don't need to explicitely check for errors.
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//PDO will not emulate prepared statements. This solves some edge cases, and relives work from the PDO object.
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
//Prepare the statement.
$statement = $db->prepare("SELECT id, postdate, title, body FROM FooBarTable WHERE id = :id");
//Bind the Value, binding parameters should be used when the same query is run repeatedly with different parameters.
$statement->bindValue(":id", $_GET['id'], PDO::PARAM_INT);
//Execute the query
$statement->execute();
//Fetch all of the results.
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
//$result now contains the entire resultset from the query.
}
//In the case an error occurs, a PDOException will be thrown. We catch it here.
catch (PDOException $e) {
echo "An error has occurred: " . $e->getMessage();
}
You need to use PDOStatement::execute instead of PDO::query:
$foo_query = $sql->execute();
You may also bind all your params at once when calling execute:
$foo_query = $sql->execute(array(
':id' => $id
));
You should change it to:
$sql->execute();
if($r = $sql->fetch()) {
$title = $r["title"];
$body = $r["body"];
Try this:
$sql = $DBH->prepare("SELECT id, postdate, title, body
FROM FooBarTable WHERE id = :id OR id = $id");
$sql->bindParam (':id', $_REQUEST['id'],PDO::PARAM_INT);
$sql->execute();
while($row = $sth->fetch(PDO::FETCH_ASSOC)) {
$title = $row["title"];
$body = $row["body"];
}

MySQL: Update statement shows no errors but changes nothing

I have a connection to a database and want to update(override) an existing string called profile by a new one.
$uid = 1;
$serProfile = 'abc';
$sql = 'UPDATE
Users
SET
profile = ?
WHERE
id = ?';
$stmt = $db->prepare($sql);
if (!$stmt) { safeExit($db->error, 'msgError'); }
$stmt->bind_param('si', $serProfile, $uid);
if (!$stmt->execute()) { safeExit($stmt->error, 'msgError'); }
$stmt->close();
However, although the variables exist, the fields exist and there are no errors, the values in the database do not get changed. How to resolve this behaviour?
Test this one
$sql = 'UPDATE Users SET profile = :profile WHERE id = :id';
$stmt = $db->prepare($sql);
$stmt->execute(array('id'=>$uid,'profile'=>$serProfile));

Categories