[Agavi-Users] Generating a RSS feed

0 views
Skip to first unread message

Van Daele, Koen

unread,
Jan 22, 2007, 2:58:40 AM1/22/07
to Agavi Users Mailing List
Hi,

I'd like to make a RSS feed for newsitems. I've already got an action a
a view to display the html page with the newsitems, but now I'd like to
generate a feed for this.

Do I need to define a completely different but identical action for this
or can I reuse the action and e.g. set the output type to rss? Can
anyone give an example of the different files that need to be altered
for this (routing, output_types, view, ...)?

Greetings,
Koen

_______________________________________________
users mailing list
us...@lists.agavi.org
http://lists.agavi.org/mailman/listinfo/users

David Zülke

unread,
Jan 22, 2007, 7:57:58 AM1/22/07
to Agavi Users Mailing List
Hi Koen,

you were right - all you need is a new output type!

First, you have to define that new one (e.g. "rss") in
output_types.xml. You can define a renderer if you want to use a
template to generate the output, or you omit the renderer definition
and use a library to generate the RSS content in the view (even
though I'm not aware of any PHP libraries that generate RSS).
Next, simply define executeRss() in your View and put the necessary
code in there.
Now all that's left is to decide that we want RSS as the output type
and not HTML. To do that, you have several options. You can use the
routing:
<route name="rss" stop="false" pattern="/rss$" output_type="rss" />
That will set the output type to "rss" for all URLs that end on /rss.
You can generate such an RSS variant of a URL using $r->gen('routename
+rss', ...);
Alternatively, you could use a filter, but that's not very elegant.
The last opportunity to change the output type is in your view's
initialize method, you could check a request parameter there or
something. But using the routing is definitely the way to go.

Hope that helps,

David


P.S: it is recommended that you have a MyBaseView from which all
views extend. This base view has an execute() method that throws an
exception, or forwards to a 404 action. All your specific views
implement only executeHtml(), executeRss() etc methods. That way, you
do not need to worry about the routing setting an output type that
some of your actions/views do not implement.

Van Daele, Koen

unread,
Jan 24, 2007, 4:16:33 AM1/24/07
to Agavi Users Mailing List
David,

Thanks for the explanation. Works like a charm.
One more question: is it possible to have a parameter in a route that only appears for a certain ouptut type.
E.g.: I have the route
<route name="Nieuws" pattern="^/nieuws/(page:\S+)?" module="Algemeen" action="NieuwsTonen>
<defaults>
<default for="page">1</default>
</default>
</route>

Combined with the rss output type this gives url's like /nieuws/1/rss. This is not very elegant and the page parameter is actually only relevant for the html output (sine that is paged, but rss just displays the latest X news items).

Greetings,
Koen

P.S.: I already had a baseview, but I did not have the setup with executeHtml(). Thanks for the tip.

> -----Oorspronkelijk bericht-----
> Van: users-...@lists.agavi.org
> [mailto:users-...@lists.agavi.org] Namens David Zülke
> Verzonden: maandag 22 januari 2007 13:58
> Aan: Agavi Users Mailing List
> Onderwerp: Re: [Agavi-Users] Generating a RSS feed

Van Daele, Koen

unread,
Jan 24, 2007, 5:14:32 AM1/24/07
to Agavi Users Mailing List
One more thing, generating the rss version of a route doesn't seem to work.

Echo $ro->gen('Nieuws+rss'); only generates the first part (the /rss isn't appended). Something wrong with the syntax?

Koen

> -----Oorspronkelijk bericht-----
> Van: users-...@lists.agavi.org
> [mailto:users-...@lists.agavi.org] Namens Van Daele, Koen
> Verzonden: woensdag 24 januari 2007 10:17

Van Daele, Koen

unread,
Jan 24, 2007, 6:00:48 AM1/24/07
to Agavi Users Mailing List
Well, seems I'm here again...

In the rss-template I need to put link elements that refer to the html versions. They need to be absolute links (as far as I can see, otherwise it doesn't work). I output them through $rq->getUrlHost() . $ro->gen('Nieuws'); Is there an option to generate an absolute url?
Apparently agavi automatically assumes I want the rss version (I'm guessing it detects the current output type?) and appends /rss. Is it possible to specify that this is not the rss-version but the default (html) version? Something like: $ro->gen('Nieuws-rss')?

Koen

P.S.: When I get this all sorted out I'd be willing to write it all up for the cookbook as an extended example or other. Or maybe add something similar to the default app?

> -----Oorspronkelijk bericht-----
> Van: users-...@lists.agavi.org
> [mailto:users-...@lists.agavi.org] Namens Van Daele, Koen

> Verzonden: woensdag 24 januari 2007 11:15

David Zülke

unread,
Jan 24, 2007, 6:15:01 AM1/24/07
to Agavi Users Mailing List
Koen,

what you can do here is

$r->gen('Nieuws+rss', array('page' => null));

that will skip the page parameter, which should then be empty since
it's an optional subpattern.

Let me know if that works.

Cheers,

David

David Zülke

unread,
Jan 24, 2007, 6:15:54 AM1/24/07
to Agavi Users Mailing List
Can you paste the rss rule, too, please? Maybe a small reproduce case
from routing.xml :)

Thanks,

David

Van Daele, Koen

unread,
Jan 24, 2007, 6:32:01 AM1/24/07
to Agavi Users Mailing List
I used the route you gave:

<route name="rss" stop="false" pattern="/rss$" output_type="rss" />

Is the placement within routing.xml important? Right now it's on the first line. I experimented with putting it near the end, but then the rss page never gets shown then (Makes sense, think I now understand what stop="false" does).

Koen

> -----Oorspronkelijk bericht-----
> Van: users-...@lists.agavi.org
> [mailto:users-...@lists.agavi.org] Namens David Zülke
> Verzonden: woensdag 24 januari 2007 12:16

David Zülke

unread,
Jan 24, 2007, 6:34:53 AM1/24/07
to Agavi Users Mailing List
the third argument to gen() may be an array of options. one option is
called "relative", set it to false, and the URL will be absolute.
here's a full list of all options:

"relative" (bool): relative or absolute url, defaults to true
"separator" (string): argument separator, defaults to "&amp;" for
webrouting
"use_trans_sid" (bool): whether or not to append the SID if
necessary, defaults to false (similar to PHP's session.use_trans_sid)
"scheme" (string): optional URL scheme like "https" or "ftp", default
null and therefor not used
"authority" (string): optional authority (i.e. host including port),
default null and therefor not used
"host" (string): optional host, default null and therefor not used
"port" (string): optional port, default null and therefor not used
"fragment" (string): optional fragment identifier, default null and
therefor not used

using scheme, authority, host or port sets relative to false
automatically

so you can do:

$r->gen(null, array(), array('scheme' => 'https')) to generate the
current URL, but with https as protocol
$r->gen('foo', array(), array('port' => '81')) to generate the route
foo, but with port 81 - that will insert current server hostname and
protocol
$r->gen('bar', array(), array('fragment' => 'asdf')) to generate
route bar with #asdf at the end
$r->gen(null, array(), array('relative' => false, 'port' => false))
to generate the current URL, but without a port definition (if a non-
standard port was used, it won't insert :80 for http etc)

authority is host and port. there are occasions where you need it.
for instance, you shouldn't do
$r->gen('/search', array('q' => 'test'), array('host' =>
'www.google.com'));
to generate http://www.google.com/search?q=test (remember - if a
route name isn't valid, it will be used as the literal path, so this
example really works without a route definition!).
the reason is that your app could be running on port 81 right now,
and that port would then be used, resulting in http://www.google.com:
81/search?q=test.
Same goes for the protocol, if it's https right now, that would be
used, too. So the correct way to produce the url here is:
$r->gen('/search', array('q' => 'test'), array('scheme' => 'http',
'authority' => 'www.google.com'));

You might be wondering what the point of 'host' is then - simple: if
your app runs on port 81, and you want to generate a URL, but use a
subdomain, you just use "host" to specify that subdomain, and the
port will remain the same. Same again for the protocol.

Note that you can set default options from the configuration for the
routing in factories.xml:
<routing class="AgaviWebRouting">
<parameter name="default_gen_options">
<parameter name="scheme">https</parameter>
</parameter>
</routing>

Also, as one of the last changes before RC2, we'll add the ability to
set gen options from routing callbacks later today, for additional
convenience.

As for routename-rss, I'll look into that, definitely makes sense
what you say. There must be a way to do that.

Hope that helps,


David

Van Daele, Koen

unread,
Jan 24, 2007, 7:12:32 AM1/24/07
to Agavi Users Mailing List
This works, but it leads to url's like:
/nieuws//rss

Still not as elegant as I'd like. Is there a way to make one of those slashes disappear if the parameter is not set? Or should I just define a special route for the rss page?

Koen

> -----Oorspronkelijk bericht-----
> Van: users-...@lists.agavi.org
> [mailto:users-...@lists.agavi.org] Namens David Zülke

> Verzonden: woensdag 24 januari 2007 12:15

Veikko Mäkinen

unread,
Jan 24, 2007, 7:18:23 AM1/24/07
to Agavi Users Mailing List
Van Daele, Koen wrote:
> This works, but it leads to url's like: /nieuws//rss
>
> Still not as elegant as I'd like. Is there a way to make one of those
> slashes disappear if the parameter is not set?

There is :)

Here's an example:

name="foo" pattern="foo(/{id:\d+})?/bar"

gen('foo', array('id'=>null)) -> '/foo/bar'

gen('foo', array('id'=>2)) -> '/foo/2/bar'


-veikko

Van Daele, Koen

unread,
Jan 24, 2007, 7:21:40 AM1/24/07
to Agavi Users Mailing List
Thanks for the explanation.

One thing about the 'Nieuws-rss' thing. If I include the 'page' parameter, routing skips the rss output.

So when in templates/rss.php:
$ro->gen('Nieuws') generates /nieuws/1/rss
But:
$ro->gen('Nieuws',array('page'=>null)) generates /nieuws/

Is this intentional?

Koen

> -----Oorspronkelijk bericht-----
> Van: users-...@lists.agavi.org
> [mailto:users-...@lists.agavi.org] Namens David Zülke
> Verzonden: woensdag 24 januari 2007 12:35

David Zülke

unread,
Jan 24, 2007, 7:20:05 AM1/24/07
to Agavi Users Mailing List
use

<default for="id">/{1}</default>

together with that.

David Zülke

unread,
Jan 24, 2007, 7:24:07 AM1/24/07
to Agavi Users Mailing List
Probably not. I'll look into it once I finished merging around the
branches here.

Van Daele, Koen

unread,
Jan 24, 2007, 7:31:55 AM1/24/07
to Agavi Users Mailing List
Thanks,

Now it does what I want it to do. :)

Seems I'll have to look into regex's a bit deeper. Might be able do some nice things with it. I do think it'll be difficult to explain the power of routing to users who don't have a good grasp of regexes.

Koen

> -----Oorspronkelijk bericht-----
> Van: users-...@lists.agavi.org
> [mailto:users-...@lists.agavi.org] Namens David Zülke

> Verzonden: woensdag 24 januari 2007 13:20


> Aan: Agavi Users Mailing List
> Onderwerp: Re: [Agavi-Users] Generating a RSS feed
>

David Zülke

unread,
Jan 24, 2007, 7:48:16 AM1/24/07
to Agavi Users Mailing List
That's true, however, routes aren't full regular expressions, two
restrictions apply:
- regular expressions in route patterns must be enclosed in parentheses
- non-matching pre and postfixes must be outside of the curly braces
that wrap the actual pattern

I believe <route pattern="^/products/view/(id:\d+)$" /> is relatively
straightforward even for someone with only basic knowledge of regular
expressions. all you have to know is that they may only occur in
parantheses, and that the name of the parameter that should contain
the match is at the beginning, followed by a colon.

(foo{id:\d+}bar) is a special syntax by agavi, the curly braces are
used as delimiters for pre and postfix. for "foo23bar", this example
puts only "23" into the parameter "id". that's why you hae to set the
defaults with curly braces, because the pre and postfix could also be
a regular expression, and agavi must know a constant value to use
when generating urls (since you cannot set the pre and postfix from
gen(), only the "inner" value).


David

Van Daele, Koen

unread,
Jan 24, 2007, 8:41:38 AM1/24/07
to Agavi Users Mailing List
Thanks for the info. I thought the curly braces where a subset of regex syntax. The basic stuf I understood already?

I think you explanation enables me to try something else I had been wondering about.

Koen

> -----Oorspronkelijk bericht-----
> Van: users-...@lists.agavi.org
> [mailto:users-...@lists.agavi.org] Namens David Zülke

> Verzonden: woensdag 24 januari 2007 13:48

David Zülke

unread,
Jan 24, 2007, 10:32:17 AM1/24/07
to Agavi Users Mailing List
Koen,

sorry, I totally missed this: the issue here is the missing cutting
parameter. You have to use
<route name="rss" stop="false" cut="true" pattern="/rss$"
output_type="rss" />
for this to work properly.

Cheers,

David

Reply all
Reply to author
Forward
0 new messages