How can i repeat a while cicle in php? - php

I need to create a 'wall' of images.
There's my code:
<?php
$q = $db->prepare("SELECT * FROM wall");
$q->execute();
while($row = $q->fetch(PDO::FETCH_ASSOC)) { ?>
<div class="col-4-perc"><img src="<?=$site?>/assets/img/wall/<?=$row['source']?>.png"
alt="Foto wall" class="img-fluid"></div>
<?php } ?>
I would like to repeat the while loop repeating the photos in the database at least 3/4 times but I don't know how to do it.

As explained in the comments, you have to use FetchAll instead of fetch in a while. Here is a example script for the result you want:
$q = $db->prepare("SELECT * FROM wall");
$q->execute();
$allImage = $q->fetchAll() ;
$limit = 100 ;
$activeKey = 0 ;
for ($i = 0; $i < $limit ;$i++){
if (!isset($allImage[$activeKey]['source'])) {
$activeKey = 0 ;
// if the line does not exist, reset to the first key (0)
}
echo "<div class='col-4-perc'><img src='{$site}/assets/img/wall/{$allImage[$activeKey]['source']}.png'
alt='Foto wall' class='img-fluid'></div>";
$activeKey++ ;
}
Images are saved in $allImage, a table with numeric indexes. Next we just have to loop with a simple for using $limit (the max image you want display).
And $activeKey for the curent displayed image, if $allImage[$activeKey] is not set, reset to 0.

Related

PHP duplicate staffID

staff table
code
<?php
//db configuration
$q = "select * from staff";
$r = mysqli_query($dbc, $q);
$num_rows = mysqli_num_rows($r);
$staffID = array();
while($row = mysqli_fetch_array($r, MYSQLI_ASSOC))
{
$staffID[] = $row['staffID'];
}
for($i = 0; $i < $num_rows; $i++)
{
if($staffID[$i] == $staffID[$i+1])
{
$remark = "Not OK. Multiple staff ID selected.";
$i++;
}
else
{
$remark = "OK.";
}
$data[$i] = $staffID[$i].','.$remark.'<br />';
}
$list = array($data);
print_r($list);
?>
From above code, I want to check whether the staffID got duplicate.
Expected output
0001, OK.
0002, Not OK. Multiple staffID.
0003, OK.
0004, OK.
However, I get another error as below:
Undefined offset: 5 in play.php on line X.
How do I solve it?
By performing the correct query in the first place.
SELECT staffID
FROM staff
GROUP BY staffID
HAVING COUNT(staffID) > 1
Or if you need to know about all staff IDs:
SELECT staffID, COUNT(staffID) as qty
FROM staff
GROUP BY staffID
Just updating your code and i think you have to check the existence first :
if (isset($staffID[$i]) && isset($staffID[$i+!])) {
if($staffID[$i] == $staffID[$i+1])
{
$remark = "Not OK. Multiple staff ID selected.";
$i++;
}
else
{
$remark = "OK.";
}
$data[$i] = $staffID[$i].','.$remark.'<br />';
}
You get the error at this line:
if($staffID[$i] == $staffID[$i+1])
Say for example your $num_rows variable is 3. Then the $staffID array would have indexes 0, 1 and 2. But what happens at this line I noted is that once $i reaches 2 (which is a valid since it's less than 3) you go and do $i+1 which equals 3. And, as you can see, the index 3 is out of the bounds of the array.
If you wish to do this like you wrote your for loop should be like this:
for($i = 0; $i < $num_rows-1; $i++)
But, there is a better way without even doing the for loop. You can do it all in the while loop by making use of the in_array function. Or as Ignacio pointed out, you could do it all on the SQL level.
Not a good way to solve this problem. You should use GROUP BY query for this.
SELECT staffID, COUNT(staffID) as count
FROM staff
GROUP BY staffID
HAVING count > 1
And also about your error. It's because of
if($staffID[$i] == $staffID[$i+1])
on last iteration $i is equal 4 and $i+1 is 5. But $staffID array has no element with such key

PHP: for loop making page load very slowly on VPS

I'm new to php so I'm having trouble seeing where I'm going wrong with this code. I'm trying to pull a set of 4 random IDs to display their images and links on the page. Running the same code on my local dev environment works fine and the response is quick. On my VPS, however, the page will take 15-30 seconds to load. I managed to isolate the issue to this loop by just taking the whole block out and the page loads quickly again.
<?php
$alreadypicked = array();
for ($i = 1; $i <= 4; $i + 0) {
$randchoice = getinfoForRandom();
$info = pullrandinfo($randchoice);
if (!in_array($randchoice, $alreadypicked)) {?>
<div class="col-sm-3 col-xs-6">
<a href="<?php echo 'recipes.php?id=' . $info[0]['id'];?>">
<img class="img-responsive portfolio-item" src="<?php echo 'images/' . $info[0]['filename'];?>" alt="<?php echo $info[0]['name'];?>">
</a>
</div>
<?php
array_push($alreadypicked, $randchoice);
} else {
$i = $i - 1;
}
}?>
I tried doing the same with a while loop instead of an if/else statement, but that did not fix the slow loading.
Other relevant parts of code:
// Gets all IDs in database
function getIDs() {
$handler = dbconnector();
$query = $handler->query('SELECT id FROM dishes');
$query->setFetchMode(PDO::FETCH_ASSOC);
$output = $query->fetchAll();
$array = array();
for ($i = 0; $i < count($output); $i++) {
array_push($array, $output[$i]['id']);
}
return $array;
}
// Chooses a random ID that exists
function getinfoForRandom() {
$IDs = getIDs();
$totalIDs = count($IDs);
do {
$random = mt_rand(1, max($IDs));
} while (!in_array($random, $IDs));
return $random;
}
// Pulls data for the randomly selected ID
function pullrandinfo($id) {
$handler = dbconnector();
$query = $handler->query('SELECT id, name, filename FROM dishes WHERE id = ' . $id);
$query->setFetchMode(PDO::FETCH_ASSOC); // Fetches only assoc array from the query above
$data = $query->fetchAll();
return $data;
}
You can improve performance by limiting the number of queries that you execute.
Your code appears to execute two queries in each loop, one in getIds() and the other in pullrandinfo(). These queries are expensive and time-consuming.
Instead, fetch your IDs in a single query making use of SQL's RAND().
SELECT id FROM <table> ORDER BY RAND() LIMIT 4;
Then fetch all of the IDs in a single query:
'SELECT ... WHERE id IN (' . implode(',', $ids) . ')...'
Finally, use your loop only to output the data.

End Foreach after X number of records PHP

I have the following query:
$trabajos = $con->query("SELECT * FROM portafolio ORDER BY RAND() LIMIT 4");
while ($po = $trabajos->fetch_array()) {
$trab[] = $po;
}
This query is working fine, but, it shows only 4 records, but then again in another part of the same page I need the same table information but I don't want it to be limited, say I want 10 instead of only 4. so.
Section Header
Section Slider <-- here only shows 4 items as intended
Using a foreach as follow:
foreach ($trab as $it) {
// My html Code
}
Section Mid Body some info
Section Main Body More info
Section Mid End Footer <-- here I need the same information as in the slider section but with a different layout instead of only 4 items I need 10 items.
For that last item I have to open another query similar as before.
$trabajos = $con->query("SELECT * FROM portafolio ORDER BY RAND() LIMIT 10");
while ($po = $trabajos->fetch_array()) {
$trab[] = $po;
}
So I was thinking is there a way to use:
$trabajos = $con->query("SELECT * FROM portafolio ORDER BY RAND()");
while ($po = $trabajos->fetch_array()) {
$trab[] = $po;
}
That query without the LIMIT and instead Limit the foreach to only fetch the first 4 rows or is there a way to use that query with the LIMIT but instead of 4 or 10, say I use 20, and for the first foreach only display the first 4 and for the second foreach show the rest after the first 4.
The main idea is not have more than 1 query for the same information.
this will exit a loop, but why not query 10 records, build your results, all 10 and then just output 4 of them, there and all 10 over yonder.
$x = 0;
foreach ($trab as $it) {
if($x == 5){
break; //will exit loop as will return.
}
// My html Code
++$x;
}
This will work with any kind of loop, you can also use continue to skip to the next pass of the loop
foreach ($trab as $it) {
if($x < 5){
continue; //code below here wont run until $x >= 5.
}
// My html Code
++$x;
}
i'm not sure to understand exactly what you want, but if you want to divide your array in 2 part. You can use a counter
$trabajos = $con->query("SELECT * FROM portafolio ORDER BY RAND() LIMIT 20");
$i = 0;
$trab2 = new Array();
while ($po = $trabajos->fetch_array()) {
if($i < 4) {
$trab[] = $po;
} else {
$trab2[] = $po;
}
$i++;
}
First, RAND() is horrible since it essentially disables MySQL’s built in caching with each run of the query. But there is no best way for me to advise how to get around that based on your script’s requirements. So just keep that in mind. But here is what I would recommend.
That query without the LIMIT and instead Limit the foreach to only
fetch the first 4 rows or is there a way to use that query with the
LIMIT but instead of 4 or 10, say I use 20, and for the first
foreach only display the first 4 and for the second foreach show
the rest after the first 4.
Yes, just use array_slice like this:
$trabajos = $con->query("SELECT * FROM portafolio ORDER BY RAND() LIMIT 20");
while ($po = $trabajos->fetch_array()) {
$trab[] = $po;
}
$trab_slice_1_size = 4;
$trab_slice_2_size = 10;
$trab_slice_1 = array_slice($trab, 0, $trab_slice_1_size);
$trab_slice_2 = array_slice($trab, $trab_slice_1_size, $trab_slice_2_size);
The nice thing about array_slice is you can cleanly select a start & end point. In my example I set the sizes in variables. Which makes it easier to adjust in your code if you somehow want to dynamically change values.
The easiest way is to use a counter variable:
function fetch_items($limit=10) {
public $trabajos,$trab;
$count=0;
$trabajos = $con->query("SELECT * FROM portafolio ORDER BY RAND()");
while (($po = $trabajos->fetch_array()) && ($count<$limit)) {
$count++;
$trab[] = $po;
}
}
If you call fetch_items() without a parameter, it defaults to 10 or less. If you specify a parameter it loads the array with up to the amount you specify. You could also have the function return the value of $count so you know how many were returned.
try;
$trabajos = $con->query("SELECT * FROM portafolio ORDER BY RAND() LIMIT 10");
$i = 0;
while ($i < 5 && $po = $trabajos->fetch_array()) {
.....
.....
$i++;
}
then, if you want to re-use the data,
mysql_data_seek($trabajos, 0);
$i = 0;
while ($i < 11 && $po = $trabajos->fetch_array()) {
.....
.....
$i++;
}

Date comparison inside a "for loop" in php

I have a set of rows with five fields. My requirement is if "Internal_Deadline" field is greater than "Client_Deadline" in any of the rows, then it has to display a alert saying "Internal Deadline should not be greater than Client Deadline". Now it's checking only with the first row. I need to check with all the rows. Thanks
<?php
for( $i = 1; $i <= 100; $i++ )
{
$task = $_POST['task'.$i];
$Description = $_POST['Description'.$i];
$Internal_Deadline = $_POST['Internal_Deadline'.$i];
$Client_Deadline = $_POST['Client_Deadline'.$i];
$Actual_Deadline = $_POST['Actual_Deadline'.$i];
if(strtotime($Internal_Deadline) > strtotime($Client_Deadline)){
?>
<script>alert('Internal Deadline should not be greater than Client Deadline');</script>
<?php
}
else{
$result_task=mysql_query("select * from project_plan where p_id='$p_id' and task_no='$i'", $dbconnect1);
$row_task=mysql_fetch_array($result_task);
$id=$row_task['id'];
if(mysql_num_rows($result_task)!=0){
$update_result=mysql_query("update project_plan set Task='$task',Description='$Description',Internal_Deadline='$Internal_Deadline',Client_Deadline='$Client_Deadline',Actual_Deadline='$Actual_Deadline' where id='$id'", $dbconnect1);
}
else{
if($task!=""){
$que = mysql_query("insert INTO project_plan(task_no,Task,Description,Internal_Deadline,Client_Deadline,Actual_Deadline,Created_Date,p_id) VALUES ('".$i."','".$task."','".$Description."','".$Internal_Deadline."','".$Client_Deadline."','".$Actual_Deadline."','".$current_date."','".$p_id."')", $dbconnect1);
}
}
}
}
First of all the length of your for loop is not correct.
You need to run this loop exact same times to the post data count.
secondly i have tried locally with your given data(in your comment). it seems that is not met the condition:
if(strtotime($Internal_Deadline) > strtotime($Client_Deadline)){
try like this:
it will skip unnecessary loops. if you have task1,task2,task3 set in post data then it will run for 3 times not 100 times as your implementation.
$i=1;
while(isset($_POST['task'.$i]))
{
$task = $_POST['task'.$i];
$Description = $_POST['Description'.$i];
$Internal_Deadline = $_POST['Internal_Deadline'.$i];
$Client_Deadline = $_POST['Client_Deadline'.$i];
$Actual_Deadline = $_POST['Actual_Deadline'.$i];
if(strtotime($Internal_Deadline) > strtotime($Client_Deadline)){
?>
<script>alert('Internal Deadline should not be greater than Client Deadline');</script>
<?php
}
else{
$result_task=mysql_query("select * from project_plan where p_id='$p_id' and task_no='$i'", $dbconnect1);
$row_task=mysql_fetch_array($result_task);
$id=$row_task['id'];
if(mysql_num_rows($result_task)!=0){
$update_result=mysql_query("update project_plan set Task='$task',Description='$Description',Internal_Deadline='$Internal_Deadline',Client_Deadline='$Client_Deadline',Actual_Deadline='$Actual_Deadline' where id='$id'", $dbconnect1);
}
else{
if($task!=""){
$que = mysql_query("insert INTO project_plan(task_no,Task,Description,Internal_Deadline,Client_Deadline,Actual_Deadline,Created_Date,p_id) VALUES ('".$i."','".$task."','".$Description."','".$Internal_Deadline."','".$Client_Deadline."','".$Actual_Deadline."','".$current_date."','".$p_id."')", $dbconnect1);
}
}
}
$i =$i +1;
}

list mysql data in 3 columns alphabetical vertical

I have this statement that works fine, but list alphabetical from left to right across 3 columns. I want it to list alphabetical vertically down the column and then continue onto the next column. Anyone know how I can do this.
$models = mysql_query("SELECT model, id FROM model where make='$phonemake' order by model asc") or die(mysql_error());
$count = 0;
$max = 3;
while($model = mysql_fetch_array( $models ))
{
$count++;
echo "<div style='float:left; width:31%; padding-right:5px;'>".$model['model']." <a href='include/delete-model.php?id=".$model['id']."' onclick='return makesure".$model['id']."();'>Delete</a></div>";
if($count >= $max){
//reset counter
$count = 0;
//end and restart
echo"<div style='clear:both;'></div>";
You have two options:
You can buffer result into array and change the order of adding of divs
The code could look like this:
$allmodels = array();
while($model = mysql_fetch_array( $models ))
{
$allmodels[] = $model;
}
for($i = 0; 3 * $i < count($allmodels); $i++)
{
for($j = 0; $j < 3; $j++)
{
if(isset($allmodels[($i * 3) + $j]))
{
$model = $allmodels[($i * 3) + $j];
// print your stuff here...
}
}
}
Or you can somehow reorder items in the sql query, maybe dump that to the temporary table or play with mysql_data_seek.
echo the data in a UL LIST , and use your counter to set the number of rows in the UL LIST , when counter is reaches max, create a new list and continue displaying. Personally i would use:
if($counter%3==0) {
create new list
}
this way you dont need to reset the counter everytime.

Categories