Dynamic Pages with PyroCMS and PyroStreams

Update! September 16, 2011

Since I wrote this blog post, there have been some new developments. First of all, the PyroCMS releases after 1.3.2 will fix the bug mentioned below. Secondly, I’ve released an add-on that makes it easier to manage your custom routes, called PyroRoutes. You can download it for free here.


There has been a lot of questions on the PyroStreams forum about one subject in particular – showing dynamic info on its own page – so what follows is a guide on how to do that. Once the new Addict site is up (which has a blog), I’ll cross-post this over there.

One note – I am using PyroStreams 2 beta syntax here with the {entries} tag inside of the cycle plugin. If you are using PyroStreams 1, please adjust accordingly. If you are using 2 beta, please update to the latest version (uploaded today at 6pm EST), as it contains fixes to the single function.

Alright, let’s get started!

Pages in PyroCMS

First a little note on the relationship between pages and streams. When you create a stream, there is nothing created in the page system that tells PyroCMS to do anything but to create that stream and populate it with data. The display is up to you, which means that it is very flexible, but some things require a little bit of elbow grease.

If you’ve used ExpressionEngine before, you know that you can create a URL and EE will show you anything but a 404 (unless you have strict URLs turned on, and they are turned off by default). That means if you have a template group called products and a template inside of it called product, you could do products/product/sample-product or products/product/sample-product/features all you want. EE doesn’t really care about the URL as long as it can find something to show.

PyroCMS cares about your URL. If you give it the URL products/product/4, It is going to look for a page in your page tree called products/product/4 and try and load that page. The trick is you need to tell PyroCMS to ignore certain segments in your URL, so it will load a base page (in this case products/product-page). On that page, we’ll pay attention to what’s in the URL, and display an entry based on that.

If you are confused, don’t worry! It’s easy – below is an example.

Building a Simple Products Directory

So if you are listing products on a page, you pretty much can tell how that goes. You create a “Products” page:

In the page layout (let’s called it “Product Listing”) associated with that page (under the “Design” tab), you run through code that grabs your products:

{pyro:streams:cycle stream="products"}

<a href="products/product/{id}">{name}</a>

{/pyro:streams:cycle}

Easy enough! We are dynamically creating links to products by id. (Keep in mind, this could be a slug or something else you want to use, but for this example we’ll use IDs since every post has them.)

Now, we need to create a Product page as a child page of Products. This page has a URI of products/product-page. We can create a separate page layout for that as well. In this example we’ll call it “Product”.

Now, if we go to our product listing, and click on a product, we get a 404, because PyroCMS is looking for a page called 2 (if the id is 2) that is a child page of Product. That doesn’t exist in our pages tree, so we need to add a route.

If you are not familiar with routes, they are a CodeIgniter thing, and they are located in system/pyrocms/config/routes.php. It is a simple array that has a standard format:

$route['uri to route'] = 'uri to route to';

You can also use :any and :num to signify anything in a URI segment and a number in the URI segment, respectively.

You might ask “what are we routing to”? The answer is the view function in the pages module. So our route is going to look like this:

$route['products/product/:any'] = 'pages/view/products/product-page';

What we are doing is saying that when PyroCMS encounters a URI with products/product/, and anything in the third segment (our id, slug, whatever), it will load up products/product-page. Notice that we don’t use any routing variables like $1 because we don’t want to pass dynamic info to the root value – we just want PyroCMS to ignore some segments.

Bypassing a Bug

I will add a pull request for this ASAP, but doing this throws an error in PyroCMS 1.2 and above. This is because of a bug (what I think is a bug anyways) in the pages module. Luckily, the fix is really easy. Go to system/pyrocms/modules/pages/controllers/pages.php and change line 43 to:

$url_segments = $this->uri->total_rsegments() > 0 ? array_slice($this->uri->rsegment_array(), 2) : null;

That’s it! You should be set to go now.

Displaying Dynamic Data

No you should be able to click on any one of your product links, and you won’t get a 404. Awesome! Now we just need to display some dynamic data.

You can use the cycle plugin if you want but we have a simplified function called single in PyroStreams 2 that you can use. It basically just eliminates the need to use “entries” and limit 1 and all that stuff. So in our Product page layout, we have this code:

{pyro:streams:single stream="products" id="[segment_3]"}

<h1>{name}</h1>

{/pyro:streams:single}

Simple as that – we can tell it to grab the ID using our (PyroStreams 2 only) segment variables. Using the cycle plugin you can do:

{pyro:streams:cycle stream="products" where="id==seg_3" limit="1"}

{entries}

<h1>{name}</h1>

{/entries}

{/pyro:streams:cycle}​

That should cover it! I’ll be posting some more how-to’s here on PyroStreams just as soon as I get the last damn bits of PyroStreams 2 finished!

This entry was posted in Code, PyroCMS and tagged . Bookmark the permalink.
  • http://twitter.com/chiste Carlos Vidal

    Thanks Adam.

    Just one question. I bought PyroStreams from PyroCMS website. Do you upload the new version there?

    Carlos Vidal

  • http://twitter.com/adamfairholm Adam Fairholm

    Carlos,

    Yes – every time I update PyroStreams I update it on the Addict website as well as the downloadable package on the PyroCMS website. The PyroCMS website has a zip that contains PyroStreams 1.1.3 and PyroStream 2 beta.

    Adam

  • Mschenker

    Hey Adam,
    I’m still very new at PyroCMS and Pyro Streams, so my comments will probably embarrassing to me one day.  However, I must admit I don’t follow what you’re saying to do.

    It seems to be just what I need, but I can’t quite get the steps to come together.

    Thanks,
    Matthew

  • http://twitter.com/adamfairholm Adam Fairholm

    Hey Matthew,

    What step are you having trouble at? Meaning, up until what part are you able to follow? Let’s start there and see if we can get it worked out.

    Adam

  • Mschenker

    Adam,
    Thank you for responding, and again I emphasize that it’s probably just my inexperience with PyroCMS and Pyro Streams.

    Let me gather my responses in a more organized fashion and report back later.  This is definitely worth pursuing for me because I see such terrific potential here!

    Thanks again,
    Matthew

  • gcoulthard

    Wonderful — Working nicely now. Thanks for your help! — Glen

  • Mschenker

    Adam,
    Again, probably my inexperience with PyroCMS….

    To update PyroStreams, can we just FTP the contents of the new “Streams” folder into the addons/modules/streams folder?

    Thanks,
    Matthew

  • http://twitter.com/adamfairholm Adam Fairholm

    Matthew – correct – you just overwrite the folder and overwrite it. You should also go to the add-ons section and click “Upgrade”. That way the DB schema is updated if it needs to be.

  • Mschenker

    Hello,
    Still stuck on this… For whatever reason, I just can’t make it work.

    Is there any chance this kind of capability will be built into the new PyroStreams release?

  • Jitse

    I want to use PyroStreams to display specific images on the pages.
    I’m trying to use the following code in PyroCMS 2.0 Professional:

    {{ streams:cycle stream=”images” where=”page_number=={{ page:id }}” }}
    With this where syntax, I can’t get it to work…

    {{ streams:cycle stream=”images” where=”page_number==2″ }}

    This does work, but thats not how I want it…

    Any suggestions?

  • Asdasd

    dsdsdf