Welcome to WebmasterWorld Guest from 54.147.165.246

Forum Moderators: coopster & jatar k

Message Too Old, No Replies

Turn local variable into a global variable

Maybe not right terminology

     

doubleJ

3:30 pm on Sep 8, 2011 (gmt 0)



Hello...
I have this chunk of code...

<?php
$rss = new SimpleXMLElement("http://$fqdn/rss/FreeDownloads.xml", null, true);
foreach($rss->xpath("channel/item") as $item) {
$filename = basename($item->guid,".xml");
echo $filname;
}
?>

$filename seems to only be accessible within the foreach confines.
I'd like to be able to use the variable on other parts of the page.
I don't think I can move foreach to the top of the page or I'll be replicating a lot of code that I don't want replicated.
Any ideas?
JJ

rocknbil

4:12 pm on Sep 8, 2011 (gmt 0)

WebmasterWorld Senior Member rocknbil is a WebmasterWorld Top Contributor of All Time 10+ Year Member



Well, since you have it in a foreach this implies multiple instances of $filename. You shouldn't need a global in the context of a single page, unless it's in a function. Is it?

You could do something like this:

<?php
$files = Array();
// Added only for your echo
$counter=0;
$rss = new SimpleXMLElement("http://$fqdn/rss/FreeDownloads.xml", null, true);
foreach($rss->xpath("channel/item") as $item) {
$files[] = basename($item->guid,".xml");
echo $files[$counter];
$counter++;
}
?>

Then you should have $files[0], $files[1], etc.

That should give you $files [ 0 ], $files [ 1 ] etc. (something on the board is messing up my example)

doubleJ

4:32 pm on Sep 8, 2011 (gmt 0)



So, in theory, I could use $files[18] anywhere on the page (even above foreach)?
JJ

penders

5:06 pm on Sep 8, 2011 (gmt 0)

WebmasterWorld Senior Member penders is a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month



Yes. If your code is not in a function, then it is probable that all the variables you have used so far are global variables and are directly available anywhere in the global scope, which probably includes your page.

As rocknbil suggests, your problem was probably not to do with variable scope but the fact that $filename would have been repeatedly overwritten inside your foreach() loop.

doubleJ

10:12 pm on Sep 8, 2011 (gmt 0)



Well, I just did a test and it doesn't work quite like I had planned.
$files[18] works just fine anywhere after foreach (even outside the loop).
It doesn't work before the loop, though. That's what I'd really like to be able to do.
A couple of ideas to what I'm going for...
The page is very long. I'd like to make a navigation sidebar with small font links to each $item.
I'd also like to be able to dynamically set a background image in css for each $item.
In order to do that, I need those variables above the loop.
Maybe the loop can be further up, but there is a lot of code that shouldn't be duplicated (<body>, for instance).
JJ

Readie

10:14 pm on Sep 8, 2011 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



You could build up the $files array as the first thing on the page (so no echo) - and then foreach through it everytime you need the data

doubleJ

10:51 pm on Sep 8, 2011 (gmt 0)



I must be doing something wrong. Trying to build the array at the top of the page didn't work, either. Nothing was echoed.
JJ

<?php
$articles = array();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<?php
foreach($articles as $key => $val) {
echo "articles[".$key."] = ".$val."\n";
}
?>
<?php
$rss = new SimpleXMLElement("http://$fqdn/rss/FreeDownloads.xml", null, true);
foreach($rss->xpath("channel/item") as $item) {
$articles[] = $item->title;
$filename = basename($item->guid,".xml");
echo $filename;
}
?>

penders

12:18 am on Sep 9, 2011 (gmt 0)

WebmasterWorld Senior Member penders is a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month



PHP code is executed top to bottom. So if you expect a variable to have a value it must have previously been assigned that value earlier in the code. In your code snippet above you are initialising the $articles variable to an empty array at the top. You then try to output the $articles array, but nothing has been assigned to it yet, so nothing is output. You then assign values to the $articles array at the bottom. This is in the wrong order.

What's happened to your $files variable - an array to hold all your {$filename}s?

Just to note... all the <?php ... ?> blocks in your page are in the same variable scope so any difference in local and global variables does not apply here.

doubleJ

2:53 am on Sep 9, 2011 (gmt 0)



$article was a tangent. The same rules should apply, though.
I thought it was odd when Readie said to build it at the top. I figured you guys knew more about it than me.
Hehehe...
That's why I said that I could move the loop further up the page, but I don't want to put a lot of the code within the loop.
So, is there a way to do what I'm trying?
JJ

penders

9:23 am on Sep 9, 2011 (gmt 0)

WebmasterWorld Senior Member penders is a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month



I thought it was odd when Readie said to build it at the top.


But that is correct, or "as the first thing on the page" - same thing. "build" in this sense means to "assign values to". The "page" is the entire document, not just the visual page.

So, reordering your code and adding back rocknbil's $files...

<?php 
/**
* 1. Declare/initialise your variables
* Or at least the ones that *need* to be initialised
*/
$articles = array();
$files = array();
/**
* 2. Assign values to your variables
*/
$rss = new SimpleXMLElement("http://$fqdn/rss/FreeDownloads.xml", null, true);
foreach($rss->xpath("channel/item") as $item) {
$articles[] = $item->title;
$files[] = basename($item->guid,".xml");
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<pre>
<?php
/**
* 3. Output
*/
print_r($articles);
print_r($files);
?>
</pre>
</body>
</html>

doubleJ

3:05 pm on Sep 9, 2011 (gmt 0)



Ok...
That is completely different than what I expected the output to be.
I thought that any code (<!DOCTYPE html> as an example) under foreach would be duplicated.
The difference, I've found, is that your html is outside of the foreach() function.
In my code, the html that represents each $item is within the foreach() function.
I modified your code to put the ending } at the end of the print_r()'s and it did what I was expecting (duplicating <!DOCTYPE html>, among others).
I then thought that I might be able to do the same foreach() function twice and that worked.
I'm not sure if it's the best way, but it does get the job done.
JJ

doubleJ

3:55 pm on Sep 9, 2011 (gmt 0)



I was trying to figure out why $articles printed so differently from $files. Then I tried putting basename() in $articles and it printed only the title.
I thought basename() was only for filenames, but I guess not.
JJ

doubleJ

4:53 pm on Sep 9, 2011 (gmt 0)



Ok, starting to get a grasp on this (again, using multiple foreach() functions, which may be completely wrong).
Now, I'm trying to figure out sort().
The xml is sorted by date descending and I want an alphabetical list as a sidebar.
I can do sort($articles) and it does sort the list, alphabetically. Unfortunately, it removes the first alphabetic entry (A Fighting Spirit) and shows the second alphabetic entry (A Vision Of Victory) as the first. Then it shows a blank last alphabetic entry.
Also, obviously, if I also do sort($files), it sorts the two variables differently.
That's not what I'm looking for (as $files will be used for the links).
I'm trying to figure out how to sort $item, so that it will force everything within $item to be sorted.
JJ

Edit...
Apparently, no sorting produces the same result (missing the first entry and having an empty last entry).
I didn't realize it until just now.
JJ

doubleJ

6:26 pm on Sep 9, 2011 (gmt 0)



Is there a way to sort an array by an interior array?
I tried sort($item["title"]) and sort($item
  • ["title"]) and neither worked, correctly.

    Array
    (
    [0] => SimpleXMLElement Object
    (
    [title] => The Life Of Praise
    [description] => SimpleXMLElement Object
    (
    )

    [guid] => [moorelife.org...]
    [pubDate] => Fri, 24 Sep 2004 19:30:00 CST
    [category] => Victory
    )

    [1] => SimpleXMLElement Object
    (
    [title] => Faith And Patience
    [description] => SimpleXMLElement Object
    (
    )

    [guid] => [moorelife.org...]
    [pubDate] => Thu, 14 Oct 1999 10:00:00 CST
    [category] => Faith
    )

    I'm not sure why [description] doesn't have data, though. It should have multiple <p> within CDATA.
    JJ
  • doubleJ

    9:03 pm on Sep 9, 2011 (gmt 0)



    I guess we've gotten a little off-topic, here, but in the interest of answering a question...
    Alphabetical sorting of the array for the sidebar is working.
    I'm using SimpleDOM.
    JJ

    $rss = simpledom_load_file("http://www.moorelife.org/rss/FreeDownloads.xml");
    foreach($rss->sortedXPath('channel/item', 'title') as $item) {
    $filename = basename($item->guid,".xml");
    echo <<<END
    <li><a href="#$filename">$item->title</a></li>\n
    END;
    }