Request & Response Objects

The request and response objects provide an abstraction around HTTP requests andresponses. The request object in CakePHP allows you to introspect an incomingrequest, while the response object allows you to effortlessly create HTTPresponses from your controllers.

Request

  • class Cake\Http\ServerRequest
  • ServerRequest is the default request object used in CakePHP. It centralizes anumber of features for interrogating and interacting with request data.On each request one Request is created and then passed by reference to thevarious layers of an application that use request data. By default the requestis assigned to $this->request, and is available in Controllers, Cells, Viewsand Helpers. You can also access it in Components using the controllerreference. Some of the duties ServerRequest performs include:

  • Processing the GET, POST, and FILES arrays into the data structures you arefamiliar with.

  • Providing environment introspection pertaining to the request. Informationlike the headers sent, the client’s IP address, and the subdomain/domainnames the server your application is running on.
  • Providing access to request parameters both as array indexes and objectproperties.
    As of 3.4.0, CakePHP’s request object implements the PSR-7ServerRequestInterface making it easier touse libraries from outside of CakePHP.

Request Parameters

The request exposes routing parameters through the getParam() method:

  1. $controllerName = $this->request->getParam('controller');
  2.  
  3. // Prior to 3.4.0
  4. $controllerName = $this->request->param('controller');

To get all routing parameters as an array use getAttribute():

  1. $parameters = $this->request->getAttribute('params');

All Route Elements are accessed through this interface.

In addition to Route Elements, you also often need access toPassed Arguments. These are both available on the request object aswell:

  1. // Passed arguments
  2. $passedArgs = $this->request->getParam('pass');

Will all provide you access to the passed arguments. Thereare several important/useful parameters that CakePHP uses internally, theseare also all found in the routing parameters:

  • plugin The plugin handling the request. Will be null when there is noplugin.
  • controller The controller handling the current request.
  • action The action handling the current request.
  • prefix The prefix for the current action. See Prefix Routing formore information.

Query String Parameters

  • Cake\Http\ServerRequest::getQuery($name)
  • Query string parameters can be read using the getQuery() method:
  1. // URL is /posts/index?page=1&sort=title
  2. $page = $this->request->getQuery('page');
  3.  
  4. // Prior to 3.4.0
  5. $page = $this->request->query('page');

You can either directly access the query property, or you can usegetQuery() method to read the URL query array in an error-free manner.Any keys that do not exist will return null:

  1. $foo = $this->request->getQuery('value_that_does_not_exist');
  2. // $foo === null
  3.  
  4. // You can also provide default values
  5. $foo = $this->request->getQuery('does_not_exist', 'default val');

If you want to access all the query parameters you can usegetQueryParams():

  1. $query = $this->request->getQueryParams();

New in version 3.4.0: getQueryParams() and getQuery() were added in 3.4.0

Request Body Data

  • Cake\Http\ServerRequest::getData($name, $default = null)
  • All POST data can be accessed usingCake\Http\ServerRequest::getData(). Any form data thatcontains a data prefix will have that data prefix removed. For example:
  1. // An input with a name attribute equal to 'MyModel[title]' is accessible at
  2. $title = $this->request->getData('MyModel.title');

Any keys that do not exist will return null:

  1. $foo = $this->request->getData('Value.that.does.not.exist');
  2. // $foo == null

PUT, PATCH or DELETE Data

  • Cake\Http\ServerRequest::input($callback[, $options])
  • When building REST services, you often accept request data on PUT andDELETE requests. Any application/x-www-form-urlencoded request body datawill automatically be parsed and set to $this->data for PUT andDELETE requests. If you are accepting JSON or XML data, see below for howyou can access those request bodies.

When accessing the input data, you can decode it with an optional function.This is useful when interacting with XML or JSON request body content.Additional parameters for the decoding function can be passed as arguments toinput():

  1. $jsonData = $this->request->input('json_decode');

Environment Variables (from $_SERVER and $_ENV)

  • Cake\Http\ServerRequest::env($key, $value = null)
  • ServerRequest::env() is a wrapper for env() global function and acts asa getter/setter for environment variables without having to modify globals$_SERVER and $_ENV:
  1. // Get the host
  2. $host = $this->request->env('HTTP_HOST');
  3.  
  4. // Set a value, generally helpful in testing.
  5. $this->request->env('REQUEST_METHOD', 'POST');

To access all the environment variables in a request use getServerParams():

  1. $env = $this->request->getServerParams();

New in version 3.4.0: getServerParams() was added in 3.4.0

XML or JSON Data

Applications employing REST often exchange data innon-URL-encoded post bodies. You can read input data in any format usingHttp\ServerRequest::input(). By providing a decoding function,you can receive the content in a deserialized format:

  1. // Get JSON encoded data submitted to a PUT/POST action
  2. $jsonData = $this->request->input('json_decode');

Some deserializing methods require additional parameters when called, such asthe ‘as array’ parameter on json_decode. If you want XML converted into aDOMDocument object, Http\ServerRequest::input() supportspassing in additional parameters as well:

  1. // Get XML encoded data submitted to a PUT/POST action
  2. $data = $this->request->input('Cake\Utility\Xml::build', ['return' => 'domdocument']);

Path Information

The request object also provides useful information about the paths in yourapplication. The base and webroot attributes are useful forgenerating URLs, and determining whether or not your application is in asubdirectory. The attributes you can use are:

  1. // Assume the current request URL is /subdir/articles/edit/1?page=1
  2.  
  3. // Holds /subdir/articles/edit/1?page=1
  4. $here = $request->getRequestTarget();
  5.  
  6. // Holds /subdir
  7. $base = $request->getAttribute('base');
  8.  
  9. // Holds /subdir/
  10. $base = $request->getAttribute('webroot');
  11.  
  12. // Prior to 3.4.0
  13. $webroot = $request->webroot;
  14. $base = $request->base;
  15. $here = $request->here();

Checking Request Conditions

  • Cake\Http\ServerRequest::is($type, $args…)
  • The request object provides an easy way to inspect certain conditions in a givenrequest. By using the is() method you can check a number of commonconditions, as well as inspect other application specific request criteria:
  1. $isPost = $this->request->is('post');

You can also extend the request detectors that are available, by usingCake\Http\ServerRequest::addDetector() to create new kinds ofdetectors. There are four different types of detectors that you can create:

  • Environment value comparison - Compares a value fetched from env()for equality with the provided value.
  • Pattern value comparison - Pattern value comparison allows you to compare avalue fetched from env() to a regular expression.
  • Option based comparison - Option based comparisons use a list of options tocreate a regular expression. Subsequent calls to add an already definedoptions detector will merge the options.
  • Callback detectors - Callback detectors allow you to provide a ‘callback’ typeto handle the check. The callback will receive the request object as its onlyparameter.
  • Cake\Http\ServerRequest::addDetector($name, $options)
  • Some examples would be:
  1. // Add an environment detector.
  2. $this->request->addDetector(
  3. 'post',
  4. ['env' => 'REQUEST_METHOD', 'value' => 'POST']
  5. );
  6.  
  7. // Add a pattern value detector.
  8. $this->request->addDetector(
  9. 'iphone',
  10. ['env' => 'HTTP_USER_AGENT', 'pattern' => '/iPhone/i']
  11. );
  12.  
  13. // Add an option detector
  14. $this->request->addDetector('internalIp', [
  15. 'env' => 'CLIENT_IP',
  16. 'options' => ['192.168.0.101', '192.168.0.100']
  17. ]);
  18.  
  19. // Add a callback detector. Must be a valid callable.
  20. $this->request->addDetector(
  21. 'awesome',
  22. function ($request) {
  23. return $request->getParam('awesome');
  24. }
  25. );
  26.  
  27. // Add a detector that uses additional arguments. As of 3.3.0
  28. $this->request->addDetector(
  29. 'controller',
  30. function ($request, $name) {
  31. return $request->getParam('controller') === $name;
  32. }
  33. );

Request also includes methods likeCake\Http\ServerRequest::domain(),Cake\Http\ServerRequest::subdomains() andCake\Http\ServerRequest::host() to help applications with subdomains,have a slightly easier life.

There are several built-in detectors that you can use:

  • is('get') Check to see whether the current request is a GET.
  • is('put') Check to see whether the current request is a PUT.
  • is('patch') Check to see whether the current request is a PATCH.
  • is('post') Check to see whether the current request is a POST.
  • is('delete') Check to see whether the current request is a DELETE.
  • is('head') Check to see whether the current request is HEAD.
  • is('options') Check to see whether the current request is OPTIONS.
  • is('ajax') Check to see whether the current request came withX-Requested-With = XMLHttpRequest.
  • is('ssl') Check to see whether the request is via SSL.
  • is('flash') Check to see whether the request has a User-Agent of Flash.
  • is('requested') Check to see whether the request has a query param‘requested’ with value 1.
  • is('json') Check to see whether the request has ‘json’ extension andaccept ‘application/json’ mimetype.
  • is('xml') Check to see whether the request has ‘xml’ extension and accept‘application/xml’ or ‘text/xml’ mimetype.

New in version 3.3.0: Detectors can take additional parameters as of 3.3.0.

Session Data

To access the session for a given request use the session() method:

  1. $userName = $this->request->session()->read('Auth.User.name');

For more information, see the Sessions documentation for howto use the session object.

Host and Domain Name

  • Cake\Http\ServerRequest::domain($tldLength = 1)
  • Returns the domain name your application is running on:
  1. // Prints 'example.org'
  2. echo $request->domain();
  • Cake\Http\ServerRequest::subdomains($tldLength = 1)
  • Returns the subdomains your application is running on as an array:
  1. // Returns ['my', 'dev'] for 'my.dev.example.org'
  2. $subdomains = $request->subdomains();
  • Cake\Http\ServerRequest::host()
  • Returns the host your application is on:
  1. // Prints 'my.dev.example.org'
  2. echo $request->host();

Reading the HTTP Method

  • Cake\Http\ServerRequest::getMethod()
  • Returns the HTTP method the request was made with:
  1. // Output POST
  2. echo $request->getMethod();
  3.  
  4. // Prior to 3.4.0
  5. echo $request->method();

Restricting Which HTTP method an Action Accepts

  • Cake\Http\ServerRequest::allowMethod($methods)
  • Set allowed HTTP methods. If not matched, will throwMethodNotAllowedException. The 405 response will include the requiredAllow header with the passed methods:
  1. public function delete()
  2. {
  3. // Only accept POST and DELETE requests
  4. $this->request->allowMethod(['post', 'delete']);
  5. ...
  6. }

Reading HTTP Headers

Allows you to access any of the HTTP_* headers that were usedfor the request. For example:

  1. // Get the header as a string
  2. $userAgent = $this->request->getHeaderLine('User-Agent');
  3.  
  4. // Get an array of all values.
  5. $acceptHeader = $this->request->getHeader('Accept');
  6.  
  7. // Check if a header exists
  8. $hasAcceptHeader = $this->request->hasHeader('Accept');
  9.  
  10. // Prior to 3.4.0
  11. $userAgent = $this->request->header('User-Agent');

While some apache installs don’t make the Authorization header accessible,CakePHP will make it available through apache specific methods as required.

  • Cake\Http\ServerRequest::referer($local = false)
  • Returns the referring address for the request.

  • Cake\Http\ServerRequest::clientIp()

  • Returns the current visitor’s IP address.

Trusting Proxy Headers

If your application is behind a load balancer or running on a cloud service, youwill often get the load balancer host, port and scheme in your requests. Oftenload balancers will also send HTTP-X-Forwarded-* headers with the originalvalues. The forwarded headers will not be used by CakePHP out of the box. Tohave the request object use these headers set the trustProxy property totrue:

  1. $this->request->trustProxy = true;
  2.  
  3. // These methods will now use the proxied headers.
  4. $port = $this->request->port();
  5. $host = $this->request->host();
  6. $scheme = $this->request->scheme();
  7. $clientIp = $this->request->clientIp();

Once proxies are trusted the clientIp() method will use the last IPaddress in the X-Forwarded-For header. If your application is behindmultiple proxies, you can use setTrustedProxies() to define the IP addressesof proxies in your control:

  1. $request->setTrustedProxies(['127.1.1.1', '127.8.1.3']);

After proxies are trusted clientIp() will use the first IP address in theX-Forwarded-For header providing it is the only value that isn’t from a trustedproxy.

New in version 3.7.0: setTrustedProxies() was added.

Checking Accept Headers

  • Cake\Http\ServerRequest::accepts($type = null)
  • Find out which content types the client accepts, or check whether it accepts aparticular type of content.

Get all types:

  1. $accepts = $this->request->accepts();

Check for a single type:

  1. $acceptsJson = $this->request->accepts('application/json');
  • Cake\Http\ServerRequest::acceptLanguage($language = null)
  • Get all the languages accepted by the client,or check whether a specific language is accepted.

Get the list of accepted languages:

  1. $acceptsLanguages = $this->request->acceptLanguage();

Check whether a specific language is accepted:

  1. $acceptsSpanish = $this->request->acceptLanguage('es-es');

Cookies

Request cookies can be read through a number of methods:

  1. // Get the cookie value, or null if the cookie is missing.
  2. $rememberMe = $this->request->getCookie('remember_me');
  3.  
  4. // Read the value, or get the default of 0
  5. $rememberMe = $this->request->getCookie('remember_me', 0);
  6.  
  7. // Get all cookies as an hash
  8. $cookies = $this->request->getCookieParams();
  9.  
  10. // Get a CookieCollection instance (starting with 3.5.0)
  11. $cookies = $this->request->getCookieCollection()

See the Cake\Http\Cookie\CookieCollection documentation for howto work with cookie collection.

New in version 3.5.0: ServerRequest::getCookieCollection() was added in 3.5.0

Response

  • class Cake\Http\Response
  • Cake\Http\Response is the default response class in CakePHP.It encapsulates a number of features and functionality for generating HTTPresponses in your application. It also assists in testing, as it can bemocked/stubbed allowing you to inspect headers that will be sent.Like Cake\Http\ServerRequest, Cake\Http\Responseconsolidates a number of methods previously found on Controller,RequestHandlerComponent and Dispatcher. The oldmethods are deprecated in favour of using Cake\Http\Response.

Response provides an interface to wrap the common response-relatedtasks such as:

  • Sending headers for redirects.
  • Sending content type headers.
  • Sending any header.
  • Sending the response body.

Dealing with Content Types

  • Cake\Http\Response::withType($contentType = null)
  • You can control the Content-Type of your application’s responses withCake\Http\Response::withType(). If your application needs to dealwith content types that are not built into Response, you can map them withtype() as well:
  1. // Add a vCard type
  2. $this->response->type(['vcf' => 'text/v-card']);
  3.  
  4. // Set the response Content-Type to vcard.
  5. $this->response = $this->response->withType('vcf');
  6.  
  7. // Prior to 3.4.0
  8. $this->response->type('vcf');

Usually, you’ll want to map additional content types in your controller’sbeforeFilter() callback, so you can leverage theautomatic view switching features of RequestHandlerComponent if youare using it.

Sending Files

  • Cake\Http\Response::withFile($path, $options = [])
  • There are times when you want to send files as responses for your requests.You can accomplish that by using Cake\Http\Response::withFile():
  1. public function sendFile($id)
  2. {
  3. $file = $this->Attachments->getFile($id);
  4. $response = $this->response->withFile($file['path']);
  5. // Return the response to prevent controller from trying to render
  6. // a view.
  7. return $response;
  8. }
  9.  
  10. // Prior to 3.4.0
  11. $file = $this->Attachments->getFile($id);
  12. $this->response->file($file['path']);
  13. // Return the response to prevent controller from trying to render
  14. // a view.
  15. return $this->response;

As shown in the above example, you must pass the file path to the method.CakePHP will send a proper content type header if it’s a known file type listedin Cake\Http\Response::$_mimeTypes. You can add new types prior to callingCake\Http\Response::withFile() by using theCake\Http\Response::withType() method.

If you want, you can also force a file to be downloaded instead of displayed inthe browser by specifying the options:

  1. $response = $this->response->withFile(
  2. $file['path'],
  3. ['download' => true, 'name' => 'foo']
  4. );
  5.  
  6. // Prior to 3.4.0
  7. $this->response->file(
  8. $file['path'],
  9. ['download' => true, 'name' => 'foo']
  10. );

The supported options are:

  • name
  • The name allows you to specify an alternate file name to be sent tothe user.
  • download
  • A boolean value indicating whether headers should be set to forcedownload.

Sending a String as File

You can respond with a file that does not exist on the disk, such as a pdf or anics generated on the fly from a string:

  1. public function sendIcs()
  2. {
  3. $icsString = $this->Calendars->generateIcs();
  4. $response = $this->response;
  5.  
  6. // Inject string content into response body (3.4.0+)
  7. $response = $response->withStringBody($icsString);
  8.  
  9. // Inject string content into response body (before 3.4.0)
  10. $response->body($icsString);
  11.  
  12. $response = $response->withType('ics');
  13.  
  14. // Optionally force file download
  15. $response = $response->withDownload('filename_for_download.ics');
  16.  
  17. // Return response object to prevent controller from trying to render
  18. // a view.
  19. return $response;
  20. }

Callbacks can also return the body as a string:

  1. $path = '/some/file.png';
  2. $this->response->body(function () use ($path) {
  3. return file_get_contents($path);
  4. });

Setting Headers

  • Cake\Http\Response::withHeader($header, $value)
  • Setting headers is done with the Cake\Http\Response::withHeader()method. Like all of the PSR-7 interface methods, this method returns a _new_instance with the new header:
  1. // Add/replace a header
  2. $response = $response->withHeader('X-Extra', 'My header');
  3.  
  4. // Set multiple headers
  5. $response = $response->withHeader('X-Extra', 'My header')
  6. ->withHeader('Location', 'http://example.com');
  7.  
  8. // Append a value to an existing header
  9. $response = $response->withAddedHeader('Set-Cookie', 'remember_me=1');
  10.  
  11. // Prior to 3.4.0 - Set a header
  12. $this->response->header('Location', 'http://example.com');

Headers are not sent when set. Instead, they are held until the response isemitted by Cake\Http\Server.

You can now use the convenience methodCake\Http\Response::withLocation() to directly set or get theredirect location header.

Setting the Body

  • Cake\Http\Response::withStringBody($string)
  • To set a string as the response body, do the following:
  1. // Set a string into the body
  2. $response = $response->withStringBody('My Body');
  3.  
  4. // If you want a json response
  5. $response = $response->withType('application/json')
  6. ->withStringBody(json_encode(['Foo' => 'bar']));

New in version 3.4.3: withStringBody() was added in 3.4.3

  • Cake\Http\Response::withBody($body)
  • To set the response body, use the withBody() method, which is provided by theZend\Diactoros\MessageTrait:
  1. $response = $response->withBody($stream);
  2.  
  3. // Prior to 3.4.0 - Set the body
  4. $this->response->body('My Body');

Be sure that $stream is a Psr\Http\Message\StreamInterface object.See below on how to create a new stream.

You can also stream responses from files using Zend\Diactoros\Stream streams:

  1. // To stream from a file
  2. use Zend\Diactoros\Stream;
  3.  
  4. $stream = new Stream('/path/to/file', 'rb');
  5. $response = $response->withBody($stream);

You can also stream responses from a callback using the CallbackStream. Thisis useful when you have resources like images, CSV files or PDFs you need tostream to the client:

  1. // Streaming from a callback
  2. use Cake\Http\CallbackStream;
  3.  
  4. // Create an image.
  5. $img = imagecreate(100, 100);
  6. // ...
  7.  
  8. $stream = new CallbackStream(function () use ($img) {
  9. imagepng($img);
  10. });
  11. $response = $response->withBody($stream);
  12.  
  13. // Prior to 3.4.0 you can use the following to create streaming responses.
  14. $file = fopen('/some/file.png', 'r');
  15. $this->response->body(function () use ($file) {
  16. rewind($file);
  17. fpassthru($file);
  18. fclose($file);
  19. });

Setting the Character Set

  • Cake\Http\Response::withCharset($charset)
  • Sets the charset that will be used in the response:
  1. $this->response = $this->response->withCharset('UTF-8');
  2.  
  3. // Prior to 3.4.0
  4. $this->response->charset('UTF-8');

Interacting with Browser Caching

  1. public function index()
  2. {
  3. // Disable caching
  4. $this->response = $this->response->withDisabledCache();
  5.  
  6. // Prior to 3.4.0
  7. $this->response->disableCache();
  8. }

Warning

Disabling caching from SSL domains while trying to sendfiles to Internet Explorer can result in errors.

  • Cake\Http\Response::withCache($since, $time = '+1 day')
  • You can also tell clients that you want them to cache responses. By usingCake\Http\Response::withCache():
  1. public function index()
  2. {
  3. // Enable caching
  4. $this->response = $this->response->withCache('-1 minute', '+5 days');
  5. }

The above would tell clients to cache the resulting response for 5 days,hopefully speeding up your visitors’ experience.The withCache() method sets the Last-Modified value to the firstargument. Expires header and the max-age directive are set based on thesecond parameter. Cache-Control’s public directive is set as well.

Fine Tuning HTTP Cache

One of the best and easiest ways of speeding up your application is to use HTTPcache. Under this caching model, you are only required to help clients decide ifthey should use a cached copy of the response by setting a few headers such asmodified time and response entity tag.

Rather than forcing you to code the logic for caching and for invalidating(refreshing) it once the data has changed, HTTP uses two models, expiration andvalidation, which usually are much simpler to use.

Apart from using Cake\Http\Response::withCache(), you can also usemany other methods to fine-tune HTTP cache headers to take advantage of browseror reverse proxy caching.

The Cache Control Header

  • Cake\Http\Response::withSharable($public, $time = null)
  • Used under the expiration model, this header contains multiple indicators thatcan change the way browsers or proxies use the cached content. ACache-Control header can look like this:
  1. Cache-Control: private, max-age=3600, must-revalidate

Response class helps you set this header with some utility methods that willproduce a final valid Cache-Control header. The first is thewithSharable() method, which indicates whether a response is to beconsidered sharable across different users or clients. This method actuallycontrols the public or private part of this header. Setting a responseas private indicates that all or part of it is intended for a single user. Totake advantage of shared caches, the control directive must be set as public.

The second parameter of this method is used to specify a max-age for thecache, which is the number of seconds after which the response is no longerconsidered fresh:

  1. public function view()
  2. {
  3. // ...
  4. // Set the Cache-Control as public for 3600 seconds
  5. $this->response = $this->response->withSharable(true, 3600);
  6. }
  7.  
  8. public function my_data()
  9. {
  10. // ...
  11. // Set the Cache-Control as private for 3600 seconds
  12. $this->response = $this->response->withSharable(false, 3600);
  13. }

Response exposes separate methods for setting each of the directives inthe Cache-Control header.

The Expiration Header

  • Cake\Http\Response::withExpires($time)
  • You can set the Expires header to a date and time after which the responseis no longer considered fresh. This header can be set using thewithExpires() method:
  1. public function view()
  2. {
  3. $this->response = $this->response->withExpires('+5 days');
  4. }

This method also accepts a DateTime instance or any string that canbe parsed by the DateTime class.

The Etag Header

  • Cake\Http\Response::withEtag($tag, $weak = false)
  • Cache validation in HTTP is often used when content is constantly changing, andasks the application to only generate the response contents if the cache is nolonger fresh. Under this model, the client continues to store pages in thecache, but it asks the application every timewhether the resource has changed, instead of using it directly.This is commonly used with static resources such as images and other assets.

The withEtag() method (called entity tag) is a stringthat uniquely identifies the requested resource, as a checksum does for a file,in order to determine whether it matches a cached resource.

To take advantage of this header, you must either call thecheckNotModified() method manually or include theRequest Handling in your controller:

  1. public function index()
  2. {
  3. $articles = $this->Articles->find('all');
  4. $response = $this->response->withEtag($this->Articles->generateHash($articles));
  5. if ($response->checkNotModified($this->request)) {
  6. return $response;
  7. }
  8. $this->response = $response;
  9. // ...
  10. }

Note

Most proxy users should probably consider using the Last Modified Headerinstead of Etags for performance and compatibility reasons.

The Last Modified Header

  • Cake\Http\Response::withModified($time)
  • Also, under the HTTP cache validation model, you can set the Last-Modifiedheader to indicate the date and time at which the resource was modified for thelast time. Setting this header helps CakePHP tell caching clients whether theresponse was modified or not based on their cache.

To take advantage of this header, you must either call thecheckNotModified() method manually or include theRequest Handling in your controller:

  1. public function view()
  2. {
  3. $article = $this->Articles->find()->first();
  4. $response = $this->response->withModified($article->modified);
  5. if ($response->checkNotModified($this->request)) {
  6. return $response;
  7. }
  8. $this->response;
  9. // ...
  10. }

The Vary Header

  • Cake\Http\Response::withVary($header)
  • In some cases, you might want to serve different content using the same URL.This is often the case if you have a multilingual page or respond with differentHTML depending on the browser. Under such circumstances you can use the Varyheader:
  1. $response = $this->response->withVary('User-Agent');
  2. $response = $this->response->withVary('Accept-Encoding', 'User-Agent');
  3. $response = $this->response->withVary('Accept-Language');

Sending Not-Modified Responses

  • Cake\Http\Response::checkNotModified(Request $request)
  • Compares the cache headers for the request object with the cache header from theresponse and determines whether it can still be considered fresh. If so, deletesthe response content, and sends the 304 Not Modified header:
  1. // In a controller action.
  2. if ($this->response->checkNotModified($this->request)) {
  3. return $this->response;
  4. }

Setting Cookies

Cookies can be added to response using either an array or a Cake\Http\Cookie\Cookieobject:

  1. use Cake\Http\Cookie\Cookie;
  2. use DateTime;
  3.  
  4. // Add a cookie as an array using the immutable API (3.4.0+)
  5. $this->response = $this->response->withCookie(new Cookie(
  6. 'remember_me',
  7. 'yes',
  8. new DateTime('+1 year'), // expiration time
  9. '/', // path
  10. '', // domain
  11. false, // secure
  12. true // httponly
  13. ]);
  14.  
  15. // Before 3.4.0
  16. $this->response->cookie('remember', [
  17. 'value' => 'yes',
  18. 'path' => '/',
  19. 'httpOnly' => true,
  20. 'secure' => false,
  21. 'expire' => strtotime('+1 year')
  22. ]);

See the Creating Cookies section for how to use the cookie object. Youcan use withExpiredCookie() to send an expired cookie in the response. Thiswill make the browser remove its local cookie:

  1. // As of 3.5.0
  2. $this->response = $this->response->withExpiredCookie('remember_me');

Setting Cross Origin Request Headers (CORS)

As of 3.2 you can use the cors() method to define HTTP Access Controlrelated headers with a fluent interface:

  1. $this->response = $this->response->cors($this->request)
  2. ->allowOrigin(['*.cakephp.org'])
  3. ->allowMethods(['GET', 'POST'])
  4. ->allowHeaders(['X-CSRF-Token'])
  5. ->allowCredentials()
  6. ->exposeHeaders(['Link'])
  7. ->maxAge(300)
  8. ->build();

CORS related headers will only be applied to the response if the followingcriteria are met:

  • The request has an Origin header.
  • The request’s Origin value matches one of the allowed Origin values.

New in version 3.2: The CorsBuilder was added in 3.2

Common Mistakes with Immutable Responses

As of CakePHP 3.4.0, response objects offer a number of methods that treatresponses as immutable objects. Immutable objects help prevent difficult totrack accidental side-effects, and reduce mistakes caused by method calls causedby refactoring that change ordering. While they offer a number of benefits,immutable objects can take some getting used to. Any method that starts withwith operates on the response in an immutable fashion, and will alwaysreturn a new instance. Forgetting to retain the modified instance is the mostfrequent mistake people make when working with immutable objects:

  1. $this->response->withHeader('X-CakePHP', 'yes!');

In the above code, the response will be lacking the X-CakePHP header, as thereturn value of the withHeader() method was not retained. To correct theabove code you would write:

  1. $this->response = $this->response->withHeader('X-CakePHP', 'yes!');
  • class Cake\Http\Cookie\CookieCollection
  • CookieCollection objects are accessible from the request and response objects.They let you interact with groups of cookies using immutable patterns, whichallow the immutability of the request and response to be preserved.

Creating Cookies

  • class Cake\Http\Cookie\Cookie
  • Cookie objects can be defined through constructor objects, or by using thefluent interface that follows immutable patterns:
  1. use Cake\Http\Cookie\Cookie;
  2.  
  3. // All arguments in the constructor
  4. $cookie = new Cookie(
  5. 'remember_me', // name
  6. 1, // value
  7. new DateTime('+1 year'), // expiration time, if applicable
  8. '/', // path, if applicable
  9. 'example.com', // domain, if applicable
  10. false, // secure only?
  11. true // http only ?
  12. );
  13.  
  14. // Using the builder methods
  15. $cookie = (new Cookie('remember_me'))
  16. ->withValue('1')
  17. ->withExpiry(new DateTime('+1 year'))
  18. ->withPath('/')
  19. ->withDomain('example.com')
  20. ->withSecure(false)
  21. ->withHttpOnly(true);

Once you have created a cookie, you can add it to a new or existingCookieCollection:

  1. use Cake\Http\Cookie\CookieCollection;
  2.  
  3. // Create a new collection
  4. $cookies = new CookieCollection([$cookie]);
  5.  
  6. // Add to an existing collection
  7. $cookies = $cookies->add($cookie);
  8.  
  9. // Remove a cookie by name
  10. $cookies = $cookies->remove('remember_me');

Note

Remember that collections are immutable and adding cookies into, or removingcookies from a collection, creates a new collection object.

Cookie objects can be added to your controller responses by usingwithCookie():

  1. $response = $this->response->withCookie($cookie);

Cookies set to responses can be encrypted using theEncrypted Cookie Middleware.

Reading Cookies

Once you have a CookieCollection instance, you can access the cookies itcontains:

  1. // Check if a cookie exists
  2. $cookies->has('remember_me');
  3.  
  4. // Get the number of cookies in the collection
  5. count($cookies);
  6.  
  7. // Get a cookie instance
  8. $cookie = $cookies->get('remember_me');

Once you have a Cookie object you can interact with it’s state and modifyit. Keep in mind that cookies are immutable, so you’ll need to update thecollection if you modify a cookie:

  1. // Get the value
  2. $value = $cookie->getValue()
  3.  
  4. // Access data inside a JSON value
  5. $id = $cookie->read('User.id');
  6.  
  7. // Check state
  8. $cookie->isHttpOnly();
  9. $cookie->isSecure();

New in version 3.5.0: CookieCollection and Cookie were added in 3.5.0.