foreach loop how to expect first result? [duplicate] - php

This question already has answers here:
PHP How to determine the first and last iteration in a foreach loop?
(21 answers)
Closed 7 years ago.
Using codeigniter framework i have this code here
<?php
foreach ($allposts as $posts) {
echo '<div class="col-sm-1">
<div class="thumbnail">
<img class="img-responsive user-photo" src="https://ssl.gstatic.com/accounts/ui/avatar_2x.png">
</div><!-- /thumbnail -->
</div><!-- /col-sm-1 -->
<div class="col-sm-11">
<div class="panel panel-default companel">
<div class="panel-heading companel-heading">
<strong>'.$posts->author_name.'</strong> <span class="text-muted">'.unix_to_human($posts->post_date).'</span>
</div>
<div class="panel-body">
'.$posts->post.'
</div><!-- /panel-body -->
</div><!-- /panel panel-default -->
</div><!-- /col-sm-11 -->';
}
?>
now i want to except first result or first post in my case ? it is possible
and another question may i do something like display posts but one by one i mean align one right and second one left?

You can initialize a variable outside the foreach and count inside the iteration.
$count=0;
foreach($allposts as $posts)
{
$count++; // incrememnt
if($count==1)
{
// this is the first post
}
}
Option 2:
Use for loop instead of foreach
for($i=0; $i<=count($allposts); $i++)
{
if($i==0) // this is the first post.
echo $allposts[$i];
}
Using CSS to float your posts:
.post:nth-child(odd){
float: left;
}
.post:nth-child(even){
float: right;
}

You can declare a var $count outside the foreach loop, initilize it to 0 and increment it at the end of the loop. At the beginning of the loop check if the $count variable is 0 - if that is the case - skip the echo.
To display one row aligned to the left and one to the right check the same $count variable: if $count%2 == 0 then align one direction else the other.

foreach($value as $k => $v)
{
if($k === 0)
{
continue;
}
// rest your case
}

Related

How to count the arrays from a result of a query? [duplicate]

This question already has answers here:
Echo current number of row
(3 answers)
Closed 1 year ago.
I have a query that I make using PHP and it returns me all the rows that satisfied the condition that was given, now, I'm wondering if there's a way to count each number of row a result of a query has and pass that number to an id of an element on HTML?
<?php
$res2 = mysqli_query($con,"SELECT NAME, PRICE FROM product WHERE AVAILABLE = 1 AND ID_CATEGORY = 17");
?>
<body>
<?php
while($row = mysqli_fetch_row($res2)) {
print_r($row);
?>
<div class="item">
<img class="trj_img_cls" src="RSC/COMING_SOON.jpg" alt="" id="imgDG<?php ?>">
<div class="texto_trj">
<div class="nombre_producto">
<h2 id="ttlDG<?php ?>">título</h2>
</div>
<div class="precio_producto">
<i class="icon-dollar"></i>
<label id="prDG<?php ?>">0.00</label>
</div>
<div class="caracteristicas">
<ul id="caractDG<?php ?>"></ul>
</div>
</div>
</div>
<?php
}
?>
</body>
I put <?php ?> because there I want to add the variable (number of the row) so it complements the actual id and then i'm able to look for that id with javascript. Another thing is that I use the print_r() just to see if the elements were appearing.
This can be done by setting an $increment variable to 1 at the start of the while loop, and incrementing it at the end of the loop.
<?php
$increment = 1;
while($row = mysqli_fetch_row($res2)) {
And then using it like this:
id="imgDG<?php echo $increment; ?>">
And then incrementing it at the end:
<?php
$increment++;
}
?>

Make all title elements the same height when some titles are longer than others and need to wrap

I am displaying information in a card-based layout, but if any title in the card is longer than 41 characters, it doesn't fit into the card.
I thought about using [wordwrap], but all that would do is cause the one specific title to wrap and change the height of that card, affecting the layout of the other cards.
This is the PHP I use to print my results for pagination purposes, so it only prints 9 things at a time.
<div class="row">
<?php
while ($row = mysql_fetch_assoc($rs_result)) {
?>
<div class="col xl4 l4 m12 s12">
<div class="card z-depth-5">
<div class="card-content">
<p><? echo $row["title"]; ?></p>
<p>Category: <? echo $row["category"]; ?></p>
</div>
</div>
</div>
<?php
};
?>
</div>
How would I go about line breaking every title if even one title is detected as longer than 41 characters?
EDIT: This is the solution I created:
$titlebreak = $row["title"];
if (strlen($titlebreak) >= 40)
{
$titlebreak2 = wordwrap($titlebreak, 39, "</p><p>");
}
else
{
$titlebreak2 = $row["title"] . "<p> </p>\n";
}
I've included 3 possible solutions below - adding manual line breaks as you asked about in your question; a basic but unsatisfactory CSS option and a jQuery solution which in this case is the one I would suggest as the most flexible.
Although a CSS-only solution is usually the preferred way of fixing a layout issue, when it comes to equal heights of elements there isn't a clear-cut way to do it and often a jQuery solution like the one below is required.
Manual line-break - as requested in your question
Instead of doing an additional SQL query as mentioned, you can easily do it in the PHP in 2 different ways:
(a) loop through the rows before displaying them to calculate the title lengths, then loop again to display with/without the line break
or
(b) if you really down't want to loop twice, you could include the line break regardless of length as you loop once, but also calculate the line length in that loop. Then hide the line break using CSS if its not required
(a) 2 loops: Calculate length to determine whether to add the line break or not:
<?php
$maxchars = 41;
$cards = array();
$bLongTitle = false;
while ($row = mysql_fetch_assoc($rs_result)) {
// save detaisl to $cards array
$cards[$row["title"]] = $row["category"];
// check title lengths until we find one over 41 - no need to check any more after that
if (!$bLongTitle && strlen($row["title"])) > $maxchars)
$bLongTitle = true;
}
?>
<div class="row">
<?php
foreach ($cards as $title => $category) {
?>
<div class="col xl4 l4 m12 s12">
<div class="card z-depth-5">
<div class="card-content">
<p><?
// if there were any long title, wrap them all text
if ($bLongTitle)
$title = wordwrap($title, $maxchars, "<br />\n");
echo $title;
?></p>
<p>Category: <? echo $category; ?></p>
</div>
</div>
</div>
<?php
}
?>
</div>
(b) 1 loop: Always display line break, and hide it if not required
<div class="row">
<?php
$bLongTitle = false;
while ($row = mysql_fetch_assoc($rs_result)) {
?>
<div class="col xl4 l4 m12 s12">
<div class="card z-depth-5">
<div class="card-content">
<p class="cardTitle"><? echo wordwrap($title, $maxchars, "<br />\n"); ?></p>
<p>Category: <? echo $row["category"]; ?></p>
<?php
// check title lengths until we find one over 41 - no need to check any more after that
if (!$bLongTitle && strlen($row["title"])) > $maxchars)
$bLongTitle = true;
?>
</div>
</div>
</div>
<?php
};
?>
</div>
<?php if ($bLongTitle) {?>
<script>.cardTitle br {display:none;}</script>
<?php } ?>
CSS-only solution - not viable for the OP?
Because the titles are aren't direct siblings, the only way would be to fix the height of all title. This isn't a desirable solution, as I'm sure titles can vary a lot in length so its impossible to pick a "default" height to suit every possibility, and even that's complicated by the responsive width of the columns potentially changing the heights dynamically.
But for the sake of completeness:
add a class (e.g. .cardTitle) to the title in your loop
identify suitable heights for the title with and without a line break, and set these in your CSS
add the corresponding class (e.g. wrapTitle) to your <p> if any title is too long in a loop (similar to adding a line break above)
CSS
p.cardTitle { height:20px; } /* example of the default height for title */
p.cardTitle.wraptitle { height:40px; } /* example of height for wrapped title */
PHP (after looping through SQL rows to fill $cards array as option (a) above)
<?php
foreach ($cards as $title => $category) {
?>
<div class="col xl4 l4 m12 s12">
<div class="card z-depth-5">
<div class="card-content">
<p class="cardTitle <?php if ($bLongTitle) echo "wrapTitle"; ?>"><? echo $title; ?></p>
<p>Category: <? echo $row["category"]; ?></p>
</div>
</div>
</div>
<?php
};
?>
jQuery
You could use jQuery to loop through all elements to calculate the heights, and set them all to the tallest.
You could write the code yourself (see How to make all div columns of the same height automatically with jQuery or Setting equal heights for div's with jQuery but there is a library available to do this for you: matchHeight
Using the library, all you need to do is include it on your page and call it like this (assuming you've added the class cardTitle to the <p> that holds your title)
jQuery(document).ready(function() {
$(".cardTitle").matchHeight();
});
I would perform a new SQL query first to see if any results have a title length of greater than 41 characters:
select count(*) from table where length(title)>41
And then set the result of this query to be a variable, e.g. $has41
You can then use an if statement within your loop ...
if($has41) {
// do something with $row['title']
} else {
// do something else with $row['title']
}

Looping to make outputs centered

I want to display all my categories in one page, 4 items per row.
If I have 4,8 or 12 items then I have no problem, however if I have 5 items or any "number of items" that is not divisible by 4 without any remainder appears on the next row (as I have set each item 25% of the screen with css) with subsequent gap space which looks really odd and empty. This is a problem and I call those remainder items indeBox as in independent boxes.
My end goal is to align those independent boxes on the centre.
I am trying to create an algorithm for this purpose.
Here is what I have done so far
The following function takes two parameters.
numberRestriction is the number of items allowed per row (4)
childrens is an object with all categories.
I am counting how many categories are present within the childrens object
and finding out if there are remainders.
function calculateDivision($numberRestriction, $childrens)
{
$arrayobj = new ArrayObject($childrens);
$itemLenght = $arrayobj->count();
$itemBasket = $itemLenght;
$remaining = $itemBasket % $numberRestriction;
return $remaining;
}
On the template
<?php
//$term = get_queried_object();
$childrens = get_categories(array('parent' => 27,'hide_empty' => false));
$rowRestriction =4;
$indeBox = calculateDivision($rowRestriction, $childrens);
$arrayobj = new ArrayObject($childrens);
$itemLenght = $arrayobj->count();
$i = 0;
if($indeBox == 0)
{
foreach($childrens as $index => $children)
{
$cat_image = z_taxonomy_image_url($children->term_id);
$cat_id = $children->term_id;
$desc = #explode('|', $term->description);
?>
<a href="<?php echo get_category_link($cat_id) ?>" >
<div class="food_list_single menus_list" style="background: url(<?php echo $cat_image ?>) no-repeat scroll right center / cover ">
<div class="food_hover menus_hover ">
<p style="width: 100%; overflow: hidden; padding: 10px; text-align: center;" class="food_hover_title_small"><?php echo $desc[2] ?></p>
<p class="food_hover_title"><?php echo $children->name ?></p>
<button class="btn btn-default food_button"><i class="fa fa-eye"></i>View Details</button>
</div>
</div>
</a>
<?php
} //foreach ends
}else
{
//loop all items
//set a counter
//everytime the counter reaches maximum item allowed in a row, counter should reset and add class to row even
//once it finds odd number in a row it should call the row uneven
$counter1 = 0;
foreach($childrens as $index => $children)
{
$counter1++;
$cat_image = z_taxonomy_image_url($children->term_id);
$cat_id = $children->term_id;
$desc = #explode('|', $term->description);
//out put div
?>
<a href="<?php echo get_category_link($cat_id) ?>" >
<div class="food_list_single menus_list" style="background: url(<?php echo $cat_image ?>) no-repeat scroll right center / cover ">
<div class="food_hover menus_hover ">
<p style="width: 100%; overflow: hidden; padding: 10px; text-align: center;" class="food_hover_title_small"><?php echo $desc[2] ?></p>
<p class="food_hover_title"><?php echo $children->name ?></p>
<button class="btn btn-default food_button"><i class="fa fa-eye"></i>View Details</button>
</div>
</div>
</a>
<?php
//also track the last items index
$last_items_index = $index;
?>
<?php
}
echo "Inde items :".$indeBox; //finds how many indeboxes
echo " Last items index " . $last_items_index ;
}
?>
Image
Solution: Not beautiful or efficient, but it works
Find out how many items in the array attach to a variable.
Find out how many boxes fit in a row and attach to a variable.
Calculate independent boxes using following function:
.
function calculateDivision($numberRestriction, $childrens)
{
$arrayobj = new ArrayObject($childrens);
$itemLenght = $arrayobj->count();
$itemBasket = $itemLenght;
$remaining = $itemBasket % $numberRestriction;
return $remaining;
}
Since I already know 4 boxes fit in a row, so there can only be either 1,2 or 3 independent boxes. and if there are 4 boxes then there are no independent boxes. I can run conditions
if($indeBox == 1)
{
//if there are one independent box remaining
//find the last item of the array and put a bootstrap class col-md-offset-3 to
//if not last item, no need for adding additional class
}
else if($indeBox == 2)
{
//if there are two independent boxes remaining
//find the second last item of the array and put a bootstrap class col-md-offset-3 to
//if not last item, no need for adding additional class
}
else if($indeBox == 3)
{
//if there are three independent box remaining
//find the third last item of the array and put a bootstrap class col-md-offset-3 to
//if not last item, no need for adding additional class
}

How to control foreach loop iteration in php

I want to fetch some data from database in the form of list. Following is my loop:
<div class="col-sm-4">
<ul>
<?php
foreach($subjects as $s)
{
echo "<li>$s->subject_title</li>";
}
?>
</u>
</div>
Now this loop prints data in one column and the user have to scroll down to view the last elements. I want to control the loop in such a way that after printing first 10 elements, it must start again from the div tag and print the next 10 elements and so on. I want to show the data in such a way that the user don't have to scroll down.
For example, I want to print the data in the following way:
I write the following code but it is not working. The div tag is only applied to the first 10 elements, and not on the rest of the data.
<div class="col-sm-6">
<ul class="filter-list">
<?php
$i = 0;
foreach($main_subjs as $i=>$ms)
{
if($i == 10) {
echo "</ul></div><div class='col-sm-6'><ul>";
$i++;
continue;
}
echo "<li><a href='#'>$ms->mains_title</a></li>";
}
?>
</ul>
</div>
Please Help.
As an arugment for a loop you can also use the key of array
foreach($subjects as $i=>$s)
When you will be able to "control" your loop, e.g.:
<div>
<?php
foreach($subjects as $i=>$s) {
if($i> 0 && $i % 5 == 0) {
echo "</div><div>";
}
echo "<li>$s->subject_title</li>";
}
?>
</div>

Yootheme ZOO - Application layout change in php

in ZOO Application/templates/uikit/_categories.php have this code:
<?php
// init vars
$i = 0;
$columns = $this->params->get('template.categories_cols', 2);
reset($this->selected_categories);
// render rows
while ((list($key, $category) = each($this->selected_categories))) {
if ($category && !($category->totalItemCount() || $this->params->get('config.show_empty_categories', false))) continue;
if ($i % $columns == 0) echo ($i > 0 ? '</div><hr class="uk-grid-divider"><div class="uk-grid">' : '<div class="uk-grid">');
echo '<div class="uk-width-1-'.$columns.'">'.$this->partial('category', compact('category')).'</div>';
$i++;
}
if (!empty($this->selected_categories)) {
echo '</div>';
}
?>
Render look like this:
<div class="uk-grid">
<div class="uk-width-1-3"></div>
<div class="uk-width-1-3"></div>
<div class="uk-width-1-3"></div>
</div>
<hr class="uk-grid-divider">
<div class="uk-grid">
<div class="uk-width-1-3"></div>
<div class="uk-width-1-3"></div>
<div class="uk-width-1-3"></div>
</div>
And I want this (only one div.uk-grid for all div.uk-width* and without hr.uk-grid.divider):
<div class="uk-grid">
<div class="uk-width-1-3"></div>
<div class="uk-width-1-3"></div>
<div class="uk-width-1-3"></div>
<div class="uk-width-1-3"></div>
<div class="uk-width-1-3"></div>
<div class="uk-width-1-3"></div>
</div>
Can someone help me with this, i am not good in php?
Thanks.
My modified code which not work :(
<?php
$columns = $this->params->get('template.categories_cols', 2); // I dont know why is at end ", 2"
reset($this->selected_categories); // I dont know why is needed reset array
// render rows
while ((list($key, $category) = each($this->selected_categories))) {
if ($category && !($category->totalItemCount() || $this->params->get('config.show_empty_categories', false))) {
echo '<div class="uk-grid">'; // I dont know why is not rendered
}
echo '<div class="uk-width-1-'.$columns.'">'.$this->partial('category', compact('category')).'</div>';
}
if (!empty($this->selected_categories)) {
echo '</div>';
}
?>
You must have set a parameter to add two columns, that's what kicks in the code that adds the separator.
The name of the parameter is template.categories_cols it will be translated though to something in english.
This is a commercially supported extension, you might be able to get some support on their forums
Your best bet would be to set your columns at 1, then use UIKit's CSS to size your divs. This means you'd want your container class to be uk-grid uk-grid-width-1-3, then to remove the uk-width-1-3 from the inner divs. The added benefit here is that you can vary layout depending on your screen size > Grid Component - UIKit.
In your PHP you could remove the columns param all together. Remove the line starting with $columns..., the single spot it's echo'd '.$columns.', and you should be all set.
The PHP was using your "columns" variable to split divs (2 was the default), but if you tailor the container you can avoid the column assignment altogether.

Categories