I'm asking MySQL for data, but it slows down the whole script. Yet I have no idea how to get this out of a loop. I tried converting it to PHP array but honestly after day of tries I failed.
<?php
$id = '1';
include_once 'include_once/connect.php';
for ($x = 1; $x <= 5; $x++) {
for ($y = 1; $y <= 5; $y++) {
$xy = $x."x".$y;
$pullMapInfo = "SELECT value FROM mapinfo WHERE id='".$id."' AND xy='".$xy."'";
$pullMapInfo2 = mysql_query($pullMapInfo) or die('error here');
if ($pullMapInfo3 = mysql_fetch_array($pullMapInfo2)) {
#some code
} else {
#some code
}
}
}
?>
How to get MySQL query $pullMapInfo2 out of loop to shorten loading it by asking once?
If you want to fire script on your localhost you can c&p whole thing :-)
I'm not sure what you have in your table, but considering you are basically looping through virtually everything in it, I'd say do a single query for the given Id and then sort out what you need from the larger dataset.
Especially if you are always pulling back essentially the complete dataset for each id, there's no reason to even bother with the IN query, just pull it all back into a single PHP array, and then iterate through that as needed.
Use a MySQL IN clause
<?php
$id = '1';
include_once 'include_once/connect.php';
// first we create an array with all xy
$array = array();
for ($x = 1; $x <= 5; $x++) {
for ($y = 1; $y <= 5; $y++) {
$xy = $x."x".$y;
$array[] = $xy;
}
}
$in = "'" . implode("', '", $array) . "'";
$pullMapInfo = "SELECT xy, value FROM mapinfo WHERE id='".$id."' AND xy IN ({$in})";
$pullMapInfo2 = mysql_query($pullMapInfo) or die('error here');
// we create an associative array xy => value
$result = array();
while (($pullMapInfo3 = mysql_fetch_assoc($pullMapInfo2)) !== false) {
$result[ $pullMapInfo3['xy'] ] = $pullMapInfo3['value'];
}
// we make a loop to display expected output
foreach ($array as $xy)
{
if (array_key_exists($xy, $result)) {
echo '<div class="castle_array" style="background-image: url(tiles/'.$result[$xy].'.BMP)" id="'.$xy.'">'. $result[$xy] .'</div>';
} else {
echo '<div class="castle_array" id="'.$xy.'"></div>';
}
echo '<div class="clear_both"></div>';
}
?>
Related
So basically I am trying to get the sum of AveragePrice of every single page on this api. Right now it only gets first page the things i've tried have only gotten it to go on an endless loop crashing wamp. Heres my code for 1 page of working.
I am just really unsure how I can get it to loop through pages and get sum of every page.
<?php
function getRap($userId){
$url = sprintf("https://www.roblox.com/Trade/InventoryHandler.ashx?userId=" . $userId . "&filter=0&page=1&itemsPerPage=14");
$results = file_get_contents($url);
$json = json_decode($results, true);
$data = $json['data']['InventoryItems'];
$rap = 0;
foreach($data as $var) {
$rap += $var['AveragePrice'];
}
echo $rap;
}
$userId = 1;
getRap($userId);
?>
You may get better answers by looking into the API you are working with regarding how many pages to look for. You want to loop until you hit the max pages. There should be an value in the result of your request that tells you that you've asked for a page that doesn't exist (ie. no more results). If you can get a total number of results to search for then you could do a for loop with that as your limit.
//Change the function to accept the page number as a variable
function getRap($userId, $i){
$url = sprintf("https://www.roblox.com/Trade/InventoryHandler.ashx?userId=" . $userId . "&filter=0&page=" . $i . "&itemsPerPage=14");
//work out how many pages it takes to include your total items
// ceil rounds a value up to next integer.
// ceil(20 / 14) = ceil(1.42..) == 2 ; It will return 2 and you will look for two pages
$limit = ceil($totalItems / $itemsPerPage);
// Then loop through calling the function passing the page number up to your limit.
for ($i = 0; $i < $limit; $i++) {
getRap($userId, $i);
}
If you cannot get the total number of items, you could loop while a fail state hasn't occured
// look for a fail state inside your getRap()
function getRap($userId, $i) {
if ($result = error) { //you will have to figure out what it returns on a fail
$tooMany = TRUE;
}
}
for ($i = 0; $tooMany !== TRUE ; $i++) {
getRap($userId, $i);
}
Edit: Reviewing my answer, looking for the fail state inside your function is poor form (and won't work because of the scope of the variable in this case). You could pass the variable back and forth, but I'll leave that part up to you.
To get the total, make sure that your function doesn't print the result (echo $rap) but returns it for further use.
Full example
<?php
function getRap($userId, $i){
$url = sprintf("https://www.roblox.com/Trade/InventoryHandler.ashx?userId=" . $userId . "&filter=0&page=" . $i . "&itemsPerPage=25");
$results = file_get_contents($url);
$json = json_decode($results, true);
if ($json['msg'] == "Inventory retreived!") {
$data = $json['data']['InventoryItems'];
$rap = 0;
foreach($data as $var) {
$rap += $var['AveragePrice'];
}
return $rap;
} else {
return FALSE;
}
}
$total = 0;
$userId = 1;
for ($i = 0; $i < 1000 /*arbitrary limit to prevent permanent loop*/ ; $i++) {
$result = getRap($userId, $i);
if ($result == FALSE) {
$pages = $i;
break;
} else {
$total += getRap($userId, $i);
}
}
echo "Total value of $total, across $pages pages";
?>
I have been working on my scoring system and came accros this.
I have 4 vars.
$newscore
$score1
$score2
$score3
I want to see if new score is lower than the 3 others, and if so which ones. The scoring system requires you to have the lowest possible score.
I have the following code:
if($newscore > $score1){
if($newscore > $score2){
if($newscore < $score3){
//has to be score3 to replace.
}
}else{
...
}
}
But what I'm wondering is if I will have to continue on with all these if statements, or is there something a lot shorter and easier? I need to replace the the score that it is smaller than, but not the one its larger than. Score 1 2 and 3 are all the players stats. And if I do have to continue on with all the if statements, how would the code look (its baffling my logic)?
you should probably use an array
$scores = array(8, 15, 10); //previous scores
$new_score = 5;
$new_score_smallest = true;
foreach($scores as $score) {
if($score < $new_score) {
$new_score_smallest = false;
}
}
if($new_score_smallest) {
echo "Best score!";
}
else {
echo "Not the best score :(";
}
If you only want to remember the 3 best scores:
$scores = array(5, 6, 8);
$new_score = 7;
for($i = 0; $i < count($scores); $i++) {
if($new_score < $scores[$i]) {
$scores[$i] = $new_score;
break;
}
}
You could do something like the following:
EDIT: As you're using a database, you would execute the query similar to this:
SELECT scores FROM scores_table replacing the table name and column name with your corresponding data.
$scores = [$score1, $score2] // add as many as you like
$new_score = $scores[0]; // assign a baseline
foreach ($scores as $score) {
if ($score < $new_score) {
$new_score = $score;
}
}
Hope that helps.
You can use array_search and min
$newscore = 2;
$scores = array($score1, $score2, $score3);
if($newscore < min($scores)){
$scores[array_search(min($scores), $scores)] = $newscore;
}
array $score lowest score will be updated if $newscore is inferior
Put your scores in an array or anything iterable (like a query result, whether you use PDO or mysqli).
Let's say your scores are in $scores array (it will be the same if $score is a PDOStatement for example) and ordered (use ORDER ASC in your query):
$scores = [105, 201, 305];
$newscore = '186';
$hiscore = false;
$beaten = [];
foreach ($score as $k => $score) {
if ($newscore > $score) {
$hiscore = true;
$beaten[] = $score;
unset($scores[$k]);
}
}
if ($hiscore) {
echo 'New high score!'.PHP_EOL;
echo 'Better than '.implode(', ', $beaten).PHP_EOL;
echo 'But not better than '.implode(', ', $scores);
} else {
echo 'Try harder!';
}
<?php
$newscore = 78;
$score1 = 23;
$score2 = 201;
$score3 = 107;
$max = max([$score1, $score2, $score3]);
if ($max < $newscore) {
echo "New best score ! ({$newscore})";
} else {
echo "Not the best score !\nCurrent: {$newscore}\nBest: {$max}";
}
I'm writing an export to excel & have a dynamic number of columns, i.e. I won't know how many columns will be needed before I run the query so I need to dynamically assign the column numbers like below:
$objPHPExcel->setActiveSheetIndex(0)
->setCellValue('A1', 'value')
->setCellValue('A2', 'value')
->setCellValue('B2', 'value')
->setCellValue('C2', 'value')
//...etc...
->setCellValue('AA2', 'value')
->setCellValue('AB2', 'value')
->setCellValue('AC2', 'value')
//...etc...
how can I do this with php?
UPDATE
sorry, the column naming pattern is:
A, B, C, .. AA, AB, AC ... BA, BB, BC... etc, the number suffix is actually the row. and no, the 'value would actually be populated from some query data setting my values would look more like:
$i=1;
while($result= $query->fetch_assoc()){
->setCellValue($col.$i, $result['whatever'])
$i++;
}
I just don't know how to get the column letters to increment in that pattern.
Simplest answer is
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
echo Coordinate::stringFromColumnIndex(5) // return E
echo Coordinate::columnIndexFromString('AA') // returns 27
Optimized Function
function columnFromIndex($number){
if($number === 0)
return "A";
$name='';
while($number>0){
$name=chr(65+$number%26).$name;
$number=intval($number/26)-1;
if($number === 0){
$name="A".$name;
break;
}
}
return $name;
}
If you don't know how many columns/rows you're going to be working with in advance, how can you expect to use the fluent interface in this way?
Following your edit of the question, you might do something like:
$i = 1;
while($result = $query->fetch_assoc()){
$col = 'A';
foreach($result as $value) {
$objPHPExcel->getActiveSheet()->setCellValue($col++.$i, $value);
}
$i++;
}
However, you might consider taking another approach, and using the fromArray() method to populate your data
$i = 1;
while($result = $query->fetch_assoc()){
$objPHPExcel->getActiveSheet()->fromArray('A'.$i++, $result);
}
Maybe so late, and i dont know if there's a better solution but, i make this recursive function to solve this problem
private function getLastColumn($last){ //last represent how mouch X axis spaces
//you want to jump
$max = 26; //Max characters (in number) that you cant jump, ('z´)
$inicial = 'A';
$col = '';
if ($last > $max) //if last is bigger than last you should recall the function
{
$last = $last - $max; //discount the max to the last
$letterAscii = ord($inicial); //tansform the charcter to to number
$letterAscii += ($last - 1); // add last -1(-1 to stay in A to keep the
//base 1)
$col = chr($letterAscii); // int to ascci
$col = $col.$this->getLastColumn($last); // recall the funcion and concat
//the result
}else{
$letterAscii = ord($inicial); // same as adove
$letterAscii += ($last - 1);
$col = chr($letterAscii); //only pass the result to col
}
return $col; //return coll
}
and with this if you need 27 spaces to de right you will get 'AA'
if there is a better solution teld me :)
i think is too late, but for my snippet
i make this function,
function number_to_column($num) {
$column_name = array();
for($i=0;$i<=$num;$i++) {
$numeric = $i % 26;
$letter = chr(65 + $numeric);
$num2 = intval($num / 26);
if ($num2 > 0) {
if($i<26) {
$v_column = $letter;
}
if($i>25 && $i<52) {
$v_column = 'A'.$letter;
}
if($i>51) {
$v_column = 'B'.$letter;
}
$column_name[] = $v_column;
} else {
$v_column = $letter;
$column_name[] = $v_column;
}
}
return $column_name;
}
then we can use it like this
$column_name = number_to_column(count($array[0])-1);
the $column_name will result excel row name,
I used this same code before and not like that just for one image at one time it is working fine there for showing img(stars)but now stars in first value is fine next it is collecting result with previous one
while ($query = mysql_fetch_array($tableone))
{
$Rating = $query['rating'];
$totalV = $query['total_votes'];
$commentcount = $query['comment_counts'];
if (!$Rating == 0 )
{
$number = $Rating / $totalV ;
$numbers = (round($number,3));
for ($x = 1 ; $x <= $numbers ; $x++)
{
$star .= '<img src="img/stars.gif" width="14%"/>';
}
$left = 5 - $numbers ;
for ($x = 1 ; $x <= $left ; $x++)
{
$result .='<img src="img/whitestar.gif" width="12%"/>';
}
if ( strpos($left, '.' ) == true)
{
$hs .= '<img src="img/halfwhitestar.gif" width="12%"/>';
}
$result1 = $star. $hs .$result;
}
else
{
$result1 ='Null';
}
if (empty($totalV))
{
$totalV = 'No votes';
}
$totalV ="/".$totalV;
$ratingbox = "<span id=\"ratingimg\">".$result1." </span>
<br/>
<span class=\"valueimg\">".$number.$totalV."</span>";
}
my Values in database of each image is
and this code is visible like this
this code i am using now for table for all images present in database including their some information...need guidance:S
Since you are concatenating strings during your loop, those strings just keep growing with each iteration of the loop.
I suggest that you reset these variables to blank strings upon each iteration of your while loop: $star, $hs, $result.
Something like this:
while ($query = mysql_fetch_array($tableone)) {
$star=$hs=$result='';
...
When I launch my web page, increment doesn't work correctly!
It should go like this: $i = from 1 to x (0,1,2,3,4,5,6 etc..).
But instead it jumps over every step giving result of (1,3,5,7 etc..).
Why is this code doing this?
<ul class="about">
<?php
$result = mysql_query("SELECT * FROM info WHERE id = 1");
while ($row = mysql_fetch_assoc($result))
{
$bioText = $row['bio'];
}
$endBioTxt = explode("\n", $bioText);
for ($i=0; $i < count($endBioTxt);)
{
if (checkNum($i) == true)
{
echo "<li class='left'><div>".$endBioTxt[$i]."</div></li>";
echo $i;
}
else
{
echo "<li class='right'><div>".$endBioTxt[$i]."</div></li>";
echo $i;
}
$i++;
}
// Function to check if number is prime
function checkNum($num){
return ($num % 2) ? TRUE : FALSE;
}
?>
</ul>
Output:
Sometext!(right side)
0
1
Sometext2!(right side)
2
3
...
Please DONT do this as other suggested:
for ($i=0; $i < count($endBioTxt); $i++)
do this:
$count = count($endBioTxt);
for ($i=0; $i < $count; $i++) {
}
No need to calculate the count every iteration.
Nacereddine was correct though about the fact that you don't need to do:
$i++;
inside your loop since the preferred (correct?) syntax is doing it in your loop call.
EDIT
You code just looks 'strange' to me.
Why are you doing:
while ($row = mysql_fetch_assoc($result))
{
$bioText = $row['bio'];
}
???
That would just set $bioText with the last record (bio value) in the recordset.
EDIT 2
Also I don't think you really need a function to calculate the modulo of a number.
EDIT 3
If I understand your answer correctly you want 0 to be in the left li and 1 in the right li 2 in the left again and so on.
This should do it:
$endBioTxt = explode("\n", $bioText);
$i = 0;
foreach ($endBioTxt as $txt)
{
$class = 'left';
if ($i%2 == 1) {
$class = 'right';
}
echo '<li class="'.$class.'"><div>'.$txt.'</div></li>';
echo $i; // no idea why you want to do this since it would be invalid html
$i++;
}
Your for statement should be:
for ($i=0; $i < count($endBioTxt); $i++)
see http://us.php.net/manual/en/control-structures.for.php
$i++; You don't need this line inside a for loop, it's withing the for loop declaration that you should put it.
for ($i=0; $i < count($endBioTxt);$i++)
{
if (checkNum($i) == true)
{
echo "<li class='left'><div>".$endBioTxt[$i]."</div></li>";
echo $i;
}
else
{
echo "<li class='right'><div>".$endBioTxt[$i]."</div></li>";
echo $i;
}
//$i++; You don't need this line inside a for loop otherwise $i will be incremented twice
}
Edit: Unrelated but this isn't how you check whether a number is prime or not
// Function to check if number is prime
function checkNum($num){
return ($num % 2) ? TRUE : FALSE;
}
This code works, please test it in your environment and then uncomment/comment what you need.
<?php
// This is how query should look like, not big fan of PHP but as far as I remember...
/*
$result = mysql_query("SELECT * FROM info WHERE id = 1");
$row = mysql_fetch_assoc($result);
$bioText = $row['bio'];
$endBioTxt = explode("\n", $bioText);
*/
$endBioTxt[0] = "one";
$endBioTxt[1] = "two";
$endBioTxt[2] = "three";
$endBioTxt[3] = "four";
$endBioTxt[4] = "five";
$totalElements = count($endBioTxt);
for ($i = 0; $i < $totalElements; $i++)
{
if ($i % 2)
{
echo "<li class='left'><div>".$endBioTxt[$i]."</div></li>";
}
else
{
echo "<li class='right'><div>".$endBioTxt[$i]."</div></li>";
}
/*
// This is how you should test if all your array elements are set
if (isset($endBioTxt[$i]) == false)
{
echo "Array has some values that are not set...";
}
*/
}
Edit 1
Try using $endBioTxt = preg_split('/$\R?^/m', $bioTxt); instead of explode.