5

I've extended a FormBase and I've defined the submitForm method. In this method I want to redirect to an external URL (https://example.com/my/path?amount=33&gift=0&product_id=1)

$myurl = "https://example.com/my/path?amount=33&gift=0&product_id=1";
$redirect = Url::fromUri($myurl);
$form_state->setRedirectUrl($redirect);

And I get the error:

Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\TrustedRedirectResponse for it.

Ok, no problem, let's create one:

$myurl = "https://example.com/my/path?amount=33&gift=0&product_id=1";
$redirect = new TrustedRedirectResponse($myurl);
$form_state->setRedirectUrl($redirect);

Here's the error:

Argument 1 passed to Drupal\Core\Form\FormState::setRedirectUrl() must be an instance of Drupal\Core\Url

So it appears we've gone full circle. Is there a way that maybe I can convert the TrustedRedirectResponse to a Url object?

  • Using setResponse instead of setRedirectUrl will address this issue. – njp Aug 3 '16 at 9:29
5

You'll want to use $form_state->setResponse() instead to utilize the TrustedRedirectResponse you're creating.

Something like this should work:

public function submitForm(array &$form, FormStateInterface $form_state) {
  // Do form stuff...

  $myurl = "https://example.com/my/path?amount=33&gift=0&product_id=1";
  $response = new TrustedRedirectResponse(Url::fromUri($myurl)->toString());
  $form_state->setResponse($response);
}

This response may be cached depending on your page cache settings. If you need to change this behavior, you can modify the caching metadata. This should disable this type of caching completely for the response (not tested):

public function submitForm(array &$form, FormStateInterface $form_state) {
  // Do form stuff...

  $myurl = "https://example.com/my/path?amount=33&gift=0&product_id=1";
  $response = new TrustedRedirectResponse(Url::fromUri($myurl)->toString());

  $metadata = $response->getCacheableMetadata();
  $metadata->setCacheMaxAge(0);

  $form_state->setResponse($response);
}
  • Thanks for the insight! I may have misinterpreted what you said, but returning a TrustedRedirectResponse on the formSubmit method just reloaded the page for me - however, it turns out that instead of using setRedirectUrl (which only applies to internal paths), one can use setResponse and then pass in the TRR object. – njp Aug 3 '16 at 9:25
  • 1
    That's correct. I think I got things mixed up with how Controllers return Response objects. I'll update my answer. – hampercm Aug 3 '16 at 16:08
  • Couple of changes needed here: You're missing new infront of TrustedRedirectResponse and you have to call toString() on the Url object before passing it into the response constructor. fixed – masterchief Nov 7 '18 at 3:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.