I am trying to figure out how I can amend part of the array name dynamically within a foreach.
I have a variable $i which is increased on each loop. Within the loop, I want to change X of ['new_row_X'] to whatever the $i is equal to. So for example:
$i = '10';
foreach( $order->items as $item ) {
$data['field_id_185']['rows']['new_row_10']['col_id_25'] = 'Entry ID';
$i++
}
OR
$i = '5';
foreach( $order->items as $item ) {
$data['field_id_185']['rows']['new_row_5']['col_id_25'] = 'Entry ID';
$i++
}
Just concatenate the index:
<?php
$i=0;
foreach($order -> items as $item) {
$data['field_id_185']['row']['new_row_'.$i]['col_id_25'] = 'Entry ID';
$i++;
}
$i = '10';
foreach( $order->items as $item ) {
foreach($data['field_id_185']['rows'] as $key=>$value) {
if (preg_match('/^new_row_.+$/', $key)) {
$data['field_id_185']['rows']["new_row_$ii"] = $value;
unset($data['field_id_185']['rows'][$key]);
}
}
$i++;
}
Related
I am trying to group items within a PHP foreach by their 'field->value' and get the sum of each group separately. This code below works, but I feel like there is a more efficient way of doing it?
Thanks in advance.
<?php
$number_1 = 0;
$number_2 = 0;
$number_3 = 0;
foreach ( $fields as $field ) {
if($field->value == 1) {
$number_1 += $field->number;
}
if($field->value == 2) {
$number_2 += $field->number;
}
if($field->value == 3) {
$number_3 += $field->number;
}
}
echo $number_1;
echo $number_2;
echo $number_3;
?>
In this case you can use variable variables.
Generally I would rather recommend an array but it's your choice.
foreach ( $fields as $field ) {
${"number_" . $field->value} += $field->number;
}
Array version.
foreach ( $fields as $field ) {
$arr["number_" . $field->value] += $field->number;
}
// Either output as array or extract values to separate variables.
Echo $arr["number_1"];
//Or
Extract($arr);
Echo $number_1;
Edit had number where it should be value.
Don't use separate variables, use an array with $field->value as the index.
$numbers = array();
foreach ($fields as $field) {
if (isset($numbers[$field->value])) {
$numbers[$field->value] += $field->number;
} else {
$numbers[$field->value] = $field->number;
}
}
I'm looping in an array, filling it with data from a file.
I'm trying to change the data from one cell to another and then leave the old cell empty.
So far I was using this code and it worked:
$custom_array_price['b'] = $custom_array_price['c'];
unset($custom_array_price['c']);
But for this specific case it doesn't work. It deletes the data before it gets copied.
How do I make it work?
This is the code I'm trying to use now:
$custom_array_price['c'] = $custom_array_price['d'];
unset($custom_array_price['d']);
The loop looks like this:
foreach ( $custom_array_price as $custom_key => $custom_value ) {
$custom_value = utf8_encode($custom_value);
if ( $custom_key == 'a' ){
if ( $custom_value == "Fecha:" ){
if( count($recibos) > 0 ){
$recibos[$cont]['html'].= "</tr>";
$recibos[$cont]['html'].= "</table>";
$cont++;
$times = 0;
}
$recibos[$cont]['html'] = "<table>";
$recibos[$cont]['html'].= "<tr>";
}else{
$recibos[$cont]['html'].= "<tr>";
}
}
if ( $times <= 5 ){
$custom_array_price['b'] = $custom_array_price['c'];
$custom_array_price['c'] = $custom_array_price['d'];
unset($custom_array_price['d']);
}
if ( $custom_value == "Neto a Pagar:"){
$custom_array_price['l'] = $custom_array_price['k'];
unset($custom_array_price['k']);
}
if ( $custom_value == "A001"){
$custom_array_price['g'] = $custom_array_price['i'];
unset($custom_array_price['i']);
}
$recibos[$cont]['html'].= "<td>";
$recibos[$cont]['html'].= $custom_value;
$recibos[$cont]['html'].= "</td>";
}
$recibos[$cont]['html'].= "</tr>";
Another part of the code. Where the csv file is being read and the data is being copied:
$recibos = array();
foreach($data_rows_price as $key => $value){
$times++;
for($i = 0; $i < count($value); $i++){
if(array_key_exists('mapping'.$i,$ret_array)){
if($ret_array['mapping'.$i]!='add_custom'.$i){
$new_post[$ret_array['mapping'.$i]] = $value[$i];
}
else{
$new_post[$ret_array['textbox'.$i]] = $value[$i];
$custom_array_price[$ret_array['textbox'.$i]] = $value[$i];
}
}
}
for($inc = 0; $inc < count($value); $inc++){
foreach($keys_price as $k => $v){
if(array_key_exists($v,$new_post)){
$custom_array_price[$v] = $new_post[$v];
}
}
}
I can't figure out a way to do this and I really bad with working with arrays so I hope someone can help me.
I have array $stuck that just contains names, like this
$stuck = array('Daniel','Alex','alfredo','dina');
I am using sort to put the names in alphabetical order, like this
sort($stuck);
Now the thing is I want to put this array into a csv or excel file so the first letter of name will be the title and all the names with this letter will be under this title.
This is an example of what I am trying to accomplish
Here try this. I added comments between the code.
$csvArray = array();
$nameArray = array('Daniel','Alex','alfredo','dina');
//Create an array that can be used for creating the CSV
foreach($nameArray as $name)
{
$firstLetter = strtoupper(substr($name, 0,1));
$csvArray[$firstLetter][] = $name;
}
//Determine the subarray which have the must rules
$maxRuleCount = 0;
foreach($csvArray as $firstLetter => $nameArray)
{
if(count($nameArray) > $maxRuleCount)
{
$maxRuleCount = count($nameArray);
}
}
//Create the first rule (letters)
$csvContent = implode(';', array_keys($csvArray));
$csvContent .= "\r\n";
//Loop through the CSV array and create rules of the names
for($i = 0 ; $i < $maxRuleCount ; $i++)
{
foreach($csvArray as $firstLetter => $nameArray)
{
$csvContent .= #$csvArray[$firstLetter][$i].';';
}
$csvContent .= "\r\n";
}
//The hole csv content is in the $csvContent variable now
//If you want to print it you need to add the text/plain header because of the \r\n new line characters
header("Content-Type:text/plain");
echo $csvContent;
Ouput is:
D;A
Daniel;Alex;
dina;alfredo;
<?php
$stuck = array('Daniel','Alex','Dina','durban','eigor','alfredo','dina');
// associate names with first letters in a new array
foreach ($stuck as $name) {
$first_letter = strtoupper( substr( $name, 0, 1 ) );
$new_name_array[ $first_letter ][] = $name;
}
// store the first letter list in an array and sort it
$first_letters = array_keys( $new_name_array );
sort( $first_letters );
// sort the name lists
foreach( array_keys( $new_name_array ) as $letter ) {
sort( $new_name_array[$letter] );
}
// output csv header row
echo "'".implode( "','", $first_letters )."'\n";
// output the CSV name rows
$i = 0;
while ( true ) {
$row = array();
$is_row = false;
foreach( $first_letters as $letter ) {
$row[] = $new_name_array[ $letter ][ $i ];
if( ! empty( $new_name_array[ $letter ][ $i ] ) ) $is_row = true;
}
if( ! $is_row ) exit;
echo "'" . implode( "','", $row ) . "'\n";
$i++;
}
?>
Outputs quoted CSV:
'A','D','E'
'Alex','Daniel','eigor'
'alfredo','Dina',''
'','dina',''
'','durban',''
<?php
$stuck = array('Daniel','Alex','alfredo','dina', 'eigor', 'durban');
sort($stuck);
$sortedNames = array();
$maxEl = 0;
foreach ($stuck as $name) {
$name = strtolower($name);
$sortedNames[$name{0}][] = $name;
$maxEl = count($sortedNames[$name{0}]) < $maxEl ? $maxEl : count($sortedNames[$name{0}]);
}
$headers = array_keys($sortedNames);
$finalArray = array($headers);
for($i = 0; $i < $maxEl; $i++) {
$tmpRow = array();
foreach ($sortedNames as $names) {
$tmpRow[] = isset($names[$i]) ? $names[$i] : '';
}
$finalArray[] = $tmpRow;
}
$file = fopen("names.csv","w");
foreach ($finalArray as $line)
{
fputcsv($file,$line);
}
fclose($file);
Here is my attempt at this question:
$names = array('Daniel','Alex','alfredo','dina', 'eigor', 'falfoul', 'fiona');
natcasesort($names);
$columns = array();
foreach ($names as $name) {
$first = strtoupper(substr($name, 0, 1));
$columns[$first][] = $name;
}
// pad the columns so they all have the same number of rows
$maxRows = 0;
foreach ($columns as &$col) {
$numRows = count($col);
if ( $numRows > $maxRows) {
$maxRows = $numRows;
}
}
// pad the columns
foreach ($columns as &$column) {
$column = array_pad($column, $maxRows, '');
}
$firstLetter = array_keys($columns);
$numCols = count($firstLetter);
// transpose the columns array
$rows = array();
foreach ($columns as $csvCol) {
foreach ($csvCol as $k=>$n) {
$rows[$k][] = $n;
}
}
// pad the rows to ensure they all have the same number of
// columns
foreach ($rows as &$row) {
$row = array_pad($row, $numCols, '');
}
// add the title row to the rows
array_unshift($rows, $firstLetter);
$handle = fopen("names.csv", 'w');
foreach ($rows as $fRow) {
fputcsv($handle, $fRow);
}
This function creates <li> tags and im trying to give each li tag a unique CSS class name,
I've tried to create a for loop to generate numbers but this is producing the number 7 rather than counting down to the number 7 in <li> tag.
any help greatly appreciated!
function the_meta() {
if ( $keys = get_post_custom_keys() ) {
echo "<ul class='post-meta'>\n";
//tried to add this counter here to generate incremental numbers in the foreach loop
for ($i = 0; $i <= 6; $i++) { }
foreach ( (array) $keys as $key ) {
$keyt = trim($key);
if ( is_protected_meta( $keyt, 'post' ) )
continue;
$values = array_map('trim', get_post_custom_values($key));
$value = implode($values,', ');
echo apply_filters('the_meta_key', "<li class='$i'><span class='post-meta-key'>$key:</span> $value</li>\n", $key, $value);
}
echo "</ul>\n";
}
}
This line of code:
for ($i = 0; $i <= 6; $i++) { }
Will just increase $i until it get to 6,
So when you're getting to the "main loop" the variable $i will have the same value.
Why having another loop to count?
You can implement the counter inside your current loop:
$i = 1; //Before the loop , set a starting value.
foreach ( (array) $keys as $key ) {
$keyt = trim($key);
if ( is_protected_meta( $keyt, 'post' ) )
continue;
$values = array_map('trim', get_post_custom_values($key));
$value = implode($values,', ');
echo apply_filters('the_meta_key', "<li class='$i'><span class='post-meta-key'>$key:</span> $value</li>\n", $key, $value);
$i++; //Increase by one!!
}
That initial for loop wasn't really doing anything (as you noted), just initialize a variable at 0, then print and increment it every time you use it:
function the_meta() {
if ( $keys = get_post_custom_keys() ) {
echo "<ul class='post-meta'>\n";
$i=0;
foreach ( (array) $keys as $key ) {
$keyt = trim($key);
if ( is_protected_meta( $keyt, 'post' ) )
continue;
$values = array_map('trim', get_post_custom_values($key));
$value = implode($values,', ');
echo apply_filters('the_meta_key', "<li class='".$i++."'><span class='post-meta-key'>$key:</span> $value</li>\n", $key, $value);
}
echo "</ul>\n";
}
}
Your for loop just iterates doing nothing. You have to use:
$i = 0;
foreach ( (array) $keys as $key ) {
// ...
$i++;
}
I have a photo album, with a 'photos' field in database which has serialized data and is base 64 encoded. I can upload up to 21 photos at the same time for the album (multiple uploading). When trying to add new photos to the album on edit mode, I can't get the new $_FILES array to merge with the old array in the database. I want to update only the values that I have changed. So let's say I already had 2 images inside my album, I would like to add a 3rd image without losing the other 2 images. I know I need to use unset() to delete empty values but I think i'm not doing it correctly. Here's my code:
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'edit') {
//select photo album and get photos and descriptions to be merged with new.
$album_id = $_REQUEST['album_id'];
$old_photos = null;
$old_descriptions = null;
$getAlbumQ = mysql_query("select * from albums where id='$album_id'");
while ($old_album = mysql_fetch_array($getAlbumQ)) {
$old_photos = unserialize(base64_decode($old_album['photos']));
$old_descriptions = unserialize(base64_decode($old_album['descriptions']));
}
if (isset($_POST['album_name']) && isset($_POST['desc'])) {
$name = $_POST['album_name'];
$desc = $_POST['desc'];
$idesc = array();
$target_path = "../uploads/albums/";
foreach ($_FILES as $k => $v) {
//first upload photos
$path = $target_path . basename($v['name']);
if(move_uploaded_file($v['tmp_name'], $path)) {
$hasUpload = true;
}
}
for ($j = 1; $j < 21; $j++) {
$img_index = $j;
$img_desc = $_POST['desc_' . $img_index];
$asdf = $_FILES['image_' . $img_index]['name'];
array_push($idesc, $img_desc);
}
foreach( $_FILES['images']['name'] as $key => $value ) {
if( empty($value) ) {
unset( $_FILES['images']['name'][$key] );
}
}
for ($i = 1; $i < 21; $i++) {
if($_FILES['image_'.$i]['name']!= '')
{
$hasUpload = true;
$presults = array_merge($old_photos, $_FILES); //THE PROBLEM WITH MERGING ARRAYS OCCURS HERE
$dresults = array_merge($old_descriptions, $idesc);
$images = base64_encode(serialize($presults));
$descriptions = base64_encode(serialize($dresults));
$posted = date("Y-m-d H:i:s");
}
else {
$hasUpload = false;
$presults = $old_photos;
$dresults = $idesc;
$images = base64_encode(serialize($presults));
$descriptions = base64_encode(serialize($dresults));
$posted = date("Y-m-d H:i:s");
}
}
}
}
I tried something similar to what Muu suggested. Combined it with another piece of code of a custom merge function found here http://keithdevens.com/weblog/archive/2003/Mar/30/MergeTwoArrays and it worked fine! Thanks for your help
Just needed to add the following lines of code outside the for ($i = 1; $i < 21; $i++) loop:
//delete empty values for $_FILES array
foreach ($_FILES as $key => $value) {
foreach ($value as $k => $v) {
if ($k=='name' && $v!='') {
break;
} else {
unset($_FILES[$key]);
}
}
}
//custom array merge function
function merge(&$a, &$b){
$keys = array_keys($a);
foreach($keys as $key){
if(isset($b[$key])){
if(is_array($a[$key]) and is_array($b[$key])){
merge($a[$key],$b[$key]);
}else{
$a[$key] = $b[$key];
}
}
}
$keys = array_keys($b);
foreach($keys as $key){
if(!isset($a[$key])){
$a[$key] = $b[$key];
}
}
}
then instead of array_merge(), I used merge() inside the for ($i = 1; $i < 21; $i++) loop:
$presults = merge($old_photos, $_FILES);
Instead of removing the empty values from the array, why not just ignore them?
For example:
$nonEmptyArray = array();
foreach ($_FILES as $k => $v) {
if (!$v) {
continue;
}
$nonEmptyArray[$k] = $v;
}
$_FILES = $nonEmptyArray;