Zero to Mojolicious, Part 3: Using External Content from WP-API
Last time,
we created a site_design
template for Mojolicious
which built on a basic layout template for Zurb Foundation. On top of
this we can use our content-specific templates, with the two lower
templates nested below.
Here's an example that uses content from a WordPress™ Post. The simplest way to retrieve the actual content of just a post from WordPress is to use the rather new WP-API. This was to be part of WP core in their version 4.1, and although its appearance in core has been delayed, can be installed as the "WP REST API" plugin from the WP repository.
Once the WP-API plugin is enabled, we can request a URI like one on this site as:
http://blog.wlindley.com/wp-json/wp/posts/1265
That will return a JSON result with the rendered HTML (WordPress stores post and page content in the database with newline breaks instead of paragraph tags, and an assortment of other changes we do not want to deal with here) as well as a variety of metadata about the post. Unfortunately the current WP-API plugin does not let us request by post name, only by internal ID. One hopes the API will be more complete when it is fully released. Also beware the URI and request schema may differ in a final release.
We can use Mojo::UserAgent to retrieve the remote content and parse its JSON.
In a new file lib/MyApp/Controller/
then we add a controller. We use
the rendered HTML versions for the content, title, and excerpt, while
copying the other values with unmodified keys all to the stash, which
we can then reference in our template. The two templates notfound and
nopage (not shown here) are used when things go wrong.
package MyApp::Controller::Blogpage;
use Mojo::Base 'Mojolicious::Controller';
use Data::Dumper;
use Mojo::UserAgent;
# This action will render a template
sub retrieve {
my $self = shift;
my $ua = Mojo::UserAgent->new;
my $id = $self->param('id');
if (defined $id) {
$id =~ s/\D//g; # remove all non-digits
}
if (!$id) {
$self->redirect_to('notfound');
return;
}
my $tx = $ua->get("http://blog.wlindley.com/wp-json/wp/posts/${id}");
if ($tx->success) {
my $value = $tx->res->json;
# Render template "blogpage/retrieve.html.ep" with
# values from WP-API
$self->render((map { $_ => $value->{$_}->{rendered} }
qw/content title excerpt/) ,
(map { my $vname = $_;
$vname =~ s/^format\Z/wp_format/;
$vname => $value->{$_} }
qw/date type format comment_status id modified
ping_status featured_image author sticky
excerpt slug guid link/) );
} else {
$self->redirect_to('nopage');
}
}
1;
and create a template in templates/blogpage/retrieve.html.ep
. Note
how we are using the site_layout
template from last time:
% layout 'site_layout';
% title "$title";
<h1><%= $title =%></h1>
<blockquote>Published on <%= $date %></blockquote>
%== $content
Of course you can use any of the metadata tags which we copy in the controller (featured_image might be an interesting one).
Then in our MyApp.pm we add this into the startup
subroutine:
$r->get('/blog')->to('blogpage#retrieve');
Now we can visit http://localhost:3000/blog?id=1265
and you should
see the content of the WordPress post, dropped into the content section
that you made in the Foundation style theme from last time.
Next time, we still plan to access a database.