MODx Evolution: Creating a Simple Custom Snippet Part 2 – Create the Snippet

Part 0: Introduction
Part 1: Write and Test the PHP Script

In the last installment of this brief series we went through the process of creating the raw PHP script that will form the basis of our snippet. We tested the code outside of MODx and it seemed to work pretty well. In this part, we’re going to start the process of transforming this script into a MODx snippet.  As I said before, I will be working on the Learn MODx website that we built during the MODx Beginner series of tutorials.  My goal is to use the snippet to add one or maybe two sections of MODx related feeds to the sidebar of the website.  But first, we need to create the snippet itself, so let’s get to work 🙂

We begin by going into manager, and navigating to Elements->Manage Elements->Snippets where we will choose to create a New Snippet.

snippettut2_1

I know that screenshot probably wasn’t necessary, but I love screenshots 😉  We enter the snippet name (rssfeedFetcher) and a description. Then switch to the Properties tab and optionally create a new category to hold our Snippet.  I say optionally because this is really a matter of preference. I’m going to place it in a category called myRSS stuff so that it’s easier for me to keep things organized.

Switch back to the General tab.  This is where we will do most of our work.  In the editor, you can see the opening and closing PHP tags are already there by default, simply because snippets are PHP code. My personal preference is to remove the closing tag since this is pure PHP, and it prevents there being any chance of whitespace after the closing tag leading to errors.

We will now take the contents of our rssfeedFetch.php file and paste them into this editor and hit save.  We have just created a snippet. But we need to do more to allow it to work in MODx.

Before we go any further, it’s important to ensure that you understand how snippets are called.  If you’re familiar with MODx (which you should be for this series to make sense) you’ll know that a snippet call comprises the snippet name followed by a list of parameters as applicable written in a particular syntax. You’ll also recall that a snippet can be called either cached or uncached. Additionally, you’ll know the new phrase around town is back ticks, not single quotes.  If you need a refresher on any of these concepts, an excellent summary on the anatomy of snippet calls can be found in the MODx wiki.  You can also look through the MODx Beginner tutorials, particularly the one on Snippets.

If you take a look at the code we just pasted to create our snippet, you recall that we need to tell the function/snippet what the url of the feed is.  This is the argument to our function, and it transforms in MODx to a parameter in our snippet call.  Thinking a bit about how our snippet is going to work, we deduce that we need to call it uncached because it’s fetching data that is constantly being updated.  Therefore, theoretically our basic snippet call would look like this:


[!rssfeedFetcher? &feed_url=`enter the url here` !]

In other words, we’re calling the snippet uncached and we must at the very least specify the feed url.

So let’s create a test page where we’ll call the snippet and get a better view of what’s happening.  I will call my page Test Feed.  I can now call the snippet on this page as above and enter the url of my blog feed.

Calling the snippet at this point will do nothing, simply because we haven’t specified what should be returned to the browser.  In our test outside MODx, we used an echo statement in our testfeed.php to show the output of the function.  Now that we’re in MODx, we simply need to return the function itself.  The way I’m going to do this is to simply add this line of code to the end of my snippet:


return fetchFeed($feed_url);

If I now reload my Test Feed page, this is what I am presented with:

snippettut2_2

We can immediately see that the code is working and the feeds are being pulled in.  So our hard PHP work paid off! 🙂  However, we cannot rest on our laurels just yet, there’s more to be done.

Once – Birds singing.  Twice – no Dice!?! Rule #2.6

Did you do your assigned reading? Did you eat all your vegetables? Let’s try a little experiment.  Right now I have the snippet call on a main page (Test Feed) and it’s working great.  Say I want to add a different feed to my website.  Let’s go for it, let’s use our snippet to the max!  I have decided I want my site visitors to be able to see at a glance the latest MODx addons as they are added.  I am going to go into my sidebar chunk and call the snippet once more but this time I will pull in feeds from the addons section of the main MODx website.  If you’re interested, the feed url to that is http://modxcms.com/extras/rss/latestadded.xml.

So now we have the snippet call on the Test Feed page showing the latest blog posts from my blog, and another call in the sidebar pulling in the latest addons from the MODx addons section.  Let’s refresh our page, and….

snippettut2_3

Oops! We have a problem.  And yes, I ate my vegetables.  Rule #2.6 to the rescue!

Wrap functions inside !function_exists conditional if the resource is needed to run more than once on a page

If you call a snippet twice on a page, it will throw up a parsing error saying something like “Cannot redeclare functionName()”. So, if you need it to be possible to run your snippet multiple times on a page, you need to wrap it inside a !function_exists conditional block.

So let’s try that.  Let’s go back into our snippet code and wrap our function in a !function_exists() conditional and see if it will work.  My snippet code now looks like this:


<?php
if (!function_exists(fetchFeed)) {
function fetchFeed($feed_url){
//create a variable to hold the output
$output = '';

//retrieve file and return as string
$content = file_get_contents($feed_url);

try {
//all is good, we parse the feed
$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 />';
}

} 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;
}
}
return fetchFeed($feed_url);

Reload the page and…

snippettut2_4

Looking good so far. But, I can already hear you saying… that’s way too many feeds on the sidebar there.  I agree, it is.  What shall we do Caeser?

Let’s Argue some more!

The obvious solution to this problem is to add an argument to our function (aka a parameter to our snippet call) to allow the user to specify how many feeds to pull in.  From the PHP end of things, we can do this in one of several ways.  I am going to simply use an if() statement.  Generally, here’s what it would look like:


if (i < 'some limit') {

//do something

}

$i++

Basically, this is a counter.  The if() statement checks the value of my counter variable $i and compares it to ‘some limit’ and if $i is less than ‘some limit’ the code inside the curly brackets executes and the value of $i is increased by 1 ($i++).  Then it loops back around and checks if $i has reached the limit and if not it repeats.  It keeps doing this until $i reaches the limit, then it stops.  Make sense?

Since I want the limit to be set by the user, I will create a variable $limit and add it as an argument to the function.  So now things look like this:


....

function fetchFeed($feed_url, $limit) {

....

foreach($feeditems->channel->item as $entry){
 if ($i < $limit) {
 $output .= "<a href='$entry->link' title='$entry->title'>" . $entry->title . '</a><br />';
 }
 $i++;

}

.....

return fetchFeed($feed_url, $limit);

So now, in our snippet call, we can add a new parameter, &limit and use it specify how many feeds we want to show at any time.  Let’s try it.  I will call 3 feeds into the sidebar and 5 into the main page.

Here are my two snippet calls:


[!rssfeedFetcher? &feed_url=`https://codingpad.maryspad.com/feed/` &limit=`5` !]

[!rssfeedFetcher? &feed_url=`http://modxcms.com/extras/rss/latestadded.xml` &limit=`3` !]

snippettut2_5

Ah Caeser, what if they don’t want to play?

Then oh Brutus, you of little faith, we shall resort to Rule #2.10

Snippet parameters should always have a default value

The configurable parameters that a snippet has should always have default values. This is to avoid errors if some parameters are not initialized and also to make the usage of the snippet as simple as possible from an end-user’s point of view. If some parameters cannot have default values, they should be checked in the snippet code and if a value is not set, an error message should be returned to the user.

We want to ensure that if the user does not provide a limit, we have a default one in play. In other words, we’re going to make this parameter optional.  We do this by using an if() statement that says if the user sets a limit, use it; if not, use this default value x.  But to make things short and sweet we’re going to use the ternary operator.

Digression: Ternary what?

They’re really not that bad. I thought of singing a song about them but… I’ll just give you an example.  Consider this generic if() statement:


if ($weather=='sunny') {

echo 'Yay!';

} else {

echo 'Boo!'

}

We can reduce this to a one liner using the ternary operator like so:


($weather=='sunny') ? 'Yay!'  : 'Boo';

Got it?  If you’re still a little fuzzy, check out the links at the bottom of the post.

Back to the business at hand.  We want to make the $limit argument optional by adding a default value.  To do this, I’m going to add this line to my code:


$limit = (isset($limit)) ? $limit : 10;

This means that if the user doesn’t specify the number of feeds to show, the snippet will by default show 10 feeds.  Let’s take this for a spin. I am going to specify a limit of 5 for my page, but not specify any limits for my sidebar.


[!rssfeedFetcher? &feed_url=`https://codingpad.maryspad.com/feed/` &limit=`5` !]

[!rssfeedFetcher? &feed_url=`http://modxcms.com/extras/rss/latestadded.xml` !]

snippettut2_6

So now we have our snippet working relatively well, we’re able to pull in our feeds, and we’ve set things up so that we can call it more than once on a page without running into problems.  We’ve also seen how, by setting an optional parameter, we can specify how many feeds to pull in, or else just let the snippet default to a preset value.

For inquiring minds, here’s the snippet code so far:


<?php
//default parameter values
$limit = (isset($limit)) ? $limit : 10;

if (!function_exists(fetchFeed)) {
function fetchFeed($feed_url, $limit){
//create a variable to hold the output
$output = '';

//retrieve file and return as string
$content = file_get_contents($feed_url);

try {
//all is good, we parse the feed
$feeditems = new SimpleXMLElement($content);

//iterate over item in the channel and get the title of each item
foreach($feeditems->channel->item as $entry){
if ($i < $limit) {
$output .= "<a href='$entry->link' title='$entry->title'>" . $entry->title . '</a><br />';
}
$i++;
}
} 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;
}
}
return fetchFeed($feed_url, $limit);

Now taking a look at our snippet call, we notice a few more things.  The output is a simple line comprising a title with a link.  What if the user of my snippet doesn’t want it to appear that way? What if they want to output the feeds as list items, or enclose them in paragraph tags? And add a custom heading to the list of feeds? And what if, in addition to that, they want to add some custom styling to the snippet output?  Well, these are all reasonable expectations, and they should be able to do that, but these are presentational issues that I don’t want to add to my snippet. And I don’t want the user to go in and start poking around the code trying to add list tags and whatnot to the output.  What to do, what to do?

Ladies and gentlemen, I would like to introduce you to the MODx API, placeholders, chunks, and all that jazzzz…. in the next post 🙂

Stay tuned, leave some feedback, eat some vegetables, come back for more.

More Vegetables Reading

Creating Snippets – MODx Wiki
PHP Comparison Operators
Ternary Conditionals

PS: Vegetables were eaten, but no Shakespear characters were harmed in the making of this tutorial.

Part 3 – MODx API, Placeholders, Chunks

18 thoughts on “MODx Evolution: Creating a Simple Custom Snippet Part 2 – Create the Snippet”

  1. “Caesar” is misspelled. Check your English punctuation, too, especially the use of commas and periods.

  2. Excellent tutorial but just wondering why you didn’t set the default value for limit in the function like:

    function fetchFeed($feed_url, $limit = 10)

    1. Jon
      Thanks for the feedback. No particular reason really, just personal coding style preference I guess. Your way would work just as well 🙂

      mary

  3. Parse error: syntax error, unexpected $end in /home/content/65/5228165/html/manager/includes/document.parser.class.inc.php(770) : eval()’d code on line 25

    or if I add the php code to the snippet near the end of this page I get the following error.

    « MODx Parse Error »
    MODx encountered the following error while attempting to parse the requested resource:
    « PHP Parse Error »

    PHP error debug
    Error: file_get_contents(https://codingpad.maryspad.com/feed/<code clas) [function.file-get-contents]: failed to open stream: No such file or directory
    Error type/ Nr.: Warning – 2
    File: /home/content/65/5228165/html/manager/includes/document.parser.class.inc.php(770) : eval()'d code
    Line: 11

    Parser timing
    MySQL: 0.0146 s (4 Requests)
    PHP: 0.1910 s
    Total: 0.2056 s

    Please help.

  4. Thanks for the tut Mary!
    Thanks to your firsts tuts about modx I plucked up the courage to start diving in this fabulous cms. I know the basics of PHP programming (barely should I say) and decided to make my own snippets.
    So, one of the first places where I sought information, has been in you blog.
    I told you I wasn’t any near to a PHP Guru. I didn’t even know how to handle objects in php and all that stuff…
    I learned about definig a class which contains the methods, etc, and put this class in a file which I include in my snippet
    Then my snippet just handles the parameters and executes any needed function which resides in an external file which is called using include_once and didn’t need the condition to check if function exist…
    just another way……..
    kind regards
    abner
    Magic Creations

  5. Hi,
    sorry if this is not the most appropriate place to ask.
    I am building a small test site with modx to see if I can use it later for projects. I got stuck with gallery at some point.
    I have set it up, has photos in etc. But I just can not find a way to gallery to put a css class on the currently selected album. The link I mean.
    I am not sure that this feature is coded in. If that is the case, what other gallery plugin would you recommend or what is the way to implement such a useful feature?

    Many thx

  6. I am about to buid my first website with MODX Evolution (I had too many problems installing Revo). Is there a ‘How to build a website with MODX Evolution’ resource out there? I have been searching online and cant seem to find a start…….
    Thanks.

Leave a Reply