I've got a serious issue here. I'm developing a forum, and trying to get an "unread posts" feature ready. However, for some reason my code decides to loop & get ridiculous CPU usage over my dedi. All i see from my MySQL process list is that the same sql is constantly looping.
This is my code:
public function __construct()
{
$this->getUnread();
}
private function getUnread()
{
global $cms;
// check unread threads
$forumSQL = $cms->db->query('SELECT * FROM forum_for');
while($forums = $forumSQL->fetch_assoc())
{
$forumId = $forums['id'];
$forumArray[$forumId] = $forums;
}
if($unreadThreadsSql = $cms->db->query('SELECT * FROM forum_threads WHERE posted > "' . $_SESSION['lastVisit'] . '"'))
{
while(!$unreadThreads = $unreadThreadsSql->fetch_assoc())
{
$forumId = $unreadThreads['forId'];
if($this->checkUnread($unreadThreads['id']))
{
$cms->db->query('
INSERT INTO
forum_unread(
threadID,
catID,
forumID,
userID,
datetime,
threadtime)
VALUES(
'.$unreadThreads['id'].',
'.$forumArray[$forumId]['cat_id'].',
'.$forumId.',
'.$_SESSION['userId'].',
NOW(),
"'.$unreadThreads['posted'].'" )');
}
}
}
// check unread posts
if($unreadPostsSql = $cms->db->query('SELECT * FROM forum_posts WHERE datetime > "' . $_SESSION['lastVisit'] . '"'))
{
while($unreadPosts = $unreadPostsSql->fetch_assoc())
{
$threadSql = $cms->db->query('SELECT * FROM forum_threads WHERE id = ' . $unreadPosts['threadId']);
$thread = $threadSql->fetch_assoc();
$forumId = $thread['forId'];
if(!$this->checkUnread($thread['id']))
{
$cms->db->query('
INSERT INTO
forum_unread(
threadID,
catID,
forumID,
userID,
datetime,
threadtime)
VALUES(
'.$thread['id'].',
'.$forumArray[$forumId]['cat_id'].',
'.$forumId.',
'.$_SESSION['userId'].',
NOW(),
"'.$thread['posted'].'" )');
}
}
}
}
private function checkUnread($id)
{
global $cms;
if($unreadSql = $cms->db->query('SELECT * FROM forum_unread WHERE threadID = ' .$id . ' AND userID = ' . $_SESSION['userId']))
{
if($unreadSql->num_rows == 1)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
Could really use some help here. I really can't find why it's looping, does anyone have an idea...
For whose wondering, it seems the code is looping in the function checkUnread().
As an extra note, when commenting the $this->getUnread(); in the constructor the entire thing stops overloading. So i'm certain it's in this bit of code.
Did you mean while($unreadThreads = $unreadThreadsSql->fetch_assoc())?
BTW it would be highly more efficient if you composed one big INSERT query then executed it once, rather than all of these little bitty queries.
Example:
$inserts = Array();
$unreadThreadsSql = $cms->db->query('SELECT * FROM forum_threads WHERE posted > "' . $_SESSION['lastVisit'] . '"') or die($cms->db->error);
while ($unreadThreads = $unreadThreadsSql->fetch_assoc()) {
$forumId = $unreadThreads['forId'];
if (!$this->checkUnread($unreadThreads['id']))
continue;
$inserts[] = '(' .
$unreadThreads['id'] . ',' .
$forumArray[$forumId]['cat_id'] . ',' .
$forumId . ',' .
$_SESSION['userId'] . ',' .
'NOW(),' .
'"' . $unreadThreads['posted'] . '")'
);
}
if (count($inserts)) {
$cms->db->query('INSERT INTO forum_unread(
threadID,
catID,
forumID,
userID,
datetime,
threadtime) VALUES' .
implode(',', $inserts)) or die($cms->db->error);
}
Related
I am having a huge issue looping through results, These two queries work hand in hand to check if a restaurant is open today. My problem is i have restaurants, id 1-5(more in the future). But the loop seems to only get restaurant id 5. I have read many posts on here and it seems like i am doing the right thing. But i cannot seem to loop to get the other restaurant id's.
I am blocked now, newbie who is very open to any suggestions or advise.
$sel = "SELECT Rest_Details.Resturant_ID,Delivery_Pcode.Pcode,Delivery_Pcode.Restaurant_ID
FROM Rest_Details INNER JOIN Delivery_Pcode
ON Delivery_Pcode.Restaurant_ID=Rest_Details.Resturant_ID
WHERE Delivery_Pcode.Pcode LIKE'$searchP'";
$res = $dbc->query($sel);
if (!$res) {
echo "invalid query '" . mysqli_error($dbc) . "\n";
}
$i=1;
while ($row_res = $res->fetch_array()) {
$rest_ = $row_res['Resturant_ID'];
$i++;
}
date_default_timezone_set("Europe/London");
$daynum = jddayofweek(unixtojd());
$query = "SELECT *
FROM Opening_hrs WHERE
Restaurant_ID = $rest_
AND Day_of_week = $daynum";
$run_qu = $dbc->query($query);
if ($run_qu->num_rows > 0) {
while ($row_qu = $run_qu->fetch_assoc()) {
$message = "open" . $row_qu["Open_time"] . "</br>";
}
} else {
$message = $message . "close" . $row_qu["Closing_time"] . "</br>";
}
You could either output whatever you want to within your loop or build-up an output string because the value of $rest_ will always be the last value in the loop and i don't think that's what you want... Again you are doing the same with $message. And I am willing to bet that this is what you want to do:
<?php
date_default_timezone_set("Europe/London");
$sel = "SELECT Rest_Details.Resturant_ID,Delivery_Pcode.Pcode,Delivery_Pcode.Restaurant_ID
FROM Rest_Details INNER JOIN Delivery_Pcode
ON Delivery_Pcode.Restaurant_ID=Rest_Details.Resturant_ID
WHERE Delivery_Pcode.Pcode LIKE'$searchP'";
$res = $dbc->query($sel);
if (!$res) {
echo "invalid query '" . mysqli_error($dbc) . "\n";
}
$i=1;
while ($row_res = $res->fetch_array()) {
$rest_ = $row_res['Resturant_ID'];
$i++; // <== YOU DON'T NEED THIS VARIABLE....
// GET THE DATES WITHIN THE LOOP...
$daynum = jddayofweek(unixtojd());
$query = "SELECT *
FROM Opening_hrs WHERE
Restaurant_ID = $rest_
AND Day_of_week = $daynum";
$run_qu = $dbc->query($query);
if ($run_qu->num_rows > 0) {
while ($row_qu = $run_qu->fetch_assoc()) {
$message = "open" . $row_qu["Open_time"] . "</br>";
}
} else {
$message = $message . "close" . $row_qu["Closing_time"] . "</br>";
}
}
I think this is what you are trying to do.
// $searchP should be checked to prevent SQL injection.
$sel = "SELECT Rest_Details.Resturant_ID, Delivery_Pcode.Pcode,
Delivery_Pcode.Restaurant_ID
FROM Rest_Details INNER JOIN Delivery_Pcode
ON Delivery_Pcode.Restaurant_ID = Rest_Details.Resturant_IDW
WHERE Delivery_Pcode.Pcode LIKE '$searchP'";
$res = $dbc->query($sel);
if (!$res) {
echo "invalid query '" . mysqli_error($dbc) . "\n";
}
// set these once as they don't change
date_default_timezone_set("Europe/London");
$daynum = jddayofweek(unixtojd());
// $i=1; - not required, never used
// loop over the original results
while ($row_res = $res->fetch_array()) {
$rest_ = $row_res['Resturant_ID'];
//$i++; not used
// check for a match
$query = "SELECT * FROM Opening_hrs
WHERE Restaurant_ID = $rest_
AND Day_of_week = $daynum";
$run_qu = $dbc->query($query);
if ($run_qu->num_rows > 0) {
// at least one match
while ($row_qu = $run_qu->fetch_assoc()) {
$message = "open" . $row_qu["Open_time"] . "<br />";
$message .= "close" . $row_qu["Closing_time"] . "<br />";
}
} else {
// no matches
$message = "No results for <i>$daynum</i>.";
}
}
It should be possible to get the details in a single query, but I would need to see your SQL tables for that (and you did not ask for that too :]).
Also, it is <br> or <br />, not </br>.
I am new to joomla. I am using RSDirectory Component. In this i have to customize validation. i have a file named rsdirectory.php which is located at: administrator>components>com_resdirectory>helpers>rsdirectory.php.
I have a table, table1. In which a unique code is stored. Now i want to fill a form using that code if exist then query will execute otherwise my validation code will be execute. i have done this successfully. Now i have an another table, table2 in which my data is storing when i am filling a form with unique code. i just want to check my unique code whether it is exist in table2 or not. if exist validation will execute.i want to use same function for both.
Here is my code. Thanks in advance.
public static function uniquestacksfield($value, $column,$column1,$id1=null, $id = null){
// Get DBO.
$column = 'uni_code';
$db = JFactory::getDBO();
$query = $db->getQuery(true)
->select($db->qn('id'))
->from($db->qn('#_table1', 'e'))
->where($db->qn($column) . ' = ' . $db->q($value));
$db->setQuery($query);
$entry = $db->loadObject();
if ($id) {
$query->where($db->qn('e.id') . ' = ' . $db->q($id));
}
$db->setQuery($query, 0, 1);
return $db->loadResult();
/------------------another query-----------------------/
$column1 = 'uni_code2';
$db1 = JFactory::getDBO();
$query1 = $db1->getQuery(true)
->select($db1->qn('entry_id'))
->from($db1->qn('#_table2', 'c'))
->where($db1->qn($column1) . ' = ' . $db1->q($value));
$db1->setQuery($query1);
$entry1 = $db1->loadObject();
if ($id1) {
$query1->where($db1->qn('c_entry_id') . ' = ' . $db1->q($id1));
}
$db1->setQuery($query1, 0, 1);
return $db1->loadResult();
}`
I think below code is may be use.you can try it now. it is not good explain more to your criteria
public static function uniquestacksfield($value, $column,$column1,$id1=null, $id = null){
// Get DBO.
$db = JFactory::getDBO();
$column = 'uni_code';
$column1 = 'uni_code2';
if($column == 'uni_code') {
$query = $db->getQuery(true)
->select($db->qn('id'))
->from($db->qn('#_table1', 'e'))
->where($db->qn($column) . ' = ' . $db->q($value));
$db->setQuery($query);
$entry = $db->loadObject();
if ($id) {
$query->where($db->qn('e.id') . ' = ' . $db->q($id));
}
} else {
$query = $db->getQuery(true)
->select($db->qn('entry_id'))
->from($db->qn('#_table2', 'c'))
->where($db->qn($column1) . ' = ' . $db->q($value));
$db->setQuery($query);
$entry = $db1->loadObject();
if ($id) {
$query->where($db->qn('c_entry_id') . ' = ' . $db->q($id1));
}
}
$db->setQuery($query, 0, 1);
$item = $db->loadResult();
return $item;
}
I am a complete noob in php and trying to learn it by working on a premade script and making changes to it. I have been trying to figure out how to display titles by their first letters in a table. I went through this site http://www.emirplicanic.com/php/php-a-to-z-sorting-script but wasn't able to make it work in the script.
public function getProducts()
{
global $db, $core, $pager;
require_once(BASEPATH . "lib/class_paginate.php");
$pager = new Paginator();
$pager = new Paginator();
$counter = countEntries($this->pTable);
$pager->items_total = $counter;
$pager->default_ipp = $core->perpage;
$pager->paginate();
if ($counter == 0) {
$pager->limit = "";
}
if (isset($_GET['sort'])) {
list($sort, $order) = explode("-", $_GET['sort']);
$sort = sanitize($sort);
$order = sanitize($order);
if (in_array($sort, array("title", "cid", "price", "created"))) {
$ord = ($order == 'DESC') ? " DESC" : " ASC";
$sorting = " p." . $sort . $ord;
} else {
$sorting = " p.created DESC";
}
} else {
$sorting = " p.created DESC";
}
----------added by me-----------------
if (isset($_GET['letter'])) {
list($letter, $order1) = explode("-", $_GET['letter']);
$letter = sanitize($letter);
$order1 = sanitize($order1);
// if (in_array($sort, "A", "B", "C", "D"))) {
if (!(strcmp($letter, "A"))) {
$ord1 = ($order1 == 'DESC') ? " DESC" : " ASC";
$sorting1 = " p." . $letter . $ord1;
}
}
------------------------------------------------------------------
$sql = "SELECT p.*, p.id as pid, c.name, c.id as cid,"
. "\n DATE_FORMAT(p.created, '" . $core->short_date . "') as cdate,"
. "\n (SELECT COUNT(pid) FROM transactions WHERE pid = p.id) as sales"
. "\n FROM " . $this->pTable . " as p"
. "\n LEFT JOIN categories as c ON c.id = p.cid"
. "\n ORDER BY " . $sorting . $pager->limit;
$row = $db->fetch_all($sql);
return ($row) ? $row : 0;
}
and then the html part of it is
<li><span>A</span></li>
<li><span>B</span></li>
.
.
.
The php part is giving me an Undefined offset error. Also i am not sure if i have to add anything extra on the html to make it work
The URLS in your HTML should be ?letter=A-DESC. (or ASC) The list($letter, $order1) is expecting two results from the call to explode('-', $_GET['letter']), and it's only getting one. Thus, an 'undefined offset' in the array returned from explode().
Note that anyone can send anything in the ?letter part of the URL, not just what's in your links. You should "sanitize" (whatever that does for you) any input arguments as the very first step, and handle the situation where the data isn't what you expect before you start processing that data.
function get_user_id()
{
global $db;
$userid = NULL;
if (!empty($_COOKIE['PHPSESSID']))
{
$result = $db->execute("
SELECT profile_id
FROM " . TABLE_PREFIX . "profile_online
WHERE hash = '" . $db->escape_string($_COOKIE['PHPSESSID']) . "'
");
if ($row = $db->fetch_array($result))
{
$userid = $row[0];
}
}
return $userid;
}
function get_membership_id($userid)
{
global $db;
$result = $db->execute("
SELECT * FROM date_profile WHERE profile_id = '" . $db->escape_string($userid) . "'");
$mem = $db->fetch_array($result)
$membership = $mem[17];
return $membership;
}
the get_user_id is functioning fine... but the membership part i just can't get it to work..
I am trying to take the membership ids.. and make it so certain code will not run for them.
with an : if ($membership != 18 )
so it shows all everyone except the membership 18 people...
also tried this:
function get_membership_id($userid)
{
global $db;
$membership = $db->execute("SELECT `membership_type_id` FROM `date_profile` WHERE `profile_id`= '" . $db->escape_string($userid) . "'");
return $membership;
}
any help would be appreciated greatly.
missed ; here
$mem = $db->fetch_array($result);
^
You're missing semicolon after $mem = $db->fetch_array($result).
forgot to use TABLE_PREFIX constant.
SELECT * FROM " . TABLE_PREFIX . "date_profile WHERE profile_id ...
I've been learning about DRY code and my code isn't DRY...
For example, I have a custom CMS and I save basically a name, content and a publish status for a few things... like an article, a user, a event. To submit a form, I submit to a file (process.php) which has a switch in it like so:
switch($_POST['process']) {
case 'speaker':
if($_POST['speaker_id']) {
$sql = '
UPDATE speakers
SET speaker_name="' . mysql_escape_string($_POST['speaker_name']) . '",
speaker_content="' . mysql_escape_string($_POST['speaker_content']) . '",
speaker_status="' . $_POST['speaker_status'] . '"
WHERE speaker_id="' . $_POST['speaker_id'] . '"
LIMIT 1
';
} else {
$sql = '
INSERT INTO speakers
SET speaker_name="' . mysql_escape_string($_POST['speaker_name']) . '",
speaker_content="' . mysql_escape_string($_POST['speaker_content']) . '",
speaker_status="' . $_POST['speaker_status'] . '"
';
}
mysql_query($sql);
if($_POST['speaker_id']) {
header('Location: speakers?speaker_id=' . $_POST['speaker_id']);
} else {
header('Location: speakers?speaker_id=' . mysql_insert_id);
}
break;
case 'event':
if($_POST['event_id']) {
$sql = '
UPDATE events
SET event_name="' . mysql_escape_string($_POST['event_name']) . '",
event_content="' . mysql_escape_string($_POST['event_content']) . '",
event_status="' . $_POST['event_status'] . '"
WHERE event_id="' . $_POST['event_id'] . '"
LIMIT 1
';
} else {
$sql = '
INSERT INTO events
SET event_name="' . mysql_escape_string($_POST['event_name']) . '",
event_content="' . mysql_escape_string($_POST['event_content']) . '",
event_status="' . $_POST['event_status'] . '"
';
}
mysql_query($sql);
if($_POST['event_id']) {
header('Location: events?event_id=' . $_POST['event_id']);
} else {
header('Location: events?event_id=' . mysql_insert_id);
}
break;
case 'article':
if($_POST['article_id']) {
$sql = '
UPDATE articles
SET article_name="' . mysql_escape_string($_POST['article_name']) . '",
article_content="' . mysql_escape_string($_POST['article_content']) . '",
article_status="' . $_POST['article_status'] . '",
article_modified="' . $_POST['article_modified'] . '"
WHERE article_id="' . $_POST['article_id'] . '"
LIMIT 1
';
} else {
$sql = '
INSERT INTO articles
SET article_name="' . mysql_escape_string($_POST['article_name']) . '",
article_content="' . mysql_escape_string($_POST['article_content']) . '",
article_status="' . $_POST['article_status'] . '"
';
}
mysql_query($sql);
if($_POST['article_id']) {
header('Location: articles?article_id=' . $_POST['article_id']);
} else {
header('Location: articles?article_id=' . mysql_insert_id);
}
break;
}
Despite some basic variations, like different table names and column names, and perhaps there sometimes being a couple more or less columns to populate, the code is literally the same and programming like this feels more like data entry than creativity.
I imagine there's a way to create a class for this so that all the below code could be achieved in 1/3 the amount. Is there some sort of streamlined mysql insert / update method/strategy?
In my head, I'm thinking if I name all my inputs the same as they are in the table, ie if the column is called 'speaker_name' and the input is..
<input type="text" name="speaker_name" />
...I wonder if I could have a function which went through the $_POST array and simply updated the appropriate fields. Is this sound logic?
Perhaps I would have a hidden input in the form which was the 'table' variable which let the function know which table to update and it takes care of the rest.
Excuse me while I just thought out-loud. Any ideas would be really cool!
My newbie solution
Here's what I have i got working
if($_POST['id']) {
$sql = 'UPDATE ';
} else {
$sql = 'INSERT INTO ';
}
// number of rows in array
$total = count($_POST);
// number of commas = total of values minus 1
$commas = $total - 1;
// starting number
$count = 1;
foreach ($_POST as $key => $value) {
if($count == 1)
{
$sql .= mysql_real_escape_string($value) . ' SET ';
}
else
{
if( $count < $total )
{
$sql .= $key . '="' . mysql_real_escape_string($value) . '"';
if($count != $commas)
{
$sql .= ', ';
}
}
elseif( $_POST['id'] )
{
$sql .= ' WHERE ' . $key . '="' . mysql_real_escape_string($value) . '"';
}
}
$count = $count + 1;
}
mysql_query($sql);
if($_POST['id']) {
header('Location: ' . $_POST['process'] . '?id=' . $_POST['id'] . '');
} else {
header('Location: ' . $_POST['process'] . '?id=' . mysql_insert_id());
}
To do this means my form designs need to have a pretty strict setup ie the first hidden input holds the table name, the last input is the id number of the row in the table being edited (if it exists).
I know its far from good... but a lot better than the hundreds of lines it previously took.
1) some flaws in your concept
every piece of data you're going to put into quotes in your query, should be processed with
mysql_real_escape_string, as you cannot know what can be inside.
never use a table name passed from the client side. there can be malicious code instead of mere table name as well.
same for the field names. every identifier should be hardcoded in your script.
2) as for the DRY - it's simple. just note similar parts in your code and put them into function. only fields differ? okay, make a function that take fields list and produce an SQL statement of them.
Luckily, Mysql let us use similar syntax for both insert and update. So, a very simple function like this one can help:
function dbSet($fields) {
$set='';
foreach ($fields as $field) {
if (isset($_POST[$field])) {
$set.="`$field`='".mysql_real_escape_string($_POST[$field])."', ";
}
}
return substr($set, 0, -2);
}
So, you can make your code shorter:
case 'speaker':
$table = "speakers";
$fields = explode(" ","speaker_name speaker_content speaker_status");
if(isset($_POST['speaker_id'])) {
$id = intval($_POST['speaker_id']);
$query = "UPDATE $table SET ".dbSet($fields)." WHERE id=$id";
} else {
$query = "INSERT INTO $table SET ".dbSet($fields);
}
mysql_query($sql) or trigger_error(mysql_error().$query);
if($_POST['speaker_id']) $id = mysql_insert_id();
header('Location: speakers?speaker_id='.$id);
break;
if all your actions are such alike, you can make more high leveled functions:
case 'speaker':
$table = "speakers";
$fields = explode(" ","speaker_name speaker_content speaker_status");
if(isset($_POST['speaker_id'])) {
$id = intval($_POST['speaker_id']);
dbUpdate($table,$fields,$id);
} else {
$id = dbInsert($table,$fields);
}
header('Location: speakers?speaker_id='.$id);
exit;
break;
and even more high level
case 'speaker':
$table = "speakers";
$fields = explode(" ","speaker_name speaker_content speaker_status");
$id = dbMagic();
header('Location: speakers?speaker_id='.$id);
exit;
break;
But I won't go into that. I'd stop at 1st option, because it's pretty straightforward and there are always some little things not fit into such a broad concept.
While your alignment of column names and perhaps a hidden form field for table name would be quicker to code and more elegant to code against you would be opening yourself up to someone spoofing an HTML file to control the inserts to a table! Consider refactoring in other ways to optimize your library. Keep thinking / you're bound to come up with a better solution within the context of your problem domain.
Usually, one has some base models to do this, for example (don't be to harsh about it's failtings, I just want to give a short example):
class Speaker {
function __construct($data){
foreach($data as $key => $value) $this->$key = $value;
}
function save(){
$query =
($this->speaker_id ? 'UPDATE ':'INSERT INTO').' speakers '
."SET speaker_name='%s',
speaker_content='%s',
speaker_status='%s'"
.($this->speaker_id ? ' WHERE speaker_id=%d ':'');
mysql_query(sprintf($query(
mysql_real_escape_string($this->speaker_name),
mysql_real_escape_string($this->speaker_content),
mysql_real_escape_string($this->speaker_status),
intval($this->speaker_id)));
if(!$this->speaker_id) $this->speaker_id = mysql_insert_id();
}
}
And then:
switch($_POST['process']) {
case 'speaker':
$speaker = new Speaker($_POST);
$speaker->save();
header('Location: /speakers?speaker_id='.$speaker->speaker_id);
But for new projects, I would suggest a more complete MVC pattern (where Event & Speaker can be subclasses from some base databasemodel, possibly able to generate some form based on settings), and use prepared statements, they will make your sql queries easier & safer. never use addslashes, for good ol' mysql_query use mysql_real_escape_string