I have a large amount of fetched rows in mysql table, it takes plenty of time to load the result everytime when the page is call, I might want to cache the result into php memcached to save loading time for every queries once the page loaded.
let say the query function is call:
class Account
{
public function get_account($mysqli)
{
$q = "SELECT * ";
$q .= "FROM `account`";
$sql = $mysqli->query($q);
if($sql->num_rows !== 0){
return $sql;
}
return false;
}
}
request the result:
$acc = new Account;
$m = new Memcache;
$m->addServer('localhost', 11211);
$ls = $acc->get_account($mysqli);
$html = '';
while($ob = $ls->fetch_object()){
$html .= '
<tr>
<td>'.$ob->name.'</td>
<td>'.$ob->phone.'</td>
<td>'.$ob->email.'</td>
<td>'.$ob->country.'</td>
</tr>';
}
in this case, how can I store the result into memcached? how can memcached know this result is stored and no MySQL query needed to load again?
Related
I am new to php and struggling to get the data from a table in mysql and using it to connect to an ftp server. The table contains the external ip address of the ftp server, the base directory to change into and login credentials to use. I fetched the data from mysql and stored it in an array but while looping through it I get
php notice: trying to access array offset on type null.
Code:
$now = time();
$yesterday = $now - (24 * 60 * 60);
$date = date("Y-m-d", $yesterday);
if (isset($_GET['date'])) {
$date = $_GET['date'];
}
$startDate = "$date 00:00:00";
$endDate = "$date 23:59:59";
//$conn = &newEtConn();
$sql= "SELECT stager_usr, stager_pwd, stager_ip, basedir, view_direction from et_devices.cameras as a inner join et_params.stagers as b on a.stagerid = b.idstagers ";
$result = mysqli_query($conn,$sql);
$datas = array();
if (!$result) {
die ("table Connection problem");
}
if (mysqli_num_rows($result)>0){
while ($row = mysqli_fetch_assoc($result)){
$datas[] = $row;
}
print_r($datas);
}
if ($row!= "") {
foreach ($datas as $values) {
$ip_addr = $values['stager_ip'];
$login = $values['stager_usr'];
$password = $values['stager_pwd'];
$basedir = $values['basedir'];
if ($rows != "") {
$gotFtpConn = True;
$ftp_obj = ftp_connect($ip_addr, 21, 10) or $gotFtpConn = False;
if ($gotFtpConn) {
if (ftp_login($ftp_obj, $login, $passwd)) {
echo "could not connect" . $login;
return false;
}
return $newEtConn;
}
}
}
There are a few things that I don't like (and can improve)...
It looks like you intend to filter your database data based on a date, but then you never actually apply that value to the array. I'll help to clean up that process.
Your if ($row != '') check after the loop will always fail because the loop ONLY stops when $row becomes falsey.
The rest of your code looks like it only intends to process a single row in the result set (because it returns). I am going to assume that you have more conditional logic in your query's WHERE clause which ensures that only one row is returned -- otherwise, you shouldn't be using return in your loop.
$date = !empty($_GET['date']) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $_GET['date'])
? $_GET['date']
: date('Y-m-d', strtotime('yesterday'));
$sql = "SELECT stager_usr, stager_pwd, stager_ip
FROM et_devices.cameras AS a
JOIN et_params.stagers AS b ON a.stagerid = b.idstagers
WHERE DATE(a.some_datetime_column) = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param('s', $date);
$stmt->execute();
foreach ($stmt->get_result() as $row) {
$ftp = ftp_connect($row['stager_ip'], 21, 10);
if (!$ftp) {
throw new Exception('Failed to establish FTP connection');
}
if (!ftp_login($ftp, $row['stager_usr'], $row['stager_pwd'])) {
throw new Exception('Incorrect FTP login credentials');
}
return $ftp;
}
throw new Exception('FTP connection data not found');
If you experience a noticeable performance bottleneck with DATE() in your sql, then there are other techniques that may be faster, but they use longer/uglier syntax.
I'm creating a Reddit clone for web development class. Sorting posts by hotness is the final required thing for me to do.
What I'm struggling with, is binding hotness rating to database entry of given post on website. Because I'm already using a mysqli_query in the while loop, I can't start another query for adding hotness rating.
I read posts suggesting to use arrays but that would consume a lot of server resource since hotness would be calculated again on page refresh.
<?php
$link = mysqli_connect("localhost", "username", "password", "database");
if ($link === false) {
die("ERROR: Could not connect. " . mysqli_connect_error());
}
// this is just reddit's hotness algorithm
function hot($ups, $downs, $date) {
$s = $ups - $downs;
$order = log10(max(abs($s), 1));
if ($s > 0) {
$sign = 1;
} else if ($s < 0) {
$sign = -1;
} else {
$sign = 0;
}
$seconds = $date - 1134028003;
return round($sign * $order + $seconds / 45000, 2);
}
$query = "SELECT * from posts";
$result = mysqli_query($link, $query);
if($result) {
// goes through all posts for upvote/downvote values to calculate hotness
while ($row = mysqli_fetch_array($result)) {
$post_id = $row['post_id'];
$time_in_seconds = strtotime($row['timestamp']);
$hotness_rating = hot($row['upvotes'], $row['downvotes'], $time_in_seconds);
$hotness_query = 'UPDATE posts SET hotness=$hotness_rating WHERE post_id=$post_id';
// ideally this would add hotness to post's row in database
mysqli_query($link, $hotness_query);
}
} else {
echo mysqli_error($link);
}
?>
You should calculate "hotness" of topic on its update, such as up-vote, down-vote or new message and store it in database at that moment.
This will give you a "hotness" value in database without pointless* recalculations on every refresh and you could simply sort by "hotness".
These recalculations on every refresh is pointless, because if data isn't changed - you will get same result on every refresh and make useless updates to update to same value.
Consider this sample code :
$storyID = 1;
$detailsCache = 'details'.$storyID;
if(!apc_exists($detailsCache)){
$phases_details = <<<SQL
SELECT stp.stp_id,
stp.stp_name,
stp.stp_position,
FROM story_phase stp
WHERE stp.stp_stl_id = $storyID
SQL;
$resultdetails = Helpers::execute_query($phases_details,"Get phase details failed.");
**// i cant cache the result here like apc_store($detailsCache, $phases_details);**
}
$result_phases_details = apc_fetch($detailsCache);
while($row = mysql_fetch_assoc($result_phases_details)){
// some logic
}
Any better way to cache the result ?
Assuming the MySQL result is a resource (which it seems to be based on your later use of mysql_fetch_assoc), that cannot be stored via APC. However, if you read out the result into PHP data structures first, you can store those in APC for later retrieval.
$resultdetails = Helpers::execute_query($phases_details,"Get phase details failed.");
$results = array();
while ($row = mysql_fetch_assoc($resultdetails)) {
$results[] = $row;
}
apc_store($detailsCache, $results);
// Retrieval:
$results = apc_fetch($detailsCache);
foreach ($results as $row) {
// some logic...
}
I am having a trouble with viewing the records in the database.
When i directly query in mysql server it returns 1 row. But in the web page it doesn't return anything.
After that, I tested to input another record directly in the db, then, 1 row appeared in the web page.
the $row returns false.
controller.php
$doc = 'drawings';
$model = 'test';
if($stat == '1')
{
$handlers = $this->model->getDocumentStatModel($model, $doc);
}
else
{
$handlers = $this->model->getDocumentStatNGModel($model, $doc);
}
include_once("view/model-list/sp-models-list.php");
model.php
public function getDocumentStatModel($model, $document)
{
if($document == 'nis')
{
$query = "SELECT * FROM $document WHERE Stat = 'OK'";
}
else
{
$query = "SELECT * FROM $document WHERE Model='$model' AND Stat = 'OK' ";
}
$result = mysql_query($query);
return $result;
}
sp-models-list.php
while($row = mysql_fetch_assoc($handlers)) // <----here it returns false
{
I am using MyISAM, is it related to my problem or maybe there are spaces that it cannot accept? Because when I tried in my search bar, mysql query does not return the rows when there are spaces in the string.
I have a script which looks like this which retrieves song information that people are scrobbling on LastFM:
class NowPlaying{
private $url;
private $noTrackPlayingMessage;
function __construct($user, $api_key){
// construct URL
$this->url = 'http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&limit=1';
$this->url .= '&user=' . $user . '&api_key=' . $api_key;
// default message
$this->noTrackPlayingMessage = 'Nothing is playing right now!';
}
// return the artist and track currently playing
public function getNowPlaying(){
// create an XML object
$xml = simplexml_load_file($this->url);
// get the latest track
$track = $xml->recenttracks->track;
// check if the track is actually playing
$nowplaying = $track->attributes()->nowplaying;
// return the track and artist if music is playing, otherwise show message
if($nowplaying){
$artist = $track->artist;
$songname = $track->name;
return $artist . ' - ' . $songname;
}
else{
return $this->noTrackPlayingMessage;
}
}
// set the message to be shown when no music is playing
public function setNoTrackPlayingMessage($messageIn){
$this->noTrackPlayingMessage = $messageIn;
}
} // end class
$nowPlaying = new NowPlaying($id, 'APIGOESHERE');
$nowPlaying->setNoTrackPlayingMessage($id); // optional
$currentplaying = $nowPlaying->getNowPlaying();
While this is useful for just an individual LastFM account however I want to run several accounts through this script which the details are stored in a MySQL database. My table has two columns, lastfmusername and currentsong. I want to find get all the songs those lastfm user's are listening to and then store them in their currentsong field.
I've tried adding the following to the top:
$sql = "SELECT lastfmusername FROM data";
$id = $db->query($sql);
Then the following to the bottom:
$sql2 = "UPDATE lastfmtable SET currentsong = '$currentplaying' WHERE lastfmusername = '$id'";
$cursong = $db->query($sql2);
But that failed so I'm not sure how to approach this. Any help would be appreciated.
$sql = "SELECT lastfmusername FROM data";
will return an array containing ALL values of lastfmusername, not just one.
Try this instead:
$sql = "SELECT lastfmusername FROM data";
$users = $db->query($sql);
$id = $users[0]['lastfmusername'];
meaning: $id will now store the first result.
You'll need to loop through the result of users and run the update query for each user. So what you are trying to do should look like this:
foreach($users as $r){
$id= $r['lastfmusername'];
$nowPlaying = new NowPlaying($id, 'APIGOESHERE');
$nowPlaying->setNoTrackPlayingMessage($id); // optional
$currentplaying = $nowPlaying->getNowPlaying();
$sql2 = "UPDATE lastfmtable SET currentsong = '$currentplaying' WHERE lastfmusername = '$id'";
$cursong = $db->query($sql2);
}