Working with multiple rows from a MySQL query - php

Before I begin, I want to point out that I can solve my problem. I've rehearsed enough in PHP to be able to get a workaround to what I'm trying to do. However I want to make it modular; without going too much into detail to further confuse my problem, I will simplify what I am trying to do so that way it does not detract from the purpose of what I'm doing. Keep that in mind.
I am developing a simple CMS to manage a user database and edit their information. It features pagination (which works), and a button to the left that you click to open up a form to edit their information and submit it to the database (which also works).
What does not work is displaying each row from MySQL in a table using a very basic script which I won't get into too much detail on how it works. But it basically does a database query with this:
SELECT * FROM users OFFSET (insert offset here) LIMIT (insert limit here)
Essentially, with pagination, it tells what number to offset, and the limit is how many users to display per page. These are set, defined, and tested to be accurate and they do work. However, I am not too familiar how to handle these results.
Here is an example query on page 2 for this CMS:
SELECT * FROM users OFFSET 10 LIMIT 10
This should return 10 rows, 10 users down in the database. And it does, when I try this command in command prompt, it gives me what I need:
But when I try to handle this data in PHP like this:
<?php
while ($row = $db->query($pagination->get_content(), "row")) {
print_r($row);
}
?>
$db->query method is:
public function query($sql, $type = "assoc") {
$this->last_query = $sql;
$result = mysql_query($sql, $this->connection);
$this->confirm_query($result);
if ($type == "row") {
return mysql_fetch_row($result);
} elseif ($type == "assoc" || true) {
return mysql_fetch_assoc($result);
} elseif ($type == "array") {
return mysql_fetch_array($result);
} elseif ($type == false) {
return $result;
}
}
$pagination->get_content method is:
public function get_content() {
global $db;
$query = $this->base_sql;
if (!isset($_GET["page"])) {
$query .= " LIMIT {$this->default_limit}";
return $query;
} elseif (isset($_GET["page"]) && $_GET["page"] == 1) {
$query .= " LIMIT {$this->default_limit}";
return $query;
} elseif (isset($_GET["page"])) {
$query .= " LIMIT {$this->default_limit}";
$query .= " OFFSET " . (($_GET["page"] * $this->default_limit) - 10);
return $query;
}
}
And my results from the while loop (which should print out each row of the database, no?) gives me the same row everytime, continuously until PHP hits the memory limit/timeout limit.
Forgive me if its something simple. I rarely ever handle database data in this manner. What I want it to do is show the 10 users I requested. Feel free to ask any questions.
AFTER SOME COMMENTS, I'VE DECIDED TO SWITCH TO MYSQLI FUNCTIONS AND IT WORKS
// performs a query, does a number of actions dependant on $type
public function query($sql, $type = false) {
$sql = $this->escape($sql);
if ($result = $this->db->query($sql)) {
if ($type == false) {
return $result;
} elseif ($type == true || "assoc") {
if ($result->num_rows >= 2) {
$array;
$i = 1;
while ($row = $result->fetch_assoc()) {
$array[$i] = $row;
$i++;
}
return $array;
} elseif ($result->num_rows == 1) {
return $result->fetch_assoc();
}
} elseif ($type == "array") {
if ($result->num_rows >= 2) {
$array;
$i = 1;
while ($row = $result->fetch_array()) {
$array[$i] = $row;
$i++;
}
return $array;
} elseif ($result->num_rows == 1) {
return $result->fetch_array();
}
}
} else {
die("There was an error running the query, throwing error: " . $this->db->error);
}
}
Basically, in short, I took my entire database, deleted it, and remade another one based on the OOD mysqli (using the class mysqli) and reformatted it into a class that extends mysqli. A better look at the full script can be found here:
http://pastebin.com/Bc00hESn
And yes, it does what I want it to. It queries multiple rows, and I can handle them however I wish using the very same methods I planned to do them in. Thank you for the help.

I think you should be using mysql_fetch_assoc():
<?php
while ($row = $db->query($pagination->get_content())) {
print_r($row);
}
?>

Related

What is a good percent for the similar text function for a mini-search engine?

I am creating a mini search engine for my new poll application. When you go to http://www.pollmc.com/search.php?s=mlg (website not up yet btw) it will search for a similar poll (I have a demo one called "Mlg Right?". It doesn't return it... But If I type in "Right" it does. It returns two polls; one called "Mlg Right?" and the other called "Cool Right?". What percent parameter is recommended for the is_similar text function? Here's my current code:
function search($s, $highPriority = true) {
$link = $this->connect();
$results = array();
$results_highpriority = array();
$results_lowpriority = array();
$query = mysqli_query($link, "SELECT * FROM polls");
while($row = mysqli_fetch_array($query)) {
array_push($results, $row);
}
foreach($results as $r) {
if(strtolower($r['question']) == strtolower($s)) {
array_push($results_highpriority, $r['question']);
continue;
}
/*if(strlen($s) >= 3 && strpos(strtolower($r['question']), strtolower($s)) !== false) {
array_push($results_lowpriority, $r['question']);
continue;
}*/
similar_text(strtolower($r['question']), strtolower($s), $resultPercent);
if($resultPercent >= 50) {
array_push($results_lowpriority, $r['question']);
continue;
}
}
return $highPriority ? $results_highpriority : $results_lowpriority;
}
I did have - commented out - if the question from MYSQL contains the query then add it (that seemed to work) but I'm worried it will return too much when I have like 20+ polls added. Here's my SQL database: http://prntscr.com/alr811

Terrible performance of this code

I am using codeigniter and mysql and i am trying to get some data from mssql server and updating to my system. Its very slow. please let me know if anything wrong i am doing..
class systemupdate extends MY_Controller{
function systemupdate() {
return parent::MY_Controller();
}
function index(){
$message = '';
$message = "CRON Information::COMMON INVENTORY SYSTEM: QUANTITY UPDATE FOR TRADE WH STARTED.";
log_message('info', $message);
$this->load->model("cis/sapinventorymodel");
$objMainResult = $this->sapinventorymodel->FetchDetailsByUnit(420);
$mainResult = json_decode($objMainResult);
if((isset($mainResult)) && ($mainResult->results > 0))
{
$this->load->model("cron/systemupdatemodel");
foreach($mainResult->rows as $main)
{
$arrQuantity = '';
$arrQuantity = $this->systemupdatemodel->FetchTradeWhQuantity($main->number);
if((isset($arrQuantity)) && (count($arrQuantity) > 0))
{
if((isset($arrQuantity[0]->quantity)) && ($arrQuantity[0]->quantity != NULL)){
$objMainResult = $this->sapinventorymodel->SaveTradeWhQuantity($main->a_umber, $main->a_plant,
$main->a_unit,$arrQuantity[0]->quantity);
}
}
}
}
$message = "CRON Information::COMMON INVENTORY SYSTEM: QUANTITY UPDATE FOR TRADE WH FINSIHED.";
log_message('info', $message);
}
}
Here is the model
class systemupdatemodel extends MY_Model {
function systemupdatemodel() {
parent::__construct();
$CI->sapData = $this->load->database("sapinventory", TRUE);
$this->sapData = &$CI->sapData;
}
function FetchTradeWhQuantity($p_intNumber){
$query = $this->sapData->query("SELECT quantity FROM master1 WHERE NUMBER = '$p_intNumber'");
if(($query->num_rows() > 0) && ($query->num_rows() == 1)){
return $query->result();
}else
{
$query1 = $this->sapData->query("SELECT quantity FROM master2 WHERE EANNUMBER = '$p_intNumber'");
if(($query1->num_rows() > 0) && ($query1->num_rows() == 1)){
return $query1->result();
}
}
}
}
Total number of records are 7857 i.e this many times its in loop. sapinventory is a mssql server.
FetchTradeWhQuantity and SaveTradeWhQuantity does a lot of runs in this case. That means (probably) at least 3 mysql queries per row. If you'd consider running this through 1 or 2 big queries instead, your performance would go up very noticeable.
Now this might be something easy to do, or something hard to do.
For instance;
function FetchTradeWhQuantity($p_intNumber){ ... }
Could be
function FetchTradeWhQuantity($p_intNumber) {
$query = $this->sapData->query("
SELECT quantity
FROM master 1
WHERE NUMBER = '{$p_intNumber}'
UNION
SELECT quantity
FROM master2
WHERE EANNUMBER = '{$p_intNumber}'
");
if ($query->num_rows() == 1)
return $query->result();
}
But the best thing you can do is to do all of this with 2-3 queries only. Fetch all data, use their IDs and run a UPDATE or INSERT INTO ... ON DUPLICATE KEY UPDATE. Then the server only have to connect to the mysql database a few times and doesn't have to play pinball with the php for each little row.

php if condition

I can't find anything wrong with this... This should work right?
function ConfirmedNumber()
{
$rs = mysql_query("CALL ConfirmedNumber('" , $_SESSION['UserID'] . "',#Active)");
while ($row = mysql_fetch_assoc($rs))
{
if ($row['Active'] = 1)
{
return true;
}
}
return false;
}
Assuming the Stored procedure returns a single row with the value '1' in it then I can call the function like this right?
if (ConfirmedNumber())
{
//do some stuff.
}
To expand on my comment:
if ($row['Active'] = 1) should be if ($row['Active'] == 1) to work correctly.
If you want to avoid accidentally doing this in future, you could write your if statements like this:
if (1 == $row['Active'])
This way, you can't accidentally use = as PHP will throw a Fatal Error. You can read more about Comparison Operators at PHP.net
Comment below with the full answer:
The call to the stored proc... line $rs = mysql_query("CALL ConfirmedNumber('" . $_SESSION['UserID'] . "',#Active)"); had a comma instead of the period in the initial post.
you forgot your operator in your IF statement. Change it to this:
if ($row['Active'] == 1)
or even shorter
if ($row['Active'])
it can be something like this
function ConfirmedNumber($id)
{
$rs = mysql_query("CALL ConfirmedNumber('" . $id . "',#Active)");
while ($row = mysql_fetch_assoc($rs))
{
if ($row['Active'] == 1)
{
return true;
}
}
return false;
}
ConfirmedNumber($_SESSION['UserID']);

How to check if results on while($row = mysql_fetch_array in PHP

Im trying to figure out how to handle this is no results are returned, how would I code that?
while($row = mysql_fetch_array($Result))
So like if there a results: print them out
else: show a link
http://ca3.php.net/manual/en/function.mysql-num-rows.php
if(mysql_num_rows($result) > 0) {
while($row = mysql_fetch_array($result)) { ... }
} else {
// show link
}
You can use mysql_num_rows() to tell you how many results are found. Using that with a simple if-statement, and you can determine what action to take.
if (mysql_num_rows($result) > 0) {
// do while loop
} else {
// show link
}
Others suggest using mysql_num_rows() but you should be aware that that function works only if you use a buffered query. If you query using mysql_unbuffered_query(), the number of rows in the result is not available.
I would use a simple flag variable:
$found_row = false;
while ($row = mysql_fetch_array($result)) {
$found_row = true;
. . .
}
if ($found_row == false) {
// show link
}
It may seem redundant to set $found_row to true repeatedly, but assigning a literal value to a variable ought to be an insignificant expense in any language. Certainly it is small compared to fetching and processing an SQL query result.
Use even shorter syntax without insignificant mysql_num_rows to save processor time:
if($result) {
// return db results
} else {
// no result
}
I might have figured it out:
if (!($row = mysql_fetch_array($descResult)))
{
echo "<tr><td>Add Link</td></tr>";
}
This can be done without mysql_num_rows() or an additional (flag) variable
if ( false===($row=mysql_fetch_array($result, MYSQL_ASSOC)) ) {
echo 'no rows in result set';
}
else {
do {
echo $row['X'];
} while ( false===($row=mysql_fetch_array($result, MYSQL_ASSOC)) );
}
but it duplicates the actual fetch command (one in the if-statement and one in the while-clause).

Is there a piece of public code available to create a page index using PHP?

I have a MySQL table holding lots of records that i want to give the user access to. I don't want to dump the entire table to the page so i need to break it up into 25 records at a time, so i need a page index. You have probably seen these on other pages, they kind of look like this at the base of the page:
< 1 2 3 4 5 6 7 8 9 >
For example, when the user clicks on the '4' link, the page refreshes and the offset is moved on (4th page x 25 records). Here is what i already have:
function CreatePageIndex($ItemsPerPage, $TotalNumberOfItems, $CurrentOffset, $URL, $URLArguments = array())
{
foreach($URLArguments as $Key => $Value)
{
if($FirstIndexDone == false)
{
$URL .= sprintf("?%s=%s", $Key, $Value);
$FirstIndexDone = true;
}
else
{
$URL .= sprintf("&%s=%s", $Key, $Value);
}
}
Print("<div id=\"ResultsNavigation\">");
Print("Page: ");
Print("<span class=\"Links\">");
$NumberOfPages = ceil($TotalNumberOfItems / $ItemsPerPage);
for($x = 0; $x < $NumberOfPages; $x++)
{
if($x == $CurrentOffset / $ItemsPerPage)
{
Print("<span class=\"Selected\">".($x + 1)." </span>");
}
else
{
if(empty($URLArguments))
{
Print("".($x + 1)." ");
}
else
{
Print("".($x + 1)." ");
}
}
}
Print("</span>");
Print(" (".$TotalNumberOfItems." results)");
Print("</div>");
}
Obviously this piece of code does not create a dynamic index, it just dumps the whole index at the bottom of the page for every page available. What i need is a dynamic solution that only shows the previous 5 pages and next 5 pages (if they exist) along with a >> or something to move ahead 5 or so pages.
Anybody seen an elegant and reusable way of implementing this as i feel i'm re-inventing the wheel? Any help is appreciated.
Zend Framework is becoming a useful collection and includes a Zend_Paginator class, which might be worth a look. Bit of a learning curve and might only be worth it if you want to invest the time in using other classes from the framework.
It's not too hard to roll your own though. Get a total count of records with a COUNT(*) query, then obtain a page of results with a LIMIT clause.
For example, if you want 20 items per page, page 1 would have LIMIT 0,20 while page 2 would be LIMIT 20,20, for example
$count=getTotalItemCount();
$pagesize=20;
$totalpages=ceil($count/$pagesize);
$currentpage=isset($_GET['pg'])?intval($_GET['pg']):1;
$currentpage=min(max($currentpage, 1),$totalpages);
$offset=($currentpage-1)*$pagesize;
$limit="LIMIT $offset,$pagesize";
It's called Pagination:
a few examples:
A nice one without SQL
A long tutorial
Another tutorial
And Another
And of course.. google
How about this jQuery-plugin?
So all the work is done on the clientside.
http://plugins.jquery.com/project/pagination
demo: http://d-scribe.de/webtools/jquery-pagination/demo/demo_options.htm
Heres an old class I dug out that I used to use in PHP. Now I handle most of it in Javascript. The object takes an array (that you are using to split the stack into pages) and return the current view. This can become tedious on giant tables so keep that in mind. I generally use it for paging through small data sets of under 1000 items. It can also optionally generate your jump menu for you.
class pagination {
function pageTotal($resultCount, $splitCount) {
if (is_numeric($resultCount) && is_numeric($splitCount)) {
if ($resultCount > $splitCount) {
$pageAverage = (integer)$resultCount / $splitCount;
$pageTotal = ceil($pageAverage);
return $pageTotal;
} else {
return 1;
}
} else {
return false;
}
}
function pageTotalFromStack($resultArray, $splitCount) {
if (is_numeric($splitCount) && is_array($resultStack)) {
if (count($resultStack) > $splitCount) {
$resultCount = count($resultStack);
$pageAverage = (integer)$resultCount / $splitCount;
$pageTotal = ceil($pageAverage);
return $pageTotal;
} else {
return 1;
}
} else {
return false;
}
}
function makePaginationURL($preURL, $pageTotal, $selected=0, $linkAttr=0, $selectedAttr=0) {
if (!empty($preURL) && $pageTotal >= 1) {
$pageSeed = 1;
$passFlag = 0;
$regLink = '<a href="{url}&p={page}"';
if (is_array($linkAttr)) $regLink .= $this->setAttributes($linkAttr); //set attributes
$regLink .= '>{page}</a>';
$selLink = '<a href="{url}&p={page}"';
if (is_array($selectedAttr)) $selLink .= $this->setAttributes($selectedAttr); //set attributes
$selLink .= '>{page}</a>';
while($pageSeed <= $pageTotal) {
if ($pageSeed == $selected) {
$newPageLink = str_replace('{url}', $preURL, $selLink);
$newPageLink = str_replace('{page}', $pageSeed, $newPageLink);
} else {
$newPageLink = str_replace('{url}', $preURL, $regLink);
$newPageLink = str_replace('{page}', $pageSeed, $newPageLink);
}
if ($passFlag == 0) {
$passFlag = 1;
$linkStack = $newPageLink;
} else {
$linkStack .= ', ' . $newPageLink;
}
$pageSeed++;
}
return $linkStack;
} else {
return false;
}
}
function splitPageArrayStack($stackArray, $chunkSize) {
if (is_array($stackArray) && is_numeric($chunkSize)) {
return $multiArray = array_chunk($stackArray, $chunkSize);
} else {
return false;
}
}
}

Categories