PHP duplicated list - php

Here is my code to list all category as a list item:
if ($xml) {
foreach($xml->children() as $IRXML) { // SHOW ONLY 5 NEWS ITEMS
foreach($IRXML->children() as $newsrelease) { // EACH NEWSRELEASE IS ONE SUBCHILD
// echo " <div class='news-image'>";
// echo "<img src='/wp-content/themes/bby/images/news-story-01.jpg' alt=''>";
// echo "</div>";
$categories = $newsrelease->Categories;
foreach($categories->children() as $category) {
if ($category != "NA") {
echo "<li class='category ".$category."'>".$category."</li> ";
}
}
}
}
}
What I wanted to do is only to display a category without duplicating it.

$list_cache = array();
if ($xml)
{
foreach($xml->children() as $IRXML)
foreach($IRXML->children() as $newsrelease)
{
$categories = $newsrelease->Categories;
foreach($categories->children() as $category)
{
if ($category != "NA")
{
$print_category = "<li class='category ".$category."'>".$category."</li> ";
if( !in_array($print_category, $list_cache) ) //check if you've stored in previously in this array. In such case, in_array will return true.
{
$list_cache[] = $print_category;
echo $print_category;
}
}
}
}
}
Check out the in_array function from the documentation.

Do you mean you want to display each one only once? If .children() is returning the same child twice, that could be another problem; if it's not something you can change and this is the behavior you're seeing, you could keep an array of category names/ID's, append as you display them, and check the array for duplicates before writing output each time the loop runs.

Assuming there is no way to eliminate the duplicates when generating the XML...that would be more efficient.
You could create an array outside of the loop, and then check to see if a category has already been seen. Example:
$categories = $newsrelease->Categories;
$seen_categories = array();
foreach($categories->children() as $category) {
if ($category != "NA" && !in_array($category,$seen_categories)) {
$seen_categories[]=$category;
echo "<li class='category ".$category."'>".$category."</li> ";
}
}

Related

Filtering an array with foreach and for loop

I'm pulling data from mssql database into an array called
$results2
I need to echo out each 'Item' only one time, so this example should only echo out:
"52PTC84C25" and "0118SGUANN-R"
I can do this easily with:
$uniqueItems = array_unique(array_map(function ($i) { return $i['ITEM']; }, $results2));
The issue is when i try to echo out the other items associated with those values. I'm not sure how to even begin on echoing this data. I've tried:
foreach($uniquePids as $items)
{
echo $items."<br />";
foreach($results2 as $row)
{
echo $row['STK_ROOM']."-".$row['BIN']."<br />";
}
}
This returns close to what I need, but not exactly:
This is what I need:
Assuming your resultset is ordered by ITEM...
$item = null; // set non-matching default value
foreach ($results2 as $row) {
if($row['ITEM'] != $item) {
echo "{$row['ITEM']}<br>"; // only echo first occurrence
}
echo "{$row['STK_ROOM']}-{$row['BIN']}<br>";
$item = $row['ITEM']; // update temp variable
}
The if condition in the code will check if the ITEM has already been printed or not.
$ary = array();
foreach($results2 as $row)
{
if(!in_array($row['ITEM'], $ary))
{
echo $row['STK_ROOM']."-".$row['BIN']."<br />";
$ary[] = $row['ITEM'];
}
}

Processing xml file

I have the following xml file:
row category="1" category_name="CatA" entry_id="1" entry_name="A1"
row category="1" category_name="CatA" entry_id="2" entry_name="A2"
row category="1" category_name="CatA" entry_id="3" entry_name="A3"
row category="2" category_name="CatB" entry_id="4" entry_name="B1"
row category="2" category_name="CatB" entry_id="5" entry_name="B2"
row category="2" category_name="CatB" entry_id="6" entry_name="B3"
row category="3" category_name="CatC" entry_id="7" entry_name="C1"
row category="4" category_name="CatD" entry_id="8" entry_name="D1"
and I want to produce below html:
CatA
----A1
----A2
----A3
CatB
----B1
----B2
----B3
CatC
----C1
CatD
----D1
for this I am using below php xml parser:
$ndeshjet=simplexml_load_file("xml_file.xml");
$new_category = 1;
foreach ($ndeshjet->row as $entry) {
$category = $entry['category'];
if ($category <> $new_category){
$category_name = $entry['category_name'];
echo $category_name."</br>";
$new_category = $category;
} else {
$entry_name = $entry['entry_name'];
echo "----".$entry_name."</br>";
}
}
?>
but the result is :
----A1
----A2
----A3
CatB
CatB
CatB
CatC
CatD
Thanks in advance
As an alternative, you could gather all the values first inside an array and make the category name as key pushing same keys inside. After thats done and gathered, print them accordingly:
$categories = array();
// gather inside container
foreach ($ndeshjet->row as $entry) {
$category_name = (string) $entry->attributes()->category_name;
$entry_name = (string) $entry->attributes()->entry_name;
$categories[$category_name][] = $entry_name;
}
// presentation
foreach($categories as $category_name => $entries) {
echo $category_name . '<br/>';
foreach($entries as $entry) {
echo '----' . $entry . '<br/>';
}
}
Sample Output

PHP - replace values in sub array

I have two arrays $pq and $rs. please see them below:
$pq = array ('page-0'=>array ('line-0'=>array('item-0'=>array('name'=>"item-00",'value'=>"123"),
'item-1'=>array('name'=>"item-01",'value'=>"456")
),
'line-1'=>array('item-0'=>array('name'=>"item-10",'value'=>"789"),
'item-1'=>array('name'=>"item-11",'value'=>"012")
)),
'page-1'=>array ('line-0'=>array('item-0'=>array('name'=>"item-100",'value'=>"345"),
'item-1'=>array('name'=>"item-101",'value'=>"678")
),
'line-1'=>array('item-0'=>array('name'=>"item-110",'value'=>"901"),
'item-1'=>array('name'=>"item-111",'value'=>"234")
),
'line-2'=>array('item-0'=>array('name'=>"item-210",'value'=>"567"),
'item-1'=>array('name'=>"item-211",'value'=>"890")
))
);
$rs = array ('1'=>array('name'=>'item-00', 'value'=>"abc"),
'2'=>array('name'=>'item-01', 'value'=>"def"),
'3'=>array('name'=>'item-10', 'value'=>"ghi"),
'4'=>array('name'=>'item-11', 'value'=>"jkl"),
'5'=>array('name'=>'item-100', 'value'=>"mno"),
'6'=>array('name'=>'item-101', 'value'=>"pqr"),
'7'=>array('name'=>'item-110', 'value'=>"stu"),
'8'=>array('name'=>'item-111', 'value'=>"vwx")
);
What I am trying to do is to replace the values in $pq for items with the values from $rs.
for example item-01 in $pa to be replaced with abc from $rs.
What I tried is this:
foreach($rs as &$rs1) {
echo "first count :".$firstCount."<br>";
foreach($pq as $pages) {
foreach($pages as $lines) {
foreach($lines as &$item) {
if ($item['name'] == $rs1['name']) { echo "matching </p>";
$item['value']=$rs1['value'];
echo '<pre>';
print_r($item);
echo '</pre>';
echo "<hr>";
}
}
}
}
}
When I print the values of $item from $pq, it prints the values from $rs, but when I print the whole array $pq, the values seem to be unchanged.
Can anyone please help me find out what I am missing ?
You're correctly looping through the items in each line by reference, but you're not doing it for the lines or pages themselves. So you're updating the value of an item in a copy of the line, instead of the line itself. It should be:
foreach($rs as $rs1) {
echo "first count :".$firstCount."<br>";
foreach($pq as &$pages) {
foreach($pages as &$lines) {
foreach($lines as &$item) {
if ($item['name'] == $rs1['name']) { echo "matching </p>";
$item['value']=$rs1['value'];
echo '<pre>';
print_r($item);
echo '</pre>';
echo "<hr>";
}
}
}
}
}
Note that the & in front of &$lines and &$pages. Note also that $rs1 doesn't need to be passed by reference, since you aren't changing anything in that array.
You’ve assigned $item by reference but haven’t done the same for $pages and $lines. There will be no effect on the actual values of $pq unless you assign $pages by reference; similarly, the actual values of $pages will remain unchanged unless you assign $lines by reference. Therefore, in order to achieve what you want, change foreach($pq as $pages) to foreach($pq as &$pages) and foreach($pages as $lines) to foreach($pages as &$lines).
You can build a search array first so that you can match items easier:
$search = array_reduce($rs, function(&$prev, $current) {
$prev[$current['name']] = $current;
return $prev;
}, []);
This creates another array with the item name as the key. Then, you iterate over each item in $pq and modify the leaves where necessary:
foreach ($pq as &$page_data) {
foreach ($page_data as &$line_data) {
foreach ($line_data as &$item_data) {
if (isset($search[$item_data['name']])) {
$item_data = $search[$item_data['name']];
}
}
}
}
Make sure to use references at each level of iteration.

How to use variables within a PHP array

I have this code:
foreach ($row as $result) {
if (empty($row[28])) {
$string28 = '';
} else {
$string28 = '<div class="add_img">
<h1>Connexion</h1>
<img src="images/' . $row[28] . '.jpeg">
</div>';
}
}
foreach ($row as $result) {
if (empty($row[30])) {
$string30 = '';
} else {
$string30 = '<div class="add_img">
<h1>Fixation</h1>
<img src="images/' . $row[30] . '.jpeg">
</div>';
}
}
foreach ($row as $result) {
if (empty($row[31])) {
$string31 = '';
} else {
$string31 = '<div class="add_img">
<h1>Schéma</h1>
<img src="images/' . $row[31] . '.jpeg">
</div>';
}
}
$applications = array($string28, $string30, $string31);
if (empty($applications)) {
$vide = "<h1>Pas D'Application Pour Ce Produit</h1>";
}
What I want to say here is: if all the variables are empty then show me this:
Pas D'Application Pour Ce Produit (Translated: No application for this product)
But When I use the print_r function it tells to me that the array has no data to deal with.
Please I need Help.
And Thanks to all in advanced
You are not accessing your rows correctly in your foreach loops. When using foreach($row as $result) you need to refer to the array element as $result, not row. If you need to identify a specify array key you can specify that by using foreach($row as $key => $result).
For example, in your first loop you should use this:
$string28 = ''; //Initialize your variable so can be used after the foreach loop exits
foreach ($row as $key => $result) {
if($key == 28 && empty($result[$key]) {
$string28 = '';
} else {
$string28 = '<div class="add_img"><h1>Connexion</h1><img src="images/'.$result[$key].'.jpeg">
}
}
Repeat for the other loops in your script.
EDIT
Yes, you can setup one foreach loop that will go through all your variables and create variables for you. Based on your question, if you don't have any apps an error message shows. What you may wish to do is simply set a flag based on that criteria. You could do do this like so:
$noApps = true;
$applications = array();
foreach($row as $key => $result) {
if(isset($result[$key]) && empty($result[$key])) {
$applications[$key] = '<div class="add_img"><h1>Connexion</h1><img src="images/'.$result[$key].'.jpeg'>;
$noApps = false;
}
}
if($noApps) {
echo "<h1>Pas D'Application Pour Ce Produit</h1>";
} else {
print_r($applications); //For viewing/debugging purposes
}
Your foreach loops is wrong. You are using the whole array instead of the elements as is used within a foreach loop.
You have used
foreach ($row as $result) {
//You are doing something with $row
}
Instead correct usage is
foreach ($row as $result) {
//Do something with $result
}
Hope it helps :)
Your design looks bad. You are essentially repeating the same functionality 3 times.
Your while loops don't work because you're using $row in them, instead of the $result variable.
The second point is, The $string28, $string30, $string31 are created as local variables within the if conditions you have written in the while loops. Once the control exits the "if" loops these variables are nothing. To solve this problem, try initializing these to empty data like$string28 ="" at the beginning point of your code.
However, I would recommend you to look at the structure of your code first.

PHP Multidimensional array to unordered list, building up url path

I have a multidimensional array in PHP produced by the great examples of icio and ftrotter (I am use ftrotterrs array in arrays variant):
Turn database result into array
I have made this into a unordered list width this method:
public function outputCategories($categories, $startingLevel = 0)
{
echo "<ul>\n";
foreach ($categories as $key => $category)
{
if (count($category['children']) > 0)
{
echo "<li>{$category['menu_nl']}\n";
$this->outputCategories($category['children'], $link
, $start, $startingLevel+1);
echo "</li>\n";
}
else
{
echo "<li>{$category['menu_nl']}</li>\n";
}
}
echo "</ul>\n";
}
So far so good.
Now I want to use the url_nl field to build up the url's used as links in the menu. The url has to reflect the dept of the link in de tree by adding up /url_nl for every step it go's down in the tree.
My goal:
- item 1 (has link: /item_1)
* subitem 1 (has link: /item_1/subitem_1)
* subitem 2 (has link: /item_1/subitem_1)
* subsubitem 1 (has link: /item_1/subitem_2/subsubitem_1)
- item 2 (has link: /item_2)
the table
id
id1 (parent id)
menu_nl
url_nl
title_nl
etc
What I have so far:
public function outputCategories($categories, $link, $start, $startingLevel = 0)
{
// if start not exists
if(!$start)
$start = $startingLevel;
echo "<ul>\n";
foreach ($categories as $key => $category)
{
$link.= "/".$category['url_nl'];
if($start != $startingLevel)
$link = strrchr($link, '/');
if (count($category['children']) > 0)
{
echo "<li>".$start." - ".$startingLevel.
"<a href='$link'>{$category['menu_nl']}</a> ($link)\n";
$this->outputCategories($category['children'], $link
, $start, $startingLevel+1);
echo "</li>\n";
}
else
{
$start = $startingLevel+1;
echo "<li>".$start." - ".$startingLevel.
"<a href='$link'>{$category['menu_nl']}</a> ($link)</li>\n";
}
}
echo "</ul>\n";
}
As you see in the example I have used a url_nl field which is recursively added so every level of the list has a link with a path which is used as a url.
Anyhow, I have problems with building up these links, as they are not properly reset while looping to the hierarchical list. After going down to the child in de list the first one is right but the second one not.
I'm stuck here...
It looks like you modify the $link variable inside the foreach loop, So you add item1 to $link, loop thru its subitems and return to the first iteration and add item2 to the variable...
replace this
$link .= "/".$category['url_nl'];
with
$insidelink = $link . "/".$category['url_nl'];
(and change remaining $link inside the loop to $insidelink)
Adding: This is also true for $startingLevel. Do not modify it, use +1 inline:
echo "<li>".$start." - ".$startingLevel +1.
"<a href='$link'>{$category['menu_nl']}</a> ($link)</li>\n";
Here is an easier way:
$inarray = your multi-dimensional array here. I used directory_map in codeigniter to get contents of directory including it's subdirectories.
$this->getList($filelist2, $filelist);
foreach ($filelist as $key => $val) {
echo $val;
}
function getList($inarray, &$filelist, $prefix='') {
foreach ($inarray as $inkey => $inval) {
if (is_array($inval)) {
$filelist = $this->getList($inval, $filelist, $inkey);
} else {
if ($prefix)
$filelist[] = $prefix . '--' . $inval;
else
$filelist[] = $inval;
}
}
return $filelist;
}

Categories