limit the number of entries in the for loop - php

I have a model and ready-made data in a table. In this model, I added a new field and made a connection with another table.
And in order not to manually fill in these fields for each record, I want to create a migration that will automatically fill in this field for all records.
Relationship table has two fields: post_id and author_id.
$posts = Posts::find()->all();
foreach ($posts as $index => $post) {
for($i = 0; $i < $index; $i++ ) {
$item = new PostAuthor();
$item->setAttribute('post_id', $posts->id);
$item->setAttribute('author_id', $i+1);
$item->save();
}
}
Now everything works so that the maximum number of author_id will be equal to the number of posts, i.e. for the first post it will be author_id: 1, for the second author_id: 1 and author_id: 2, and so on up to 6 author_id.
Can I limit the $index so that the maximum number here is 4, and when the author_id gets to 4, the loop starts over from 1?

$posts = Posts::find()->all();
foreach ($posts as $index => $post) {
for($i = 0; $j=0; $i < $index; $i++ ) {
if ( $j > 4 ) {
$j = 0;
}
$item = new PostAuthor();
$item->setAttribute('post_id', $posts->id);
$item->setAttribute('author_id', $j+1);
$item->save();
}
}

Related

limit the number of entries and restart after break in the for loop

The bounty expires in 5 days. Answers to this question are eligible for a +50 reputation bounty.
broken heart is looking for a canonical answer.
I have a model and ready-made data in a table. In this model, I added a new field and made a connection with another table.
And in order not to manually fill in these fields for each record, I want to create a migration that will automatically fill in this field for all records.
Relationship table has two fields: post_id and author_id.
I am trying to do like this:
$posts = Posts::find()->all();
foreach ($posts as $index => $post) {
for($i = 0, $j = 0; $i < $index; $j++, $i++) {
if ($j >= 4) {
break;
}
$item = new PostAuthor();
$item->setAttribute('post_id', $posts->id);
$item->setAttribute('author_id', $j + 1);
$item->save();
}
}
Or:
$posts = Posts::find()->all();
foreach ($posts as $index => $post) {
for($i = 0; $i < $index && $i < 4; $i++) {
$item = new PostAuthor();
$item->setAttribute('post_id', $posts->id);
$item->setAttribute('author_id', $i + 1);
$item->save();
}
}
But I get the same, only when j reaches 4, the cycle does not start again, and it adds everything else from 1 to 4:
Is it possible to make the loop start over for the post IDs I'm circling in the screenshot?
In idea my table should look like this
if($j===4){
continue 2;
}
When $j reaches 4 it will stop the for loop and continue with next post
You could save the URL string before making the ajax request and then, after receiving and handling the response, you could replace the unwanted URL with the old one you saved. This can be done with window.history.pushState()

Merging two product star ratings with foreach in Woocommerce

There may be a better way to state the question, but I'm workin' with what I know.
On Woocommerce I'm trying to get the _wc_rating_count for each star (1-5), but also for two products; then I want to combine theme; e.g., I am merging the reviews of two products on one page, in one graph.
I am doing that this way:
$product_id = array( 2146, 2166 );
$ratings = array(5, 4, 3, 2, 1);
foreach ($product_id as $pid) :
$product = wc_get_product($pid);
foreach ($ratings as $rating) :
$rating_count = $product->get_rating_count($rating);
$percentage = ($rating_count / $count) * 100 . "%";
//echo $rating_count . '<br/>';
endforeach;
endforeach;
The problem is, I'm getting an array of 10 items (2 products x 5 star ratings( 5,4,3,2,1), and I need those values merged.
11
1
0
0
2
8
0
0
0
1
Where I need it to be
19
1
0
0
3
Do you know how I may get two arrays out of the embedded foreachs and merge them based on the $ratings array?
Thanks for your help :)
So here is what do you like to achieve:
$product_ids = array( 2146, 2166 );
$ratings = array(5, 4, 3, 2, 1);
$rate_countings = array();
foreach ($product_ids as $pid){
$product = wc_get_product($pid);
foreach ($ratings as $rating){
$rating_count = $product->get_rating_count($rating);
//$percentage = ($rating_count / $count) * 100 . "%";
if( !isset($rate_countings[$rating]) ){
$rate_countings[$rating] = 0;
}
$rate_countings[$rating] += $rating_count;
}
}
var_dump($rate_countings);

Randomly add 'items' or 'ads' into PHP loop

I have an events loop set up; and I also have an ads loop set up.
I want to inject each 'ad' into the events loop at random points. These loops/arrays have different set ups so can't push into the loop/array.
I had the below set up, which tended to work, but within ad.inc it was getting a random ad... whereas it should be getting the total count of ads and injecting them randomly into the events until that count is reached.
$count = 1;
$total = count($events);
$random = rand(3, $total);
foreach ($events as $event) {
include('./inc/events-item.inc');
if ($count == $random) {
include("./inc/ad.inc");
$random = rand($count, $total);
}
$count++;
}
For example, if my total events count is 30, and my total ads count is 4 then I should see the four ads randomly injected into the 30 events.
Any help?
Create array of all positions for ads. If you have 30 ads - there're 30 positions, from 0 to 29:
$positions = range(0, 29);
// now get 4 random elements from this array:
$rand_positions = array_rand($positions, 4);
// though `array_rand` returns array of keys
// in this case keys are the same as values
// iterate over your events and if counter equals
// to any value in $rand_positions - show ad
$i = 0;
foreach ($events as $event) {
include('./inc/events-item.inc');
if (in_array($i, $rand_positions, true)) {
include("./inc/ad.inc");
}
$i++;
}
You need to randomly select 4 (or however many ads you have) points between 30 (or however many entries you have) other points. Here is a possible solution.
// Set up counts
$entry_count = count($events);
$ad_count = 4;
// Create an array of entry indices, and an array of ad indices
$entry_indices = range(0, $entry_count - 1);
$ad_indices = array();
// Fill the ad indices with random elements from the entry indices
for ($i = 0; $i < $ad_count; $i++) {
$entry = rand(0, count($entry_indices));
array_push($ad_indices, $entry_indices[$entry]);
array_splice($entry_indices, $entry, 1);
}
// Sort it so we only need to look at the first element
sort($ad_indices);
// Iterate through the events
$count = 0;
foreach ($events as $event) {
include('./inc/events-item.inc');
// If we have any ad indices left, see if this entry is one of them
if (count($ad_indices) > 0 && $count == $ad_indices[0]) {
include("./inc/ad.inc");
array_shift($ad_indices);
}
$count++;
}

Even distribution of PHP arrays across columns

So, I want to distribute evenly lists across 3 columns. The lists cannot be broken up or reordered.
At the moment, I have 5 lists each containing respectively 4, 4, 6, 3 and 3 items.
My initial approach was:
$lists = [4,4,6,3,3];
$columns = 3;
$total_links = 20;
$items_per_column = ceil($total_links/$columns);
$current_column = 1;
$counter = 0;
$lists_by_column = [];
foreach ($lists as $total_items) {
$counter += $total_items;
$lists_by_column[$current_column][] = $total_items;
if ($counter > $current_column*$links_per_column) {
$current_column++;
}
}
Results in:
[
[4],
[4,6],
[3,3]
]
But, I want it to look like this:
[
[4,4],
[6],
[3,3]
]
I want to always have the least possible variation in length between the columns.
Other examples of expected results:
[6,4,4,6] => [[6], [4,4], [6]]
[4,4,4,4,6] => [[4,4], [4,4], [6]]
[10,4,4,3,5] => [[10], [4,4], [3,5]]
[2,2,4,6,4,3,3,3] => [[2,2,4], [6,4], [3,3,3]]
Roughly what you need to do is loop over the number of columns within your foreach(). That will distribute them for you.
$numrows = ceil(count($lists) / $columns);
$thisrow = 1;
foreach ($lists as $total_items) {
if($thisrow < $numrows){
for($i = 1; $i <= $columns; $i++){
$lists_by_column[$i][] = $total_items;
}
}else{
//this is the last row
//find out how many columns need to fit.
//1 column is easy, it goes in the first column
//2 columns is when you'll need to skip the middle one
//3 columns is easy because it's full
}
$thisrow++;
}
This will be an even distribution, from left to right. But you actually want a modified even distribution that will look symmetrical to the eye. So within the foreach loop, you'll need to keep track of 1.) if you're on the last row of three, and 2.) if there are 2 remainders, to have it skip col2 and push to col3 instead. You'll need to set that up to be able to play around with it,...but you're just a couple of logic gates away from the land of milk and honey.
So, I ended up using this code:
$lists = [4,4,6,3,3];
$columns = 3;
$total_links = 20;
$items_per_column = ceil($total_links/$columns);
$current_column = 1;
$lists_by_column = [];
for ($i = 0; $i < count($lists); $i++) {
$total = $lists[$i];
$lists_by_column[$current_column][] = $lists[$i];
//Loop until reaching the end of the column
while ($total < $items_per_column && $i+1 < count($lists)) {
if ($total + $lists[$i+1] > $items_per_column) {
break;
}
$i++;
$total += $lists[$i];
$lists_by_column[$current_column][] = $lists[$i];
}
//When exiting the loop the last time we need another break
if (!isset($lists[$i+1])) {break;}
//If the last item goes onto the next column
if (abs($total - $items_per_column) < abs($total + $lists[$i+1] - $items_per_column)) {
$current_column++;
//If the last item goes onto the current column
} else if ($total + $lists[$i+1] > $items_per_column) {
$i++;
$lists_by_column[$current_column][] = $lists[$i];
$current_column++;
}
}

How to get sales ranking in PHP Codeigniter?

i am stuck in a logic. I want to generate a monthly base ranking of sales. The scenario of my ranking is, different sales man have different boxes to sold, they sold a box and i save there quantity of boxes. Now every person have different id and different no. of boxes sold. Can anyone suggest me how can i rank them?? I am using the code-igniter.
And i want to rank them in two different ways (no of boxes sold and amount of sales they generated)
Thanks in advance.
$rank = 0;
$array = array();
$j =0;
for($i = 0; $i <count($sales_ranking); $i++){
$quantity = 0;
$key = $sales_ranking[$i]->fmid;
if (in_array($key, $array)) {
echo "<br>__".$j = $j++;
continue;
}else{
array_push($array, $key);
$l = $i - $j;
for($j = 0; $j <count($sales_ranking); $j++){
if($sales_ranking[$i]->fmid == $sales_ranking[$j]->fmid){
$quantity = $quantity + $sales_ranking[$j]->qty;
$name[$l] = $this -> sales_rank -> get_name($sales_ranking[$i] -> fmid);
}else{
continue;
}
}
}
$qty[$l] = $quantity;
}

Categories