mysql plus one a column - php

i use my own mvc framework.
and post action is :
function post($pid = 0 , $title = '')
{
$pid = $this->input->clean($pid);
$stm =$this->Post->query("UPDATE posts SET `show_count`=show_count+1 WHERE id = $pid");
$stm->execute();
$row = $this->Post->find()->where(array('id'=>$pid))->fetchOne();
$this->layout->set('comments' , $this->comments($pid));
$this->layout->set('row' , $row);
$this->side();
$this->layout->view('post');
echo $this->layout->render($row['title']);
}
i want to when a record fetch from database plus one show_count column .
i use this query :
UPDATE posts SET show_count = show_count + 1 WHERE id = $pid
this right in localhost but in my shared host when run query instead of one pluses ,2 plus show_count column.
how can i solve this problem?

It's working in your localhost but not your internet host. The host is probably doing something behind the scenes that makes it not work. Also, since you don't have access to all the configuration stuff on the host server, you probably won't be able to just fix it.
Simplest fix is to do it in the software layer (assuming $pid is unique).
First get the show_count.
Then:
$oldShowCount = the current show_count
$newShowCount = $oldShowCount + 1
UPDATE posts SET show_count = $newShowCount WHERE id = $pid AND show_count = $oldShowCount
At this point, if no race conditions occurred the row will update (rows update = 1). If a race condition occurred, the update will fail (rows updated = 0).
Then check the # rows updated to verify it worked and repeat until it does.

This is quite common case.
You are running your script twice. Probably because browser is calling it twice. Check your rewrite rules.

Related

How to check each id in a column then allocate the first available number in PHP for mysql?

Using PHP i'd like to check the next available number to use as an id after comparing it to the query that lists all my id's
In theory I can do this;
$clientid = '0';
$getid_query = "SELECT clientid FROM clients";
$response = mysqli_query($conny, $getid_query);
while($data = mysql_fetch_assoc($response)){
$row[] = $data;
}
$freeid = False;
while($freeid == false){
if($row[clientid].contains($clientid){
$clientid = $clientid + 1;
}
else {
$freeid = true;
}
}
This leaves $clientid as an unique id ready to be used for the next created client
there might be a few syntax errors but in general I've tried most combinations and seem to get it right, I've been testing the different outputs such as
echo "Error:" . $row[clientid];
and sometimes (more often than not, nothing displays).
Edit 2:
Hold up! I wanted to do it php side because the associated username is generated from the clientid (all in php). So im going to follow the links from liridyn and see if i can do something.
Would there be a safe way to query the database again as soon as a new client has been registered in order to get their allocated clientid, so i can then update their row with the generated username?
Thanks
So, SELECT MAX(clientId) + 1 AS clientId FROM clients would replace your mixed PHP/SQL with a single query - but I would recommend against that, as adding AUTO_INCREMENT to clientId would instruct the SQL client to manage that for you automatically; if you then need that id, instead of generating it from PHP or calling SELECT MAX(clientID) FROM clients (which still has a race condition), you can follow the advice in this answer or call mysqli_insert_id.
I've ended up using Auto_increment on the db side. Thanks

PHP cannot increase value in Postgres database

I could use some help understanding an odd situation. I have a postgres database 'servers' with ip (inet) and load (integer) columns. I can manually update a load value via psql as follows:
UPDATE servers
SET load = load + 100
WHERE ip = '10.10.10.10';
I have written a php script to automate load updates. However, the 'value = value + x' syntax is not working for me now.
THIS WORKS:
pg_query($conn, "UPDATE servers SET load = 100 WHERE ip = '10.10.10.10'");
THIS DOESN'T:
pg_query($conn, "UPDATE servers SET load = load + 100 WHERE ip = '10.10.10.10'");
When using the latter, the script hangs indefinitely without giving a response. I have tried variations such as adding an or die(pg_last_error()) clause at the end. I have also tried using a pg_prepare and pg_execute statement. Still no output, and no change to the database.
Am I missing something? Is there an easy way to get around this (I'd rather not use a separate query to get load just so that I can add it back in).
I have solved this issue. I am not certain why this was a problem, but it turns out that best practices helped solve it in the end anyway.
Instead of running a single pg_query, I set up appropriate variables and used pg_query_params. This is probably a good idea regardless of issues.
$myQuery = "UPDATE servers SET load = load + $1 WHERE ip = '$2'";
$serverIP = '10.10.10.10';
$loadAdded = '1234';
$result = pg_query_params($conn, $myQuery, array($loadAdded, $serverIP));
Again, I don't know why this solved the issue for me, but it did.

query if a entry has changed since last check and continuously check for a time

The High Level Idea:
I have a micro controller that can connect to my site via a http request...I want to feed the device a response as soon as a change is noted on the database...
Due to the the end device being a client ie micro controller...Im unaware of a method to pass the data to the client without having to set up port forwarding...which is heavily undesired ...The problem arise when trying send data from an external network to an internal one...Either A. port forwarding or B have the client device initiate the request which leads me to the idea of having the device send an http request to file that polls for changes
Update:
Much Thanks to Ollie Jones. I have implimented some of his
suggestions here.
Jason McCreary suggested having a modified column which is a big
improvement as it should increase speed and reliability ...Great
suggestion! :)
if the database being overworked is in question in this example
maybe the following would work where...when the data is inserted into
the database the changes are wrote to a file...then have the loop
that continuously checks that file for an update....thoughts?
I have table1 and i want to see if a specific row(based on a UID/key) has been updated since the last time i checked as well as continuously check for 60 seconds if the record bets updated...
I'm thinking i can do this using the INFORMATION_SCHEMA database.
This database contains information about tables, views, columns, etc.
attempt at a solution:
<?php
$timer = time() + (10);//add 60 seconds
$KEY=$_POST['KEY'];
$done=0;
if(isset($KEY)){
//loign stuff
require_once('Connections/check.php');
$mysqli = mysqli_connect($hostname_check, $username_check, $password_check,$database_check);
if (mysqli_connect_errno($mysqli))
{ echo "Failed to connect to MySQL: " . mysqli_connect_error(); }
//end login
$query = "SELECT data1, data2
FROM station
WHERE client = $KEY
AND noted = 0;";
$update=" UPDATE station
SET noted=1
WHERE client = $KEY
AND noted = 0;";
while($done==0) {
$result = mysqli_query($mysqli, $query);
$update = mysqli_query($mysqli, $update);
$row_cnt = mysqli_num_rows($result);
if ($row_cnt > 0) {
$row = mysqli_fetch_array($result);
echo 'data1:'.$row['data1'].'/';
echo 'data2:'.$row['data2'].'/';
print $row[0];
$done=1;
}
else {
$current = time();
if($timer > $current){ $done=0; sleep(1); } //so if I haven't had a result update i want to loop back an check again for 60seconds
else { $done=1; echo 'done:nochange';}//60seconds pass end loop
}}
mysqli_close($mysqli);
echo 'time:'.time();
}
else {echo 'error:nokey';}
?>
Is this an adequate method and suggestions to improve the speed as well as improve the reliability
If I understand your application correctly, your client is a microcontroller. It issues an HTTP request to your php / mysql web app once in a while. The frequency of that request is up to the microcontroller, but but seems to be once a minute or so.
The request basically asks, "dude, got anything new for me?"
Your web app needs to send the answer, "not now" or "here's what I have."
Another part of your app is providing the information in question. And it's doing so asynchronously with your microcontroller (that is, whenever it wants to).
To make the microcontroller query efficient is your present objective.
(Note, if I have any of these assumptions wrong, please correct me.)
Your table will need a last_update column, a which_microcontroller column or the equivalent, and a notified column. Just for grins, let's also put in value1 and value2 columns. You haven't told us what kind of data you're keeping in the table.
Your software which updates the table needs to do this:
UPDATE theTable
SET notified=0, last_update = now(),
value1=?data,
value2?=data
WHERE which_microcontroller = ?microid
It can do this as often as it needs to. The new data values replace and overwrite the old ones.
Your software which handles the microcontroller request needs to do this sequence of queries:
START TRANSACTION;
SELECT value1, value2
FROM theTable
WHERE notified = 0
AND microcontroller_id = ?microid
FOR UPDATE;
UPDATE theTable
SET notified=1
WHERE microcontroller_id = ?microid;
COMMIT;
This will retrieve the latest value1 and value2 items (your application's data, whatever it is) from the database, if it has been updated since last queried. Your php program which handles that request from the microcontroller can respond with that data.
If the SELECT statement returns no rows, your php code responds to the microcontroller with "no changes."
This all assumes microcontroller_id is a unique key. If it isn't, you can still do this, but it's a little more complicated.
Notice we didn't use last_update in this example. We just used the notified flag.
If you want to wait until sixty seconds after the last update, it's possible to do that. That is, if you want to wait until value1 and value2 stop changing, you could do this instead.
START TRANSACTION;
SELECT value1, value2
FROM theTable
WHERE notified = 0
AND last_update <= NOW() - INTERVAL 60 SECOND
AND microcontroller_id = ?microid
FOR UPDATE;
UPDATE theTable
SET notified=1
WHERE microcontroller_id = ?microid;
COMMIT;
For these queries to be efficient, you'll need this index:
(microcontroller_id, notified, last_update)
In this design, you don't need to have your PHP code poll the database in a loop. Rather, you query the database when your microcontroller checks in for an update/
If all table1 changes are handled by PHP, then there's no reason to poll the database. Add the logic you need at the PHP level when you're updating table1.
For example (assuming OOP):
public function update() {
if ($row->modified > (time() - 60)) {
// perform code for modified in last 60 seconds
}
// run mysql queries
}

MySQL (and maybe PHP): Fill a new column with the host of a referer

I have a table with a request log. In there is a column with referers. Now in order to see what domains refer the most requests I want to add a new column with the host of the referer.
That is no problem for the new entries but how do I update every row without an entry in the new row to have the host from the referer?
Is there an easy way to do this in MySQL or how di I solve it in PHP?
$oldRows = mysql_query("SELECT * FROM logs_requests WHERE host_ref = ''");
while($row = mysql_Fetch_array($oldRows))
{
$host = parse_url($row['url_ref'], PHP_URL_HOST);
mysql_query("UPDATE logs_requests SET host_ref='$host' WHERE id='{$row['id']}'");
}
This php code fetch all the rows with empty host_ref field,
then it takes the host (www.domain.com) from the url_ref (www.domain.com/page/34.html) with the parse_url function.
After that , there's an update query which updates the host field.
NOTICE: Customize this code according to your db scheme.

Running multiple PHP scripts at the same time (database loop issue)

I am running 10 PHP scripts at the same time and it processing at the background on Linux.
For Example:
while ($i <=10) {
exec("/usr/bin/php-cli run-process.php > /dev/null 2>&1 & echo $!");
sleep(10);
$i++;
}
In the run-process.php, I am having problem with database loop. One of the process might already updated the status field to 1, it seem other php script processes is not seeing it. For Example:
$SQL = "SELECT * FROM data WHERE status = 0";
$query = $db->prepare($SQL);
$query->execute();
while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
$SQL2 = "SELECT status from data WHERE number = " . $row['number'];
$qCheckAgain = $db->prepare($SQL2);
$qCheckAgain->execute();
$tempRow = $qCheckAgain->fetch(PDO::FETCH_ASSOC);
//already updated from other processs?
if ($tempRow['status'] == 1) {
continue;
}
doCheck($row)
sleep(2)
}
How do I ensure processes is not re-doing same data again?
When you have multiple processes, you need to have each process take "ownership" of a certain set of records. Usually you do this by doing an update with a limit clause, then selecting the records that were just "owned" by the script.
For example, have a field that specifies if the record is available for processing (i.e. a value of 0 means it is available). Then your update would set the value of the field to the scripts process ID, or some other unique number to the process. Then you select on the process ID. When your done processing, you can set it to a "finished" number, like 1. Update, Select, Update, repeat.
The reason why your script executeds the same query multiple times is because of the parallelisation you are creating. Process 1 reads from the database, Process 2 reads from the database and both start to process their data.
Databases provide transactions in order to get rid of such race conditions. Have a look at what PDO provides for handling database transactions.
i am not entirely sure of how/what you are processing.
You can introduce limit clause and pass that as a parameter. So first process does first 10, the second does the next 10 and so on.
you need lock such as "SELECT ... FOR UPDATE".
innodb support row level lock.
see http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html for details.

Categories