How to extend array structure in nested loop? - php

I have an array with products, filled by the API.
I want to extend it and add some values like categories, price. I tried to add & before the array when looping to use it by reference row. But when I added another while loop to add categories, the $row wasn't extended.
$products = array('id_product'=>12,'link'=>'test.html','description'=>'desc');
foreach($products as &$row) {
$row['price'] = 12;
$product = new Product($row['id_product'];
$categories = $product::getCategories();
$k = 1;
while ($cat = current($categories)){
$row['categoryid'.$k] = $cat['name'];
$k++;
}
}
$product::getCategories() return
array(1) { [0]=> array(1) { ["name"]=> string(8) "T-shirts" } }
The problem is that the array key with categoryid.$k is never created, I tried with foreach on categories but it didn't work.

In provided example in foreach loop $row will contains values 12, 'test.html' and 'desc'. So you can't use them as array.
Valid code:
$products = array();
$products[] = array('id_product'=>12,'link'=>'test.html','description'=>'desc');
Also you have invalid while loop, replace current function with array_shift, or use proper foreach loop
Edited:
Replace while with this code:
if (!empty($categories)) {
foreach ($categories as $key => $category) {
$row['categoryid' . $key] = $category['name'];
}
}

I fixed my problem by adding a function and pass by value the row parameter
private function addCategories(&$row){
$categories = $this->getProductCategoriesFull((int)$row['id_product']);
if (!empty($categories)) {
$k = 2;
foreach($categories as $category) {
if($k!= 2)
$row['categoryid' . ($k-1)] = $category['name'];
$k++;
if($k>5) exit;
}
}
}
And call it in the loop
$this->addCategories($row);

Related

Can I put new values in array inide foreach?

I have a foreach loop, in which I loop through the array. I want to add elements as I go through it and have new ones go through it as well.
Now with this code it only does the iterations that I have in the array at the beginning (1 in this case).
Can somebody help me
Thanks
public static function getDirectoriesChilds($id_parent, $parents_array) {
$session_client = Client::getSessionClient();
array_push($parents_array, $id_parent);
$parents_array = array_unique($parents_array);
foreach ($parents_array as $element) {
$childs = Directory::where('id_parent' , '=', $element)->get();
foreach ($childs as $child) {
if ($child->deleted == Controller::DISABLED) {
array_push($parents_array, $child->id);
$parents_array = array_unique($parents_array);
}
}
}
return $parents_array;
}
If changes foreach to for works.
for($i=0; $i<count($parents_array); $i++){

PHP foreach loops and data retrieval

Using PHP and MySQL I have generated two arrays. I would like to loop through these arrays, retrieve data from both and display together in one sentence.
foreach ($items as $item) {
if(isset($item->item_title)) {
$itemTitle = $item->item_title;
}
// var_dump($itemTitle);
// string(7) "Halfway" string(5) "Story" string(6) "Listen"
}
foreach ($aData["Items"]["Item"] as $a) {
if (isset($a['description'])) {
$aDescription = $a['description'];
}
// var_dump($aDescription );
// string(4) "Good" string(6) "Strong" string(2) "OK"
}
?>
Desired result;
The title is Halfway and the description is Good.
The title is Story and the description is Strong.
The title is Listen and the description is OK.
// etc
// etc
Is it possible to nest the foreach loops, or is there a better more efficient way?
Please try this way. Hope this help!!
foreach ($items as $index => $item) {
if(isset($item->item_title)) {
$itemTitle = $item->item_title;
echo 'The title is '.$itemTitle;
}
if(isset($aData["Items"]["Item"][$index]['description']) {
$itemDescription = $aData["Items"]["Item"][$index]['description'];
echo ' and the description is '.$itemDescription;
}
echo '<br>';
// The title is Halfway and the description is Good.
}
You can merge those two foreach loops using a simple for loop, like this:
$count = count($items) >= count($aData["Items"]["Item"]) ? count($aData["Items"]["Item"]) : count($items);
for($i = 0; $i < $count; ++$i){
if(isset($item[$i]->item_title)) {
$itemTitle = $item[$i]->item_title;
}
if (isset($aData["Items"]["Item"][$i]['description'])) {
$aDescription = $aData["Items"]["Item"][$i]['description'];
}
// your code
}
Sidenote: The above code assumes that two arrays $items and $aData["Items"]["Item"] have unequal number of elements, though this will work for equal number of elements as well. If you're sure that these two arrays will always have equal number of elements, then refactor the $count = ... ; statement in the following way,
$count = count($items);
or
$count = count($aData["Items"]["Item"]);
and use this $count variable in for loop.
Try this hope this will help you out.
Note: Here i am assuming both array's have same indexes.
$items
$aData["Items"]["Item"].
If not you can do array_values($items) and array_values($aData["Items"]["Item"])
foreach ($items as $key => $item)
{
if (isset($item->item_title) && isset($aData["Items"]["Item"][$key]['description']))
{
$itemTitle = $item->item_title;
echo sprinf("The title is %s and the description is %s",$itemTitle,$aData["Items"]["Item"][$key]['description']);
echo PHP_EOL;
}
}

How to have foreach contains dynamic element

Here is my Foreach, How can i assign different class each time consequently
Here is what i have tried so far.
<?php
$class1="one";
$class2="two";
$class3="three";
$class4="four";
foreach ($blogs as $blog)
{
echo $blog->val;
echo $class;
}
?>
Here the foreach behaves regular as it might contain any number of records.
But i need to assign the $class as one, two, three, four consecutively (which is defined above the foreach).
How can i do this ?
Start by defining $class as an array
$class = array(
"one",
"two",
"three",
"four",
);
Iterate your blogs array retrieving the key as well
foreach ($blogs as $key => $blog) {
....
}
Then use the modulus operator % against the $key value within your loop to identify each entry from $class in turn
foreach ($blogs as $key => $blog) {
echo $blog->val;
echo $class[($key % 4)];
}
Use the modulus with a division by 4 because there are 4 entries in your $class array
For the sake of completeness, there are two more approaches; both use $classes containing all the possible values. First is a slight variation of #MarkBaker's answer:
$classes = array('one', 'two'/*, ...*/);
$length = count($class);
$i = 0;
foreach($blogs as $blog) {
echo $blog->val;
echo $classes[$i];
if (++$i === $length) {
$i = 0;
}
}
Second makes the $classes check as direct as possible - through array_chunk():
foreach (array_chunk($blogs, count($classes)) as $blogs_chunk) {
foreach($blogs_chunks as $key => $blog) {
echo $blog->val;
echo $classes[$key];
}
}
In this case it's not necessary to check for overflow/modalize because each chunk contains not more than count($classes) elements.

Magento - Adding products from CSV - Loop issue

I have a CSV file with a header row. The code puts the column names as the $Key and $postion is the values. This works okay.
This is the loop creating the string of attributes to add to the product. When i "echo $sets" it displays correctly
foreach ($each_csv as $position => $details) {
$sets .= ->set$position('$details')}
$sets is creating the ->set code for the product. How do I implement the loop values into the product set function
$product->setWebsiteIds(array(1))
->setTypeId('simple')
->setMediaGallery (array('images'=>array (), 'values'=>array ()))
// How can I add the looped values here from the array
. Full Code Below
<?php
include ("../config/init.php");
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$product = Mage::getModel('catalog/product');
$rows = array_map('str_getcsv', file('prouduct_ids.csv'));
$header = array_shift($rows);
$csv = array();
foreach ($rows as $row) {
$csv[] = array_combine($header, $row);
}
//print_r($csv);
reset($csv);
$dataSetCount = count($csv);
echo "<h1>There are $dataSetCount products</h1>";
$i = 0;
foreach ($csv as $each_csv) {
$i++;
echo "<h2>csv $i</h2>";
if(!$product->getIdBySku($each_csv['Sku'])){
echo $each_csv['Sku'] . " - Already in website";
} else {
foreach ($each_csv as $position => $details) {
$sets .=->set$position('$details')}
$product->setWebsiteIds(array(1)) //website ID the product is assigned to, as an array
->setTypeId('simple') //product type
->setMediaGallery (array('images'=>array (), 'values'=>array ()));
//media gallery initialization
$product->save();
unset($sets);
}
}
You want to use the $product->setData('data_key', 'value') function.
For example, this function:
$product->setTypeId('simple')
Is the exact same as this function:
$product->setData('type_id', 'simple')
Keep in mind that a capital letter represents an underscore in the attribute name. typeId is type_id because the I in Id is capitalized.
The code in your functon will look like this:
[...]
foreach ($each_csv as $position => $details) {
$sets .= $product->setData($position, $details)
[...]
Where $position is the attribute code, and $details is the attribute value.

Building a multidimensional associative array using PHP and MYSQL

I'm trying to build a multidimensional associative array while fetching the results from a MySQL query.
But i can't figure out how to achieve this.
I want to build an array like this one:
array ("cat_name" => "category1",
"id_cat" => "1",
"sub_cat" => array ("name_sub_cat" => "subCategory",
"id_sub_cat" => "4",
"ss_cat" =>array ("ss_cat_name" =>"ss_cat1",
"id_ss_cat" => "4"
)
)
);
Here's where i'm building the array:
Edit : I've ended up with something like that, not very sexy, but if think i'm almost there
while($row = mysql_fetch_assoc($resultQueryCat)){
$menuArray[$row["id_cat"]]["cat_name"] = $row["cat_name"];
$menuArray[$row["id_cat"]][$row["id_sub_cat"]]["id_sub_cat"] = $row["id_sub_cat"];
$menuArray[$row["id_cat"]][$row["id_sub_cat"]]["name_sub_cat"] = $row["name_sub_cat"];
$menuArray[$row["id_cat"]][$row["id_sub_cat"]][$row["ss_cat_name"]]["ss_cat_name"] = $row["ss_cat_name"];
$menuArray[$row["id_cat"]][$row["id_sub_cat"]][$row["ss_cat_name"]]["id_ss_cat"] = $row["id_ss_cat"];
}
Edit2: The code to display the array
$menu.='<ul>';
foreach ($menuArray as $key) {
$compteur_cat++;
$menu.= '<div id="collapsiblePanelCol'.$compteur_cat.'" class="collapsiblePanelCol floatleft">
<li class="categorie"> '.$key["cat_name"].'
<ul>';
foreach ($key as $key1) {
if (is_array($key1){/* One of the thing i forgot which totally screwed up my results*/
$menu.= '<ul>
<li class="ss_categorie">'.$key1["name_sub_cat"].'<ul>';
foreach ($key1 as $key2) {
if (is_array($key2)){
$menu.= '<li class="element">'.$key2["ss_cat_name"].'</li>'; }
}
$menu.= '</ul></li></ul>';
}
}
$menu.='</ul>
</li>
</div>';
}
$menu.= '</ul>';
Thanks.
Final Edit: My code is working :) i edited the previous code to make it correct
It's not an easy task, as data from DB might contain loops :-)
I'd better save it in id->data hashmap so that you can build the structure easier.
Not sure why you need multidimensions.
The way I build multidimensional arrays is through classes and their objects.
Example:
class Categories
{
public $cat_name;
public $id_cat;
function __construct($cat_name, $id_cat)
{
$this->id = $id_cat;
$this->name = $cat_name;
$this->sub_cat = array();
}
}
class SubCategories
{
public $name_sub_cat;
public $id_sub_cat;
function __construct($name_sub_cat, $id_sub_cat)
{
$this->id = $id_sub_cat;
$this->name = $name_sub_cat;
$this->ss_cat = array();
}
}
class SSCategories
{
public $ss_cat_name;
public $id_ss_cat;
function __construct($ss_cat_name, $id_ss_cat)
{
$this->id = $id_ss_cat;
$this->name = $ss_cat_name;
}
}
Then to write to those classes (after fetching MySQL DB Data [assuming OOP mysql]):
if($result)
{
$array = array();
while($row = $result->fetch_array())
{
$array[] = new Categories($row["cat_name"], $row["id_cat"]);
}
foreach($array as $main)
{
... (fetching sub category info)
if($sub_result)
{
$sub_array = array();
while($sub_row = $sub_result->fetch_array())
{
$sub_array[] = new SubCategories($sub_row["name_sub_cat"], $sub_row["id_sub_cat"]);
}
$main->sub_cat = $sub_array;
You would repeat for each within original if loop for as many sub arrays as you have. This took a while :).
NOTE: Close if loops (heirarchally) if there are no more sub arrays.
echo '<pre>';
print_r($array);
echo '</pre>';
The above code will help show the levels of your array!

Categories