In the introductory post, I explained briefly what we’re going to create, made some important disclaimers, and blew some hot air around. In this part, we’re going to get our hands dirty by diving in and writing the PHP script and testing it outside of MODx to make sure it works. In general, I think this is a good idea because it allows you to iron out any purely PHP issues in your code before dealing with the MODx side of things. Chances are that even after you’ve tested it and ported it into MODx, you’ll end up adding more PHP logic and stuff but if you can test most of it outside MODx first, it should potentially save you some headaches and debugging time when working inside MODx. This is especially important because once inside the MODx editor there’s no syntax highlighting, automatic indenting and all that other good stuff.
With that in mind, let’s go ahead and create our script.
As agreed, we want to write a simple script that will pull in an RSS feed from an external website or blog and display it on our MODx site. I am going to try and explain the code as I go for any PHP novices, so this installment might be painfully slow for those of you experienced at coding PHP 🙂 . But please do glance at the code and if you see any glaring issues or have any feedback let me know. I am hoping to learn a lot through this process too 🙂
We will start by creating a function called ‘fetchFeed‘ which will do the lion’s share of the work here. Inside this function, I will begin by fetching the rss feed of my blog, and returning the file in a string using the file_get_contents() function. I then assign this to a variable I call $content.
<?php function fetchFeed(){ //retrieve file and return as string $content = file_get_contents('https://codingpad.maryspad.com/feed/'); }
The next step is to loop through each of the results pulled in by the file_get_contents() function and output just the title of the feed. I am going to use the SimpleXMLElement extension of PHP for this purpose. Going into the details of this class is beyond the scope of this tutorial, but I will post some links to tutorials that explain how to use it at the end of this post. Basically, this class represents an element in XML document. It has several methods and is a very powerful tool to know and use. So what we’re going to do is create a new instance of the SimpleXMLElement class and then pass our contents into it, and I will assign this to a new variable $feeditems.
<?php function fetchFeed(){ //retrieve file and return as string $content = file_get_contents('https://codingpad.maryspad.com/feed/'); $feeditems = new SimpleXMLElement($content); }
The next step is to now iterate over the items and then get the title of the feed item. Now if you go to https://codingpad.maryspad.com/feed/ and view source, you’ll see the XML file. Part of it will look something like this:
<channel> <title>The Coding Pad</title> <atom:link href="https://codingpad.maryspad.com/feed/" rel="self" type="application/rss+xml" /> <link>https://codingpad.maryspad.com</link> <description>Programming blog - Discussions, Tutorials, Resources</description> <lastBuildDate>Mon, 11 Jan 2010 15:13:55 +0000</lastBuildDate> <generator>http://wordpress.org/?v=2.8.6</generator> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <item> <title>MODx Revolution on Wamp with PHP 5.2.x</title> <link>https://codingpad.maryspad.com/2010/01/11/modx-revolution-and-wamp/</link> <comments>https://codingpad.maryspad.com/2010/01/11/modx-revolution-and-wamp/#comments</comments> <pubDate>Mon, 11 Jan 2010 15:13:55 +0000</pubDate> <dc:creator>mary</dc:creator> <category><![CDATA[MODx]]></category> <category><![CDATA[Revolution]]></category> <category><![CDATA[Wampserver]]></category> <guid isPermaLink="false">https://codingpad.maryspad.com/?p=1181</guid> <description><![CDATA[In this short post I am going to cover the workaround to a
Now this might look like so much gibberish but in there you can see certain tags that we’re going to use in our code to get the output we want. You can see that the entry is enclosed in < channel > tags and then inside that channel are child tags. The title of the post is enclosed in < title > tags, the link in < link > tags, etc.
So how would the code look that would allow us to iterate over the items and pull just the title of each post?
.... //iterate over item in the channel and get the title of each item foreach($feeditems->channel->item as $entry){ echo $entry->title . '<br />'; } ....
We use a foreach() loop to iterate over the items and then simply spit them out with an echo statement. Here’s the full script so far:
<?php function fetchFeed(){ //retrieve file and return as string $content = file_get_contents('https://codingpad.maryspad.com/feed/'); $feeditems = new SimpleXMLElement($content); //iterate over item in the channel and get the title of each item foreach($feeditems->channel->item as $entry){ echo $entry->title . '<br />'; } }
Make sense? Save this code as rssfetchfeed.php. Let’s now simply create another file in the same folder and call it testfeed.php. In that file, place this code:
<?php //first we include the function file require_once('rssfetchfeed.php'); //now call the function fetchFeed();
If we load testfeed.php in the browser, this is what we should see:
As you can see, this lists the titles of the current posts from my blog at the time of this posting. So far so good.
NOTE: There are some strange characters appearing in my text which I believe are related to character encoding issues. Because I’m working purely with PHP at this point, I haven’t added a doctype or any of that other stuff, and I won’t worry about that for now. If you do use this function for your own pages outside MODx then you’ll of course want to pay attention to doctype and all that other good stuff. You’ll also need to close your php block. Since this is purely PHP I don’t need to close with the ?> at the end.
I want to be able to click on the titles and be taken back to the actual post, so we need to include the link by modifying our echo statement as below:
echo "<a href='$entry->link' title='$entry->title'>" . $entry->title . '</a><br />';
If we now reload the testfeed.php page, you now see that the list of titles is now a list of links that when clicked take us to each post page.
So far so good. Now one of the good practice principles of PHP coding is to not echo things out in a function. So instead of using echo, we’re going to return the output of our script. To do this, I’ll create a string variable called $output and initialize it as an empty string. I will then concatenate subsequent outputted values to this string using the operator “.=” , which is basically the same thing as
$output = $output . 'something here';
I will then return the output at the end of the function.
Additionally, at the moment, I have the feed url hard coded into my script, but I want a user to be able to enter their own feed without having to meddle around inside my function. So to do this I’ll simply create a variable called $feed_url and pass that as an argument into my function, and I will replace the hard coded url with this variable.
The script will now look like this:
<?php function fetchFeed($feed_url){ //create a variable to hold the output $output = ''; //retrieve file and return as string</pre> $content = file_get_contents($feed_url); $feeditems = new SimpleXMLElement($content); //iterate over item in the channel and get the title of each item foreach($feeditems->channel->item as $entry){ $output .= "<a href='$entry->link' title='$entry->title'>" . $entry->title . '</a><br />'; } return $output; }
We now need to call the function into testfeed.php with the url of our feed as an argument.
... //call the function fetchFeed('https://codingpad.maryspad.com/feed/'); ...
If we reload the page we won’t see anything, because all we’re doing now is returning the output. So we need to echo the function to actually render stuff to the browser. We do this by modifying the function call in testfeed.php to read:
.... //now call the function echo fetchFeed('https://codingpad.maryspad.com/feed/');
Catching Errors
Now our script is very simple and will not parse every kind of feed there is out there, so we need some way to catch errors if the feed is not formed in such a way for our script to read and parse it. SimpleXMLElement will throw an exception if it can’t read what’s been inputted. So let’s code that in:
<?php function fetchFeed($feed_url){ //create a variable to hold the output $output = ''; //retrieve file and return as string</pre> $content = file_get_contents($feed_url); try { //all is good, we parse the feed $feeditems = new SimpleXMLElement($content);</pre> //iterate over item in the channel and get the title of each item foreach($feeditems->channel->item as $entry){ $output .= "<a href='$entry->link' title='$entry->title'>" . $entry->title . '</a><br />'; } } catch (Exception $e) { //some error occured, we output an error message and a description of the error $output .= 'An error occurred. The feed ' . $feed_url . ' could not be read: ' . $e->getMessage(); } return $output; }
As you can see, I’ve wrapped the part of my code that takes the contents of the feed and loops through them in a try statement, and then, in case the url cannot be parsed, added an error statement to that effect. So the $output at the end will either be the titles of the feed or the error statement. We can test this by adding a typo to our feed and then try to reload the page.
(You can click on the image for a larger view).
Now that we have a custom error message we don’t want that other warning at the top to appear, especially once we move into MODx, because it will throw everything off. So we can suppress errors and rely on our own custom made error to tell the user what went wrong. One way to do this is to add the following in our code.
error_reporting(0);
Of course while in development mode you want to leave error reporting on so that you can see what’s going on, but once your script is live it makes sense to suppress errors and use your own custom errors that are more friendly to the end user. But that’s a whole other topic 🙂
So for now we have a simple functional PHP script that pulls in a feed from a website or blog and outputs the post titles. We could go on and pull in text summaries and a lot of other stuff, but we want to keep this simple for now. As mentioned before, this script is not very elegant and elaborate but it should suffice for my purposes. If you need to you can download the source code using the link at the end of this post.
In the next installment, we’re going to start the process of bringing this script into our site and transforming it into a MODx snippet. See you then! 🙂
More Reading
SimpleXML Tutorial on Devzone
Will Fitch’s Tutorial on SimpleXML
Attachments
Great start. I might take this and use it to create a feed for separate Twitter feeds I’m doing for a conference site (is-conference.com). Add a little jQuery and it will be pretty sweet I think. Looking forward to more posts.
Thanks Sal, hope you find this somewhat useful. Look forward to your feedback!
Worth it to note that this will only work on servers with the php.ini var ‘allow_url_fopen’ set to 1, due to the file_get_contents call.
Thanks Shaun, that’s useful to know! I hadn’t really thought about that!
mary
Hi Mary.
Followed everything through and the first part was all OK but the second part, starting “So far so good. Now one of the good practice principles …” lost me, I couldn’t see any error message? Is it me?
Thanks
Nobert
Not sure what you mean. Where did you get lost and what error messages are you referring to? Are you able to get an output when you call your snippet?
mary
Hi,
I made a placeholder in modx to capture url parameter by using $_GET which is working fine.
But when I use this placeholder as a ‘value’ of a hidden field of my form it is not getting saved in the hidden field as I could see from the page source.
Kindly help..
thnks
Great post was having trouble putting chunks in snippets, this helped.
thanks again! 🙂