Random number of divs with random number of elements with PHP - php

I need to generate random number of divs with five items per div (and remaining items in the last div) from random number of $totalItems and also not all the items satisfy $OKItems... Hopefully the code explains better than me.
My problem is that this script generates empty divs with no content in them.
<?php
$OKItems = 0;
$totalItems = rand(2,30);
for ($i = 0; $i < $totalItems; $i++) {
echo ($OKItems == 0 || $OKItems % 5 == 0) ? 'div open<br />' : '';
$testValue = rand(0, 1);
if ($testValue != 0) {
echo '1';
$OKItems++;
}
echo ($OKItems % 5 == 0 || $i+1 == $totalItems) ? '<br />div close<br />' : '';
}
?>
This is what I might get:
div open
div close
div open
11111
div close
div open
div close
div open
div close
div open
11
div close
And this is what I would have wanted in this case:
div open
11111
div close
div open
11
div close

<?php
const N = 5;
$totalItems = rand(2,30);
$items = array() ;
for ($i = 0; $i < $totalItems; $i++) {
$testValue = rand(0, 1);
if ($testValue != 0) {
$items[] = 1 ;
}
if( N == sizeof($items) || (($i == $totalItems - 1) && 0 < sizeof($items)) ) {
echo "<div>" . join(",", $items) . "</div>";
$items = array() ;
}
}

I think you need a bit more structure to your code.
My approach would be to break it up into several stages, as opposed to trying to do all the logic in the loop that outputs data.
What I'd suggest:
Decide how many items to be tested
Test each item and only copy the ones that pass into a new array
Partition this new array into sets of 5
Output each partition as a div
Code (untested):
// Decide how many items to test
$totalItems = rand(2,30);
// Test these items and add them to an accepted array
$items = Array();
for ($i = 0; $i < $totalItems; $i++) {
$testValue = rand(0, 1);
if ($testValue != 0) { $items[] = "1" }
}
//Partition them into sections
$partitions = array_chunk($items,5);
//Output as divs
foreach($partitions as $partition):
echo 'div open <br />';
foreach($partition as $item):
echo $item . "<br />";
endforeach;
echo 'div close <br />';
endforeach;
When you split up the code into logical steps, it becomes much easier to maintain and debug.

<?php
$OKItems = 0;
$totalItems = rand(2,30);
for ($i = 0; $i < $totalItems; $i++) {
echo ($OKItems == 0 || $OKItems % 5 == 0) ? 'div open<br>' : '';
$testValue = rand(0, 1);
if ($testValue != 0) {
echo '1';
$OKItems++;
}
if($OKItems % 5 == 0 || $i+1 == $totalItems) {
echo '<br>div close<br>';
$OKItems = 0;
}
}
?>
That should be working ;)
I changed your check line for an if function that also resets your $OKItems. The problem you had (i think) was that you got a 0 as the random value and that would keep $OKitems on 5.

Related

How to not create a big if list in this part of my code?

I don't want to create a big if list for all the story chapters of my website.
if $commentformname[$a] is equal to the number of the current chapter, then I make an array $commentonchapter1[$a] saying that a comment was inserted in the chapter 1, and chapter 2, and so on.
So if a comment was posted in the chapter 2, a array called commentonchapter2 will be created.
if ($sitecomments == true) {
$c = 0;
$i = 0;
$z = 0;
#defines the comment form name, name of who commented, the comment text and time (to be converted, example: 2020-04-09T15:53:07.580Za > 12:53 09/04/2020)
while ($c <= $commentsnumb) {
$commentformname[$z] = $comments[$i];
$i++;
$commenttername[$z] = $comments[$i];
$i++;
$commenttext[$z] = $comments[$i];
$i++;
$commenttime[$z] = $comments[$i];
$i++;
$c++;
$z++;
}
#shows the text of the comments tab
echo '<hr class="'.$sitehr2.'" />'."\n";
echo $divzoomanim.'<'.$n.'><p></p><br /><b>'.$tabnames[7].': '.$orangespan.$commentsnormalnumb.$spanc.' '.$icons[12].'</b><br /><br /><p></p></'.$n.'>'.$divc.'<hr class="'.$sitehr.'" />'."\n";
$i = 0;
$z = 0;
#converts the comment date and time
#example
#from 2020-04-09T15:53:07.580Za
#to 12:53 09/04/2020
while ($z <= $commentsnumb) {
$commenttime[$z] = substr($commenttime[$z], 0, -1);
$commenttime[$z] = date("H:i d/m/Y", strtotime($commenttime[$z]));
$z++;
}
$a = 0;
$z = 0;
$i = 0;
#styles the form name
#example
#from "pequenata-comment-7"
#to '<b>Commented on form "Pequenata-comment-7"</b>'
while ($a <= $commentsnumb) {
if ($lang == $langs[0] or $lang == $langs[1]) {
$commentformname[$i] = '<b>'.$commenttxt3.' '.$commenttxt5.' '.strtolower($formtxt).':</b> "'.ucwords($commentformname[$i]).'"';
}
if ($lang == $langs[2]) {
$commentformname[$i] = '<b>'.$commenttxt3.' '.$commenttxt4.' '.strtolower($formtxt).':</b> "'.ucwords($commentformname[$i]).'"';
}
$a++;
$z++;
$i++;
}
$a = 0;
$a2 = 1;
$i = 0;
$z = 0;
$c = 0;
$v = 0;
$b = 0;
$commentschapternumb = 0;
#Generates the array of the website comments
while ($c <= $commentsnumb) {
#Generates the comments of the website if the strlen of $commentformname[$a] is equal to 45, String: <b>Commented on form "Pequenata-comment-7"</b>
if (strlen($commentformname[$a]) == 45) {
$cmntsgeral[$b] = '<'.$m.' class="'.$textstyle2.'" style="text-align:left;border-width:3px;border-color:'.$bordercolor.';border-style:solid;"><div style="margin-left:5%;margin-right:5%;">'.'<br /><b>'.$a2.' - '.$commenttername[$i].'</b> - '.$commenttime[$i].'<br />'.$commentformname[$i].' '.'<hr class="'.$sitehr3.'" />'.$commenttext[$i].'<br /><br /><br /><br /><br />'.$divc.'</'.$m.'>'."<br />"."\n";
#Dispalyer disabled because of showing the wrong array (using $z, so it was tring to print a number on the array that didn't existed ($cmntschapter was incrementing on $z)
#echo $cmntsgeral[$z];
$a2++;
$b++;
}
#Generates the array of the chapter comments
if (strlen($commentformname[$a]) == 47) {
$cmntschapter[$v] = '<'.$m.' class="'.$textstyle2.'" style="text-align:left;border-width:3px;border-color:'.$bordercolor.';border-style:solid;"><div style="margin-left:5%;margin-right:5%;">'.'<br /><b>'.$a2.' - '.$commenttername[$i].'</b> - '.$commenttime[$i].'<br />'.$commentformname[$i].' '.'<hr class="'.$sitehr3.'" />'.$commenttext[$i].'<br /><br /><br /><br /><br />'.$divc.'</'.$m.'>'."<br />"."\n";
#Doesn't show the chapter comments because they shouldn't be showed in the website comments tab
#echo $cmntschapter[$z];
$v++;
$commentschapternumb++;
}
$a++;
$i++;
$z++;
$c++;
}
#Shows the website comments on the comments tab of the site
$z = 0;
while ($z <= $commentsnormalnumbtowrite) {
echo $cmntsgeral[$z];
$z++;
}
}

PHP: wrapping each group of 3 elements

I am trying to figure out how to write a loop that will wrap every group of 3 elements. However, for the last iteration, it should wrap whatever is left (be it one, two or three elements)
So basically this kind of pattern:
div
do stuff
do stuff
do stuff
end-div
div
do stuff
do stuff
do stuff
end-div
div
do stuff
do stuff
do stuff
end-div
div
do stuff
end-div
Here is where I'm at so far:
<?php
$counter = 0;
for ($i = 1; $i <= 10; $i++) {
if (($counter + 1) % 3 == 0) {
echo 'div <br />';
}
echo 'do stuff <br />';
if (($counter + 1) % 3 == 0) {
echo 'end-div <br />';
}
$counter ++;
}
?>
This is giving me the following:
do stuff
do stuff
div
do stuff
end-div
do stuff
do stuff
div
do stuff
end-div
do stuff
do stuff
div
do stuff
end-div
do stuff
Can anyone see where I'm going wrong?
In other words, you need to write div before each group of three items and end-div after each group of three items:
// $counter always tells the number of processed items
$counter = 0;
for ($i = 1; $i <= 10; $i++) {
// before a group of three, $counter is a multiple of three
if ($counter % 3 == 0) {
echo 'div <br />';
}
// process the item then count it
echo 'do stuff <br />';
$counter ++;
// after a group of three, $counter is a multiple of three
if ($counter % 3 == 0) {
echo 'end-div <br />';
}
}
// close the last group if it is not complete
if ($counter % 3 != 0) {
echo 'end-div <br />';
}
Check it online.
There's no need to use separate $counter variable, make use of $i variable in the for loop itself.
echo 'div <br />';
for ($i = 0; $i < 10; $i++) {
if($i != 0 && $i % 3 == 0)
echo 'end-div <br /> div <br />';
echo 'do stuff <br />';
}
echo 'end-div';
This is how I solved the problem
$total_items = 11;
for( $i = 0; $i < $total_items; $i ++ ){
// get the starting element
// the starting element will have ($i + 1 ) % 3 = 1
// all starting elements in the group will have a modulus of 1 when divided by 3
if( ( $i + 1 ) % 3 == 1 ){
echo "div <br />";
}
echo "do stuff <br />";
// the group will either end where ($i + 1 ) % 3 = 0
// or at the end of the count
// if total items are 2 then it will end at 2
if( ( $i + 1 ) % 3 == 0 || ( $i + 1 ) == $total_items ){
echo "end-div <br /><br />";
}
}
I ran my code using w3schools PHP compiler, please see the screenshot

variable increment doesn't work

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.

Print Array if Condition Exists

I'm working on a printing a baseball team lineup, via php. I want to print a place holder for a missing Player 6 (or any missing position)
So if Player 1 -> Player 5 is OK print, NO Player #6 print place holder, Player 7 -> Player 9 is OK print. I tried to simplify the code. I have tried solving this every which way but I keep getting stuck.
CODE:
$rot = array();
$pos = array();
$jn = array();
$x = 1;
// loads up the arrays from the db
while ( $rot[$x], $pos[$x], $jn[$x])= $r->fetch_row() ) {
$x++;
}
// counts the actual number of players in linuep
// used for validation and error display
$num_players = mysqli_num_rows($r);
// controls the lineup position
for ($i = 1; $i <= 15; $i++){
if($rot[$i] == $i) {
//prints player
$lineup .= "<div data-fp='" . $pos[$i] . "'>" .$jn[$i]. "</div>";
} else {
// prints place holder
$text = "This Position needs to be filled before the next game.";
$lineup .= "<div id='pid' data-rel='".$text."' data-fp='' data-pid='' data-jn='' title=''>x</div>";
}
}
I also tried this to iterate through the array rot[] to find the matching position and print the line but it actually prints the holder repeatedly.
// controls the lineup position
for ($x = 1; $x <= 15; $x++){
for ($i = 1; $i <= ($num_players+1); $i++) {
if ($x == $i) {
//prints player
$lineup .= "<div data-fp='" . $pos[$i] . "'>" .$jn[$i]. "</div>";
} else {
// prints place holder
$text = "This Position needs to be filled before the next game.";
$lineup .= "<div id='pid' data-rel='".$text."' data-fp='' data-pid='' data-jn='' title=''>x</div>";
}
}
}
What about:
# index all players by position while taking them from the database
$players = array();
while ( $row = $r->fetch_row() ) {
list($rot, $pos, $jn) = $row;
$players[$pos] = compact(array('rot', $pos, $jn);
}
...
# line-up players
for ($pos = 1; $pos <= 15; $pos++)
{
$playerExists = isset($players[$pos]);
if ($playerExists)
{
# do this ...
}
else
{
# do that ...
}
}
I think you are creating an array where all numerical elements are filled (i.e. you'll always have a 1 thru 15) and your mistake is in the
if($rot[$i] == $i) {
When populating the arrays from the database, add this line:
$playertoid = array_flip($pos); # pos is the player number array?
i.e.
while ( ($rot[$x], $pos[$x], $jn[$x])= $r->fetch_row() ) {
$x++;
}
$playertoid = array_flip($pos);
Now you've created a reverse lookup table where the index is the player number.
Replace the
if($rot[$i] == $i) {
line with:
if (isset($playertoid[$i])) {

PHP Pagination Problem

I'm having a problem with my PHP pagination for a project.
It almost works but it doesn't seem to display the numbers correctly.
I want only 6 more page numbers to display after the selected and one before;
(also if you are on page one display 7 after)
For example:
If on Page 1: 1/2/3/4/5/6/7/8
If on Page 2: 1/2/3/4/5/6/7/8
If on Page 5: 4/5/6/7/8/9/10/11
If on Page 10: 9/10/11/12/13/14/15/16
This is my code so far...
if($page == ceil($NumOfPages) && $page != 1){
for($i = 1; $i <= ceil($NumOfPages)-1; $i++){
if($i > 0){
echo "{$i}";
}
}
}
if ($page == ceil($NumOfPages) ) {
$startPage = $page;
}else{
$startPage = 1;
}
for ($i = $startPage; $i <= $page+6; $i++){
if ($i <= ceil($NumOfPages)){
if($i == $page) {
echo "<a href='/page/$i/' title='View movies page $i' id='pagelisel'>$i</a> ";
}else{
echo "<a href='/page/$i/' title='View movies page $i' id='pageli'>$i</a> ";
}
}
}
Any help would be greatly appreciated,
Thanks!
I assumed that (partly for myself... ;) ):
$page is the selected page
$startPage is the first page number you want to show
$numPages is already ceil-ed
First you need to find $startPage. Depending whether $page is the first one (ie has the value one 1, another assumption) or not. Your check is slightly off, as it check if it is equal to the last page.
if($page == 1) {
$startPage = 1;
} else {
$startPage = $page - 1;
}
Then you need to find out the last page number you want to print ($lastPage). So check if $startPage is near the end and set ~$lastPage` accordingly:
if($startPage + 7 > $numPages) {
$endPage = $numPages;
} else {
$endPage = $startPage + 7;
}
Finally, use you for-loop which seem ok, but loop from $startPage to $endPage.
Here's an alternative approach that should work for you as well:
$pageCurrent = $page;
$pagePrevious = $pageCurrent-1;
$pageClass = '';
$pageStart = 1;
$pageEnd = $pageCurrent+6;
$pageMax = ceil($NumOfPages);
if($pageCurrent==1){
echo "1";
}else{
echo "$pagePrevious";
}
for($i = $pageStart; $i <= $pageEnd; $i++){
if($i <= $pageEnd){
if($i == 1 && $pageCurrent != 1){
$pageClass = 'selected';
}else{
$pageClass = '';
}
echo "$i";
}
}

Categories