Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Journal of LTjake (4001)

Wednesday September 20, 2006
08:03 AM

Catalyst Tip: Easy paging using uri_with()

[ #31056 ]

Just about every app needs to do paging. Using DBIx::Class, grabbing a Data::Page object from a resultset is as easy as calling $rs->pager. Constructing the next/previous page urls can sometimes been an odd challenge. Enter uri_with.

uri_with lets you add new (or replace existing) key-value pairs in the current request's URL. The following Template Toolkit code shows you how to take a URL (eg. http://example.com/search/?q=foo) and append next and previous page numbers (eg. http://example.com/search/?q=foo&page=2). It assumes that you have a Data::Page object in a stash variable called "pager".

[% IF pager.previous_page %]
<a href="[% c.request.uri_with( page => pager.previous_page ) %]">Previous Page</a>
[% END %]
[% IF pager.next_page %]
<a href="[% c.request.uri_with( page => pager.next_page ) %]">Next Page</a>
[% END %]

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Where is that function stored? I can imagine it to be useful for people who are not using Template Toolkit, and just use Data::Pager in their CGI scripts.
    • The function resides in Catalyst::Request [cpan.org]. Its utility is fairly dependent on the fact that we use a URI object for the request URL.

      Here's the relevant snippet:

      use utf8;
      use Carp;
      use URI::QueryParam;

      sub uri_with {
          my( $self, $args ) = @_;

          carp( 'No arguments passed to uri_with()' ) unless $args;

          for my $value ( values %$args ) {
              for ( ref $value eq 'ARRAY' ? @$value : $value ) {
                  $_ = "$_";
       

      • OK, silly question perhaps... Why do you do the hard work manually, why not make use of the method query_param_append [cpan.org]?
        • Unless i'm misunderstanding your point, I don't believe that method does what we're looking for. Example: say we have the following URL

          http://www.example.com/?q=test&page=2

          ...and we're generating the "next page" url. The following test script should show the two different methods:

          use strict;
          use warnings;

          use Test::More tests => 2;

          use URI;
          use URI::QueryParam;

          my $uri      = URI->new( 'http://example.com/?q=test&page=2' );
          my $expected = {
              q    => '

          • Oh, if replacing instead of adding is what you want, then there are other methods that this module provides, such as query_param:
            If additional arguments are given, they are used to update successive parameters with the given key. If any of the values provided are array references, then the array is dereferenced to get the actual values.
            • The point is you don’t have to construct a URI object. You just call uri_with and everything except the bits you want to override is already set up for you. Buf if you haven’t used an MVCish web app framework (even an ad-hoc one of your own device), you probably won’t appreciate why that’s so very useful.

              • The point is you don’t have to construct a URI object.
                I'm not disputing that. I'm talking about the actual implementation of uri_with, which does create an object, and takes the long road to do it. It recreates every form parameter, instead of just adding new ones, and manually prepares every passed parameter for addition. This is a job the used module should have done.
  • Shouldn't the 'page' param be quoted? Like: c.request.uri_with( 'page' => pager.next_page