Skip to content

Commit

Permalink
Merge pull request cakephp#4391 from cakephp/psr7-request
Browse files Browse the repository at this point in the history
Update documentation for PSR7 requests
  • Loading branch information
markstory authored Oct 16, 2016
2 parents c731d18 + 87d9a5e commit 4ed249e
Show file tree
Hide file tree
Showing 22 changed files with 139 additions and 108 deletions.
6 changes: 3 additions & 3 deletions en/controllers/components/authentication.rst
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ calling ``$this->Auth->setUser()`` with the user data you want to 'login'::

public function register()
{
$user = $this->Users->newEntity($this->request->data);
$user = $this->Users->newEntity($this->request->data());
if ($this->Users->save($user)) {
$this->Auth->setUser($user->toArray());
return $this->redirect([
Expand Down Expand Up @@ -987,12 +987,12 @@ checked::
public function isAuthorized($user = null)
{
// Any registered user can access public functions
if (empty($this->request->params['prefix'])) {
if (!$this->request->param('prefix')) {
return true;
}

// Only admins can access admin functions
if ($this->request->params['prefix'] === 'admin') {
if ($this->request->param('prefix') === 'admin') {
return (bool)($user['role'] === 'admin');
}

Expand Down
6 changes: 3 additions & 3 deletions en/controllers/components/pagination.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ options into a custom finder method within the paginate property::
// find articles by tag
public function tags()
{
$tags = $this->request->params['pass'];
$tags = $this->request->param('pass');

$customFinderOptions = [
'tags' => $tags
Expand Down Expand Up @@ -130,7 +130,7 @@ Once the ``$paginate`` property has been defined, we can use the
pagination data, and add the ``PaginatorHelper`` if it hasn't already been
added. The controller's paginate method will return the result set of the
paginated query, and set pagination metadata to the request. You can access the
pagination metadata at ``$this->request->params['paging']``. A more complete
pagination metadata at ``$this->request->param('paging')``. A more complete
example of using ``paginate()`` would be::

class ArticlesController extends AppController
Expand Down Expand Up @@ -278,7 +278,7 @@ block and take appropriate action when a ``NotFoundException`` is caught::
$this->paginate();
} catch (NotFoundException $e) {
// Do something here like redirecting to first or last page.
// $this->request->params['paging'] will give you required info.
// $this->request->param('paging') will give you required info.
}
}

Expand Down
4 changes: 2 additions & 2 deletions en/controllers/components/request-handling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ RequestHandler will automatically switch the layout and template files to those
that match non-HTML media types. Furthermore, if a helper with the same name as
the requested extension exists, it will be added to the Controllers Helper
array. Lastly, if XML/JSON data is POST'ed to your Controllers, it will be
parsed into an array which is assigned to ``$this->request->data``, and can then
parsed into an array which is assigned to ``$this->request->data()``, and can then
be accessed as you would standard POST data. In order to make use of
RequestHandler it must be included in your ``initialize()`` method::

Expand Down Expand Up @@ -169,7 +169,7 @@ callbacks like ``json_decode``::
// After 3.1.0 you should use
$this->RequestHandler->config('inputTypeMap.json', ['json_decode', true]);

The above will make ``$this->request->data`` an array of the JSON input data,
The above will make ``$this->request->data()`` an array of the JSON input data,
without the additional ``true`` you'd get a set of ``stdClass`` objects.

.. deprecated:: 3.1.0
Expand Down
4 changes: 2 additions & 2 deletions en/controllers/components/security.rst
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ want and the Security Component will enforce them on its startup::

public function beforeFilter(Event $event)
{
if (isset($this->request->params['admin'])) {
if ($this->request->param('admin')) {
$this->Security->requireSecure();
}
}
Expand Down Expand Up @@ -196,7 +196,7 @@ require secure SSL requests::

public function forceSSL()
{
return $this->redirect('https://' . env('SERVER_NAME') . $this->request->here);
return $this->redirect('https://' . env('SERVER_NAME') . $this->request->here());
}
}

Expand Down
98 changes: 65 additions & 33 deletions en/controllers/request-response.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,29 +33,29 @@ reference. Some of the duties ``Request`` performs include:
* Providing access to request parameters both as array indexes and object
properties.

As of 3.4.0, CakePHP's request object implements the `PSR-7
ServerRequestInterface <http://www.php-fig.org/psr/psr-7/>`_ making it easier to
use libraries from outside of CakePHP.

Request Parameters
------------------

Request exposes several interfaces for accessing request parameters::
The request exposes the routing parameters through the ``param()`` method::

$this->request->params['controller'];
$this->request->param('controller');

All of the above will access the same value. All :ref:`route-elements` are
accessed through this interface.
All :ref:`route-elements` are accessed through this interface.

In addition to :ref:`route-elements`, you also often need access to
:ref:`passed-arguments`. These are both available on the request object as
well::

// Passed arguments
$this->request->pass;
$this->request['pass'];
$this->request->params['pass'];
$this->request->param('pass');

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

* ``plugin`` The plugin handling the request. Will be null when there is no
plugin.
Expand All @@ -82,6 +82,14 @@ Any keys that do not exist will return ``null``::
$foo = $this->request->query('value_that_does_not_exist');
// $foo === null

If you want to access all the query parameters you can use
``getQueryParams()``::

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

.. versionadded:: 3.4.0
``getQueryParams()`` was added in 3.4.0

Request Body Data
-----------------

Expand All @@ -99,11 +107,6 @@ Any keys that do not exist will return ``null``::
$foo = $this->request->data('Value.that.does.not.exist');
// $foo == null

You can also access the array of data, as an array::

$this->request->data['title'];
$this->request->data['comments'][1]['author'];

PUT, PATCH or DELETE Data
-------------------------

Expand Down Expand Up @@ -137,6 +140,13 @@ a getter/setter for enviromnent variables without having to modify globals
// Set a value. Generally helpful in testing.
$this->request->env('REQUEST_METHOD', 'POST');

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

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

.. versionadded:: 3.4.0
``getServerParams()`` was added in 3.4.0

XML or JSON Data
-----------------

Expand All @@ -160,20 +170,24 @@ Path Information
----------------

The request object also provides useful information about the paths in your
application. ``$request->base`` and ``$request->webroot`` are useful for
application. The ``base`` and ``webroot`` attributes are useful for
generating URLs, and determining whether or not your application is in a
subdirectory. The various properties you can use are::
subdirectory. The attributes you can use are::

// Assume the current request URL is /subdir/articles/edit/1?page=1

// Holds /subdir/articles/edit/1?page=1
$request->here;
$request->here();

// Holds /subdir
$request->base;
$request->getAttribute('base');

// Holds /subdir/
$request->getAttribute('base');

// Prior to 3.4.0
$request->webroot;
$request->base;

.. _check-the-request:

Expand Down Expand Up @@ -229,7 +243,7 @@ Some examples would be::
$this->request->addDetector(
'awesome',
function ($request) {
return isset($request->awesome);
return $request->param('awesome');
}
);

Expand Down Expand Up @@ -305,36 +319,54 @@ Returns the host your application is on::
// Prints 'my.dev.example.org'
echo $request->host();

Working With HTTP Methods & Headers
-----------------------------------
Reading the HTTP Method
-----------------------

.. php:method:: method()
.. php:method:: getMethod()
Returns the HTTP method the request was made with::

// Output POST
echo $request->getMethod();

// Prior to 3.4.0
echo $request->method();

Restricting Which HTTP method an Action Accepts
-----------------------------------------------

.. php:method:: allowMethod($methods)
Set allowed HTTP methods. If not matched, will throw MethodNotAllowedException.
The 405 response will include the required ``Allow`` header with the passed methods
Set allowed HTTP methods. If not matched, will throw ``MethodNotAllowedException``
The 405 response will include the required ``Allow`` header with the passed methods::

public function delete()
{
// Only accept POST and DELETE requests
$this->request->allowMethod(['post', 'delete']);
...
}

.. php:method:: header($name)
Reading HTTP Headers
--------------------

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

$this->request->header('User-Agent');
// Get the header as a string
$this->request->getHeaderLine('User-Agent');

would return the user agent used for the request. Some servers don't populate
``$_SERVER['HTTP_AUTHORIZATION']`` when the ``Authorization`` header is set. If
you are using Apache you can add the following to your ``.htaccess`` to allow
you to access the ``Authorization`` header::
// Get an array of all values.
$this->request->getHeader('Accept');

// Check if a header exists
$this->request->hasHeader('Accept');

// Prior to 3.4.0
$this->request->header('User-Agent');

RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
While some apache installs don't make the ``Authorization`` header accesisble,
CakePHP will make it available through apache specific methods as required.

.. php:method:: referer($local = false)
Expand All @@ -356,7 +388,7 @@ have the request object use these headers set the ``trustProxy`` property to

$this->request->trustProxy = true;

// These methods will not use the proxied headers.
// These methods will now use the proxied headers.
$this->request->port();
$this->request->host();
$this->request->scheme();
Expand Down
20 changes: 10 additions & 10 deletions en/core-libraries/form.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ and validate request data::
{
$contact = new ContactForm();
if ($this->request->is('post')) {
if ($contact->execute($this->request->data)) {
if ($contact->execute($this->request->data())) {
$this->Flash->success('We will get back to you soon.');
} else {
$this->Flash->error('There was a problem submitting your form.');
Expand All @@ -97,13 +97,13 @@ In the above example, we use the ``execute()`` method to run our form's
accordingly. We could have also used the ``validate()`` method to only validate
the request data::

$isValid = $form->validate($this->request->data);
$isValid = $form->validate($this->request->data());
Setting Form Values
===================

In order to set the values for the fields of a modelless form, one can define
the values using ``$this->request->data``, like in all other forms created by the FormHelper::
the values using ``$this->request->data()``, like in all other forms created by the FormHelper::

// In a controller
namespace App\Controller;
Expand All @@ -117,23 +117,23 @@ the values using ``$this->request->data``, like in all other forms created by th
{
$contact = new ContactForm();
if ($this->request->is('post')) {
if ($contact->execute($this->request->data)) {
if ($contact->execute($this->request->data())) {
$this->Flash->success('We will get back to you soon.');
} else {
$this->Flash->error('There was a problem submitting your form.');
}
}

if ($this->request->is('get')) {
//Values from the User Model e.g.
$this->request->data['name'] = 'John Doe';
$this->request->data['email'] = '[email protected]';
// Values from the User Model e.g.
$this->request->data('name', 'John Doe');
$this->request->data('email','[email protected]');
}

$this->set('contact', $contact);
}
}

Values should only be defined if the request method is GET, otherwise
you will overwrite your previous POST Data which might have been incorrect
and not been saved.
Expand Down
4 changes: 2 additions & 2 deletions en/development/dispatch-filters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ features that all applications are likely to need. The built-in filters are:
DispatcherFactory::add('Asset', ['cacheTime' => '+24 hours']);

* ``RoutingFilter`` applies application routing rules to the request URL.
Populates ``$request->params`` with the results of routing.
* ``ControllerFactory`` uses ``$request->params`` to locate the controller that
Populates ``$request->param()`` with the results of routing.
* ``ControllerFactory`` uses ``$request->param()`` to locate the controller that
will handle the current request.
* ``LocaleSelector`` enables automatic language switching from the ``Accept-Language``
header sent by the browser.
Expand Down
10 changes: 5 additions & 5 deletions en/development/rest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ controller might look something like this::

public function add()
{
$recipe = $this->Recipes->newEntity($this->request->data);
$recipe = $this->Recipes->newEntity($this->request->data());
if ($this->Recipes->save($recipe)) {
$message = 'Saved';
} else {
Expand All @@ -68,7 +68,7 @@ controller might look something like this::
{
$recipe = $this->Recipes->get($id);
if ($this->request->is(['post', 'put'])) {
$recipe = $this->Recipes->patchEntity($recipe, $this->request->data);
$recipe = $this->Recipes->patchEntity($recipe, $this->request->data());
if ($this->Recipes->save($recipe)) {
$message = 'Saved';
} else {
Expand Down Expand Up @@ -148,9 +148,9 @@ as input. Not to worry, the
:php:class:`Cake\\Routing\\Router` classes make things much easier. If a POST or
PUT request has an XML content-type, then the input is run through CakePHP's
:php:class:`Xml` class, and the array representation of the data is assigned to
``$this->request->data``. Because of this feature, handling XML and POST data in
``$this->request->data()``. Because of this feature, handling XML and POST data in
parallel is seamless: no changes are required to the controller or model code.
Everything you need should end up in ``$this->request->data``.
Everything you need should end up in ``$this->request->data()``.

Accepting Input in Other Formats
================================
Expand All @@ -159,7 +159,7 @@ Typically REST applications not only output content in alternate data formats,
but also accept data in different formats. In CakePHP, the
:php:class:`RequestHandlerComponent` helps facilitate this. By default,
it will decode any incoming JSON/XML input data for POST/PUT requests
and supply the array version of that data in ``$this->request->data``.
and supply the array version of that data in ``$this->request->data()``.
You can also wire in additional deserializers for alternate formats if you
need them, using :php:meth:`RequestHandler::addInputType()`.

Expand Down
Loading

0 comments on commit 4ed249e

Please sign in to comment.