Reusable Controllers

To reuse a single controller in multiple applications you can easily just inherit from your parent controller and implement it. However, if you had more than a couple controllers that you needed to do this with it could get tedious. A solution is to inherit from a single controller, and dynamically load the rest.

For this example, assume a set of controllers exists in the OtherApp::Controller::MyComponent namespace, so we have: OtherApp::Controller::MyComponent::A, OtherApp::Controller::MyComponent::B, etc. Rather than creating a mirrored set of empty 'use base qw/OtherApp::Controller::MyComponent::X/;' modules in your application, we can inherit from just OtherApp::Controller::MyComponent and dynamically build the subcontrollers.

In your Application (MyApp):

package MyApp::Controller::MyComponentImplementation;
use base qw/OtherApp::Controller::MyComponent/;

__PACKAGE__->build_subcontrollers;

In your OtherApp::Controller::MyComponent:

package OtherApp::Controller::MyComponent;
...
use base 'Catalyst::Controller';
...
sub build_subcontrollers {
    my $class = shift;

    foreach my $sub (qw(A B C D)) {
        my $base = join('::', __PACKAGE__, $sub);
        Catalyst::Utils::ensure_class_loaded($base);
        my $target = join('::', $class, $sub);
        { no strict 'refs'; @{"${target}::ISA"} = ($base); }
    }
}

The build_subcontrollers function above will load our list of subcontrollers (A, B, C, D) at runtime, so we only need to inherit and implement one controller instead of all 5.

If we were to run the above, will will have all 4 controllers available in MyApp::Controller::MyComponentImplementation namespace, as ::A, ::B, ::C and ::D

More to come on: Integrating Resources (such as view templates, etc)

Thanks to mst for his direction!

My tags:
 
Popular tags:
 
Powered by Catalyst
Powered by MojoMojo Hosted by Shadowcat - Managed by Nordaaker