homepage Welcome to WebmasterWorld Guest from 23.20.103.29
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Pubcon Platinum Sponsor 2014
Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
Forum Library, Charter, Moderators: coopster & jatar k

PHP Server Side Scripting Forum

    
Turn local variable into a global variable
Maybe not right terminology
doubleJ




msg:4360004
 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




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

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




msg:4360049
 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




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

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




msg:4360244
 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




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

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




msg:4360258
 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




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

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




msg:4360321
 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




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

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




msg:4360553
 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




msg:4360585
 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




msg:4360608
 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




msg:4360669
 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




    msg:4360712
     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;
    }

    Global Options:
     top home search open messages active posts  
     

    Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
    rss feed

    All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
    Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
    WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
    © Webmaster World 1996-2014 all rights reserved