Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

How to use Controller::handleRequest() correctly


Go to End


8 Posts   3251 Views

Avatar
Mo

Community Member, 541 Posts

30 March 2015 at 6:02am

Hi All,

This is something I have been trying to work out for some time and am still finding it a bit difficult to unpick.

I get the basic concept, you have a controller ($controller) and you then add a handleRequest method to that controller and then handleRequest is called when the controller is matched by a route.

As far as I am aware, if I want to then use another controller to handle a URL I then pass the request to the new controller using handlleRequest() on that controller?

Is that the case? If so, are there any docs on how to do this propperly? If not, is this how I would go about handing over a request to another controller?

The use case I have currently is as follows:

I have "Payment_Controller", this is responsible for sending users to and recieving data from Payment Gateways (such as Paypal, WorldPay, Stripe, etc).

If I want to add a new payment gateway, I add a new controller that extends an abstract controller (called PaymentHandler).

When the URL "/payment/index/paypal" or "/payment/callback/paypal" is called, I want Payment_Controller to automatically hand over control to the PayPal controller. Then I will be free to impliment whatever code I want inside Paypal_Controller such as redirect the user, return a template (or anything else I would do with a controller).

Anyone got and advice on how to do this? Is handleRequest() the right way to go?

Cheers,

Mo

Avatar
Mo

Community Member, 541 Posts

2 April 2015 at 10:33pm

Hi Pyromanik,

Yes I am aware of the payment module (and have been for some time), the example I have given is just one example but I need to understand how this works for some other projects I am working on elsewhere.

Mo

Avatar
dhensby

Community Member, 253 Posts

2 April 2015 at 10:52pm

Hey Mo,

This is something I solved recently.

You actually want to overoad handle action and not much else:


/**
 * Base request handling controller for Member section
 */
class RootMemberController extends MemberController {

	/**
	 * @config
	 * @var array
	 */
	private static $allowed_actions = array(
		'register',
	);

	/**
	 * Set up the "restful" URLs
	 *
	 * @config
	 * @var array
	 */
	private static $url_handlers = array(
		'$ID/profile' => 'index',
		'$ID/$Action' => 'handleAction',
	);

	/**
	 * @param SS_HTTPRequest $request
	 *
	 * @return SS_HTTPResponse
	 */
	public function index($request) {
		return MemberProfileController::create($this->getMember())->handleRequest($request, $this->model);
	}

	/**
	 * @param SS_HTTPRequest $request
	 *
	 * @return SS_HTTPResponse
	 */
	public function register($request) {
		return MemberRegisterController::create($this->getMember())->handleRequest($request, $this->model);
	}

	/**
	 * @param SS_HTTPRequest $request
	 * @param $model
	 *
	 * @return HTMLText|SS_HTTPResponse
	 */
	protected function handleAction($request, $model) {
		//we return nested controllers, so the parsed URL params need to be discarded for the subsequent controllers
		// to work
		$request->shiftAllParams();
		return parent::handleAction($request, $model);
	}

}

the reason for shiftng off the params from the request is so that the nested controllers can be agnostic to the full URL and only need to know about the parts they are concerned with.

Avatar
Mo

Community Member, 541 Posts

8 April 2015 at 10:01pm

Hi DHensby,

Ok, this makes some sense (I think).

How have you setup your routes? I am assuming you have a routes.yml? Does it look like:

Director:
  rules:
    'member//$ID/$Action': 'RootMemberController'

Or something more like

Director:
  rules:
    'member: 'RootMemberController'

Just trying to get right in my head how you are routing URL's and at what point Silverstripe know's how to determine $ID and $Action.

Hope that makes sense?

Cheers,

Mo

Avatar
dhensby

Community Member, 253 Posts

8 April 2015 at 10:25pm

Yep, just like your first routes.yml

Avatar
Mo

Community Member, 541 Posts

9 April 2015 at 4:40am

Ok, I think I see how this is working then. Trouble is with SilverStripe is that I often consider handleAction to involve forms (as for some reason, buttons in forms are also called Actions in Silverstripe).

But that is probably just me!

I will have a play around and see if I can get anywhere :-).

Cheers,

Mo

Avatar
Mo

Community Member, 541 Posts

14 April 2015 at 9:18am

Wow, ok, this works really well! I had assumed there must be a fairly easy way for SS to hand control of an action over to another object, but until now hadn't managed to work it out!

Thanks a lot.

Mo