Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

navneet's avatar

How to I get query strings of previous URL?

I am trying to get a query strings from previous URL in Laravel. My app is similar to Formspree where users can submit a form using and it get send to my website through POST method.

Here is a form hosted on external website

<!-- www.user-website/?ref=53saf2 -->

<form action="https://localhost:8080/s/FORM_KEY" method="POST">
  <input type="email" name="email">
  <button type="submit">Send</button>
</form>

I want to get capture ?ref=53saf2 in my Laravel controller.

I've tried

$request->headers->get('referer');

URL::previous();

$_SERVER['HTTP_REFERER'];

None of it can capture ?ref. My API route is

Route::post('s/{FORM_KEY}', [Controllers\SubmissionController::class, 'processForm']);
0 likes
8 replies
Nakov's avatar

@nano7 and you've tried:

$request->input('ref');

since you are saying that it is ?ref=53saf2 in the URL.

navneet's avatar

@Nakov I am getting null value. ?ref= is not in the input. I want to capture from external website where this form will be hosted. I can capture previous url but without query parameter (?ref=).

Nakov's avatar

@nano7 You can try using the parse_url function:

$parsedUrl = parse_url(URL::previous());
dd($parsedUrl['query']);

but you've got to make sure that that's really the previous URL that hits your endpoint when you want to parse the URL and it does not do any other redirects.

navneet's avatar

@Nakov

parse_url(URL::previous()) doesn't seems to get query. The url where form is hosted is http:// 127.0.0.1:8080 /?ref=3nswq92

^ array:4 [▼
  "scheme" => "http"
  "host" => "127.0.0.1"
  "port" => 8080
  "path" => "/"
]
kokoshneta's avatar

What do you get if you simply dd() the returned value from URL::previous()? That underlyingly retrieves the referrer header from the HTTP request; if the query string isn’t included there (which it may not be, depending on the Referrer-Policy on the external website), there’s no way to get it. If you don’t control the external website and it doesn’t send any referrer header with the HTTP request, you’re out of luck.

navneet's avatar

@kokoshneta

If form is in this url http:// 127.0.0.1:8080 /?ref=3nswq92 , I get when dd(URL::previous())

^ "http://127.0.0.1:8080/"

I get this whendd($request)

^ Illuminate\Http\Request {#42 ▼
  #json: null
  #convertedFiles: null
  #userResolver: Closure($guard = null) {#443 ▼
    class: "Illuminate\Auth\AuthServiceProvider"
    this: Illuminate\Auth\AuthServiceProvider {#152 …}
    use: {▶}
  }
  #routeResolver: Closure() {#428 ▶}
  +attributes: Symfony\Component\HttpFoundation\ParameterBag {#44 ▼
    #parameters: []
  }
  +request: Symfony\Component\HttpFoundation\InputBag {#43 ▼
    #parameters: array:1 [▼
      "email" => "[email protected]"
    ]
  }
  +query: Symfony\Component\HttpFoundation\InputBag {#50 ▼
    #parameters: []
  }
  +server: Symfony\Component\HttpFoundation\ServerBag {#46 ▼
    #parameters: array:37 [▼
      "DOCUMENT_ROOT" => "E:\dev\code\formcollection\public"
      "REMOTE_ADDR" => "127.0.0.1"
      "REMOTE_PORT" => "55028"
      "SERVER_SOFTWARE" => "PHP 8.0.2 Development Server"
      "SERVER_PROTOCOL" => "HTTP/1.1"
      "SERVER_NAME" => "127.0.0.1"
      "SERVER_PORT" => "8000"
      "REQUEST_URI" => "/s/brEa1S"
      "REQUEST_METHOD" => "POST"
      "SCRIPT_NAME" => "/index.php"
      "SCRIPT_FILENAME" => "E:\dev\code\formcollection\public\index.php"
      "PATH_INFO" => "/s/brEa1S"
      "PHP_SELF" => "/index.php/s/brEa1S"
      "HTTP_HOST" => "localhost:8000"
      "HTTP_CONNECTION" => "keep-alive"
      "CONTENT_LENGTH" => "28"
      "HTTP_CONTENT_LENGTH" => "28"
      "HTTP_CACHE_CONTROL" => "max-age=0"
      "HTTP_SEC_CH_UA" => "" Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98""
      "HTTP_SEC_CH_UA_MOBILE" => "?0"
      "HTTP_SEC_CH_UA_PLATFORM" => ""Windows""
      "HTTP_ORIGIN" => "http://127.0.0.1:8080"
      "HTTP_UPGRADE_INSECURE_REQUESTS" => "1"
      "HTTP_DNT" => "1"
      "CONTENT_TYPE" => "application/x-www-form-urlencoded"
      "HTTP_CONTENT_TYPE" => "application/x-www-form-urlencoded"
      "HTTP_USER_AGENT" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36"
      "HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
      "HTTP_SEC_FETCH_SITE" => "cross-site"
      "HTTP_SEC_FETCH_MODE" => "navigate"
      "HTTP_SEC_FETCH_USER" => "?1"
      "HTTP_SEC_FETCH_DEST" => "document"
      "HTTP_REFERER" => "http://127.0.0.1:8080/"
      "HTTP_ACCEPT_ENCODING" => "gzip, deflate, br"
      "HTTP_ACCEPT_LANGUAGE" => "en-US,en;q=0.9"
      "REQUEST_TIME_FLOAT" => 1646029787.1629
      "REQUEST_TIME" => 1646029787
    ]
  }
  +files: Symfony\Component\HttpFoundation\FileBag {#47 ▶}
  +cookies: Symfony\Component\HttpFoundation\InputBag {#45 ▶}
  +headers: Symfony\Component\HttpFoundation\HeaderBag {#48 ▶}
  #content: null
  #languages: null
  #charsets: null
  #encodings: null
  #acceptableContentTypes: null
  #pathInfo: "/s/brEa1S"
  #requestUri: "/s/brEa1S"
  #baseUrl: ""
  #basePath: null
  #method: "POST"
  #format: null
  #session: null
  #locale: null
  #defaultLocale: "en"
  -preferredFormat: null
  -isHostValid: true
  -isForwardedValid: true
  basePath: ""
  format: "html"
}
kokoshneta's avatar
Level 27

@nano7 Looks like the remote server has its Referrer-Policy set to origin, origin-when-cross-origin or strict-origin-when-cross-origin (the default value), which leaves out the query string in the HTTP headers.

That means your receiving script never has any way of knowing what the query string from the originating page is, under any circumstances, because the remote server strips it before sending the request.

It looks like both your servers are serving pages through plain HTTP, rather than HTTPS. This is fine if it’s just for localhost development, but once in production, you really should make sure everything is HTTPS.

There are three possible ways to remedy the limitation of not having access to the query string, but they all require control over the remote server as well as your own:

  1. (preferred) Use HTTPS and add the referrer as form input so it will always be sent along, and automatically encrypted: <input type="hidden" name="ref" value="<?= $_REQUEST['ref'] ?>" />
  2. (less preferred) Use HTTPS for both servers and set the remote server’s Referrer-Policy to no-referrer-when-downgrade. That will include the query string when sending HTTPS→HTTPS requests through secure connections, but not when sending HTTPS→HTTP requests. It will, however, include the query string on HTTP→HTTP requests (if neither server uses HTTPS), where it will be fully exposed, which is why this isn’t really recommended
  3. (NOT recommended) Set the remote server’s Referrer-Policy to unsafe-url. This will always include the query string, regardless of security, so everything will be exposed at all times

If you don’t have control over the remote server to change the form or the server’s Referrer-Policy, then you’re out of luck. It cannot be done.

2 likes
navneet's avatar

@kokoshneta thanks for your answer. You are right about referrer-policy. I think it's not going to work. I have now creating a JS widget that sends post data to my server.

Please or to participate in this conversation.