11

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?

1
  • Using setResponse instead of setRedirectUrl will address this issue.
    – njp
    Aug 3, 2016 at 9:29

1 Answer 1

13

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);
}
4
  • 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, 2016 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, 2016 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 Nov 7, 2018 at 3:20
  • This worked for me.
    – Pupil
    Jan 3, 2020 at 11:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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