diff --git a/config/all.py b/config/all.py
index d0e8b66c4c..170e758fc2 100644
--- a/config/all.py
+++ b/config/all.py
@@ -103,3 +103,7 @@
# The depth of the table of contents in toc.ncx.
epub_tocdepth = 2
+
+rst_epilog = """
+.. |minphpversion| replace:: 7.1.0
+"""
diff --git a/en/appendices/4-0-migration-guide.rst b/en/appendices/4-0-migration-guide.rst
index a59d49ec92..21706e0d06 100644
--- a/en/appendices/4-0-migration-guide.rst
+++ b/en/appendices/4-0-migration-guide.rst
@@ -2,7 +2,7 @@
###################
CakePHP 4.0 contains breaking changes, and is not backwards compatible with 3.x
-releases. Before attempting to upgrade to 4.0, first upgrade to 3.6 and resolve
+releases. Before attempting to upgrade to 4.0, first upgrade to 3.7 and resolve
all deprecation warnings.
To upgrade to 4.0.x run the following composer command:
diff --git a/en/console-and-shells.rst b/en/console-and-shells.rst
index 75aec129e8..b9c45e0647 100644
--- a/en/console-and-shells.rst
+++ b/en/console-and-shells.rst
@@ -51,7 +51,7 @@ comes with an executable in the **bin** directory:
Running the Console with no arguments produces this help message::
- Welcome to CakePHP v3.6.0 Console
+ Welcome to CakePHP v4.0.0 Console
---------------------------------------------------------------
App : App
Path: /Users/markstory/Sites/cakephp-app/src/
diff --git a/en/contributing/code.rst b/en/contributing/code.rst
index dc13e9076b..6ed2c45b55 100644
--- a/en/contributing/code.rst
+++ b/en/contributing/code.rst
@@ -122,12 +122,12 @@ branch, as you cannot edit it once the pull request is created.
choose **master** as your merge target.
* If your change is a **new feature** or an addition to the framework, then you
should choose the branch with the next version number. For example if the
- current stable release is ``3.6.0``, the branch accepting new features will
- be ``3.next``.
+ current stable release is ``4.0.0``, the branch accepting new features will
+ be ``4.next``.
* If your change is a breaks existing functionality, or API's then you'll have
to choose then next major release. For example, if the current release is
- ``3.6.0`` then the next time existing behavior can be broken will be in
- ``4.x`` so you should target that branch.
+ ``4.0.0`` then the next time existing behavior can be broken will be in
+ ``5.x`` so you should target that branch.
.. note::
diff --git a/en/controllers/middleware.rst b/en/controllers/middleware.rst
index 2756f93422..760e530718 100644
--- a/en/controllers/middleware.rst
+++ b/en/controllers/middleware.rst
@@ -68,15 +68,16 @@ process, you can use the ``MiddlewareQueue`` object to attach middleware::
namespace App;
use Cake\Http\BaseApplication;
+ use Cake\Http\MiddlewareQueue;
use Cake\Error\Middleware\ErrorHandlerMiddleware;
class Application extends BaseApplication
{
- public function middleware($middlewareQueue)
+ public function middleware(MiddlewareQueue $middlwareQueue): MiddlewareQueue
{
// Bind the error handler into the middleware queue.
- $middlewareQueue->add(new ErrorHandlerMiddleware());
- return $middlewareQueue;
+ $middlwareQueue->add(new ErrorHandlerMiddleware());
+ return $middlwareQueue;
}
}
@@ -86,19 +87,19 @@ a variety of operations::
$layer = new \App\Middleware\CustomMiddleware;
// Added middleware will be last in line.
- $middlewareQueue->add($layer);
+ $middlwareQueue->add($layer);
// Prepended middleware will be first in line.
- $middlewareQueue->prepend($layer);
+ $middlwareQueue->prepend($layer);
// Insert in a specific slot. If the slot is out of
// bounds, it will be added to the end.
- $middlewareQueue->insertAt(2, $layer);
+ $middlwareQueue->insertAt(2, $layer);
// Insert before another middleware.
// If the named class cannot be found,
// an exception will be raised.
- $middlewareQueue->insertBefore(
+ $middlwareQueue->insertBefore(
'Cake\Error\Middleware\ErrorHandlerMiddleware',
$layer
);
@@ -106,7 +107,7 @@ a variety of operations::
// Insert after another middleware.
// If the named class cannot be found, the
// middleware will added to the end.
- $middlewareQueue->insertAfter(
+ $middlwareQueue->insertAfter(
'Cake\Error\Middleware\ErrorHandlerMiddleware',
$layer
);
@@ -118,110 +119,25 @@ middleware to specific sets of routes using
Adding Middleware from Plugins
------------------------------
-After the middleware queue has been prepared by the application, the
-``Server.buildMiddleware`` event is triggered. This event can be useful to add
-middleware from plugins. Plugins can register listeners in their bootstrap
-scripts, that add middleware::
-
- // In ContactManager plugin bootstrap.php
- use Cake\Event\EventManager;
-
- EventManager::instance()->on(
- 'Server.buildMiddleware',
- function ($event, $middlewareQueue) {
- $middlewareQueue->add(new ContactPluginMiddleware());
- });
-
-PSR-7 Requests and Responses
-============================
-
-Middleware and the new HTTP stack are built on top of the `PSR-7 Request
-& Response Interfaces `__. While all
-middleware will be exposed to these interfaces, your controllers, components,
-and views will *not*.
-
-Interacting with Requests
--------------------------
-
-The ``RequestInterface`` provides methods for interacting with the headers,
-method, URI, and body of a request. To interact with the headers, you can::
-
- // Read a header as text
- $value = $request->getHeaderLine('Content-Type');
-
- // Read header as an array
- $value = $request->getHeader('Content-Type');
-
- // Read all the headers as an associative array.
- $headers = $request->getHeaders();
-
-Requests also give access to the cookies and uploaded files they contain::
-
- // Get an array of cookie values.
- $cookies = $request->getCookieParams();
-
- // Get a list of UploadedFile objects
- $files = $request->getUploadedFiles();
-
- // Read the file data.
- $files[0]->getStream();
- $files[0]->getSize();
- $files[0]->getClientFileName();
-
- // Move the file.
- $files[0]->moveTo($targetPath);
+Plugins can use their ``middleware`` hook method to apply any middleware they
+have to the application's middleware queue::
-Requests contain a URI object, which contains methods for interacting with the
-requested URI::
+ // in plugins/ContactManager/src/Plugin.php
+ namespace ContactManager;
- // Get the URI
- $uri = $request->getUri();
-
- // Read data out of the URI.
- $path = $uri->getPath();
- $query = $uri->getQuery();
- $host = $uri->getHost();
-
-Lastly, you can interact with a request's 'attributes'. CakePHP uses these
-attributes to carry framework specific request parameters. There are a few
-important attributes in any request handled by CakePHP:
-
-* ``base`` contains the base directory for your application if there is one.
-* ``webroot`` contains the webroot directory for your application.
-* ``params`` contains the results of route matching once routing rules have been
- processed.
-* ``session`` contains an instance of CakePHP's ``Session`` object. See
- :ref:`accessing-session-object` for more information on how to use the session
- object.
-
-Interacting with Responses
---------------------------
-
-The methods available to create a server response are the same as those
-available when interacting with :ref:`httpclient-response-objects`. While the
-interface is the same the usage scenarios are different.
-
-When modifying the response, it is important to remember that responses are
-**immutable**. You must always remember to store the results of any setter
-method. For example::
-
- // This does *not* modify $response. The new object was not
- // assigned to a variable.
- $response->withHeader('Content-Type', 'application/json');
-
- // This works!
- $newResponse = $response->withHeader('Content-Type', 'application/json');
-
-Most often you'll be setting headers and response bodies on requests::
+ use Cake\Core\BasePlugin;
+ use Cake\Http\MiddlewareQueue;
+ use ContactManager\Middleware\ContactManagerContextMiddleware;
- // Assign headers and a status code
- $response = $response->withHeader('Content-Type', 'application/json')
- ->withHeader('Pragma', 'no-cache')
- ->withStatus(422);
+ class Plugin extends BasePlugin
+ {
+ public function middleware(MiddlewareQueue $middlwareQueue): MiddlewareQueue
+ {
+ $middlwareQueue->add(new ContactManagerContextMiddleware());
- // Write to the body
- $body = $response->getBody();
- $body->write(json_encode(['errno' => $errorCode]));
+ return $middlwareQueue;
+ }
+ }
Creating Middleware
===================
@@ -252,7 +168,10 @@ creating their own response. We can see both options in our simple middleware::
class TrackingCookieMiddleware implements MiddlewareInterface
{
- public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
+ public function process(
+ ServerRequestInterface $request,
+ RequestHandlerInterface $handler
+ ): ResponseInterface
{
// Calling $handler->handle() delegates control to the *next* middleware
// In your application's queue.
@@ -282,14 +201,14 @@ application::
class Application
{
- public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
+ public function middleware(MiddlewareQueue $middlwareQueue): MiddlewareQueue
{
// Add your simple middleware onto the queue
- $middlewareQueue->add(new TrackingCookieMiddleware());
+ $middlwareQueue->add(new TrackingCookieMiddleware());
// Add some more middleware onto the queue
- return $middlewareQueue;
+ return $middlwareQueue;
}
}
@@ -306,10 +225,10 @@ enable cached routes, provide the desired :ref:`cache configuration
` as a parameter::
// In Application.php
- public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
+ public function middleware(MiddlewareQueue $middlwareQueue): MiddlewareQueue
{
// ...
- $middlewareQueue->add(new RoutingMiddleware($this, 'routing'));
+ $middlwareQueue->add(new RoutingMiddleware($this, 'routing'));
}
The above would use the ``routing`` cache engine to store the generated route
@@ -344,7 +263,7 @@ your application's middleware stack::
->noOpen()
->noSniff();
- $middlewareQueue->add($securityHeaders);
+ $middlwareQueue->add($securityHeaders);
.. _encrypted-cookie-middleware:
@@ -364,7 +283,7 @@ Cookie data is encrypted with via OpenSSL using AES::
Configure::read('Security.cookieKey')
);
- $middlewareQueue->add($cookies);
+ $middlwareQueue->add($cookies);
.. note::
It is recommended that the encryption key you use for cookie data, is used
@@ -392,14 +311,14 @@ stack you protect all the actions in application::
// in src/Application.php
use Cake\Http\Middleware\CsrfProtectionMiddleware;
- public function middleware($middlewareQueue) {
+ public function middleware($middlwareQueue) {
$options = [
// ...
];
$csrf = new CsrfProtectionMiddleware($options);
- $middlewareQueue->add($csrf);
- return $middlewareQueue;
+ $middlwareQueue->add($csrf);
+ return $middlwareQueue;
}
By applying the ``CsrfProtectionMiddleware`` to routing scopes, you can include
diff --git a/en/controllers/request-response.rst b/en/controllers/request-response.rst
index 57741535fe..3f210e393b 100644
--- a/en/controllers/request-response.rst
+++ b/en/controllers/request-response.rst
@@ -32,7 +32,7 @@ reference. Some of the duties ``ServerRequest`` 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
+CakePHP's request object implements the `PSR-7
ServerRequestInterface `_ making it easier to
use libraries from outside of CakePHP.
@@ -279,9 +279,12 @@ There are several built-in detectors that you can use:
Session Data
------------
-To access the session for a given request use the ``session()`` method::
+To access the session for a given request use the ``getSession()`` method or use the ``session`` attribute::
- $userName = $this->request->session()->read('Auth.User.name');
+ $session = $this->request->getSession();
+ $session = $this->request->getAttribute('session');
+
+ $userName = $session->read('Auth.User.name');
For more information, see the :doc:`/development/sessions` documentation for how
to use the session object.
@@ -442,6 +445,39 @@ Request cookies can be read through a number of methods::
See the :php:class:`Cake\\Http\\Cookie\\CookieCollection` documentation for how
to work with cookie collection.
+
+Uploaded Files
+--------------
+
+Requests expose the uploaded file data in ``getData()`` as
+arrays, and as ``UploadedFileInterface`` objects by ``getUploadedFiles()``::
+
+ // Get a list of UploadedFile objects
+ $files = $request->getUploadedFiles();
+
+ // Read the file data.
+ $files[0]->getStream();
+ $files[0]->getSize();
+ $files[0]->getClientFileName();
+
+ // Move the file.
+ $files[0]->moveTo($targetPath);
+
+Manipulating URIs
+-----------------
+
+Requests contain a URI object, which contains methods for interacting with the
+requested URI::
+
+ // Get the URI
+ $uri = $request->getUri();
+
+ // Read data out of the URI.
+ $path = $uri->getPath();
+ $query = $uri->getQuery();
+ $host = $uri->getHost();
+
+
.. index:: $this->response
Response
diff --git a/en/core-libraries/httpclient.rst b/en/core-libraries/httpclient.rst
index e4dd33ea05..ceeac993ad 100644
--- a/en/core-libraries/httpclient.rst
+++ b/en/core-libraries/httpclient.rst
@@ -74,12 +74,6 @@ You can include files in request bodies by including a filehandle in the array::
The filehandle will be read until its end; it will not be rewound before being read.
-.. warning::
-
- For compatibility reasons, earlier versions of CakePHP will treat strings
- beginning with ``@`` as local or remote file paths. This functionality was
- deprecated in CakePHP 3.0.5 and was removed in a 3.7.
-
Building Multipart Request Bodies by Hand
-----------------------------------------
diff --git a/en/development/application.rst b/en/development/application.rst
index 89401c242d..357f557f4c 100644
--- a/en/development/application.rst
+++ b/en/development/application.rst
@@ -20,33 +20,58 @@ methods:
* ``console`` Used to add :doc:`console commands ` to your
application. By default this will automatically discover shells & commands in
your application and all plugins.
-* ``events`` Used to add :doc:`event listeners ` to the
- application event manager.
-.. _adding-http-stack:
+Bootstrapping your Application
+==============================
-Adding the new HTTP Stack to an Existing Application
-====================================================
+If you have any additional configuration needs, you should add them to your
+application's **config/bootstrap.php** file. This file is included before each
+request, and CLI command.
-Using the Application class and HTTP Middleware in an existing application
-requires a few changes to your code.
+This file is ideal for a number of common bootstrapping tasks:
-#. First update your **webroot/index.php**. Copy the file contents from the `app
- skeleton `__.
-#. Create an ``Application`` class. See the :ref:`using-middleware` section
- above for how to do that. Or copy the example in the `app skeleton
- `__.
-#. Create **config/requirements.php** if it doesn't exist and add the contents
- from the `app skeleton `__.
-#. If you are using the ``CsrfProtectionMiddleware`` make sure you remove the
- ``CsrfComponent`` from your controllers.
+- Defining convenience functions.
+- Declaring constants.
+- Defining cache configuration.
+- Defining logging configuration.
+- Loading custom inflections.
+- Loading configuration files.
-Once those three steps are complete, you are ready to start re-implementing any
-application/plugin dispatch filters as HTTP middleware.
+It might be tempting to place formatting functions there in order to use them in
+your controllers. As you'll see in the :doc:`/controllers` and :doc:`/views`
+sections there are better ways you add custom logic to your application.
-If you are running tests you will also need to update your
-**tests/bootstrap.php** by copying the file contents from the `app skeleton
-`_.
+.. _application-bootstrap:
+
+Application::bootstrap()
+------------------------
+
+In addition to the **config/bootstrap.php** file which should be used to
+configure low-level concerns of your application, you can also use the
+``Application::bootstrap()`` hook method to load/initialize plugins, and attach
+global event listeners::
+
+ // in src/Application.php
+ namespace App;
+
+ use Cake\Core\Plugin;
+ use Cake\Http\BaseApplication;
+
+ class Application extends BaseApplication
+ {
+ public function bootstrap()
+ {
+ // Call the parent to `require_once` config/bootstrap.php
+ parent::bootstrap();
+
+ // Load MyPlugin
+ $this->addPlugin('MyPlugin');
+ }
+ }
+
+Loading plugins and events in ``Application::bootstrap()`` makes
+:ref:`integration-testing` easier as events and routes will be re-processed on
+each test method.
.. meta::
:title lang=en: CakePHP Application
diff --git a/en/development/configuration.rst b/en/development/configuration.rst
index ca11a35e2b..7e65b8757d 100644
--- a/en/development/configuration.rst
+++ b/en/development/configuration.rst
@@ -523,57 +523,6 @@ The built in configuration engines are:
By default your application will use ``PhpConfig``.
-Bootstrapping CakePHP
-=====================
-
-If you have any additional configuration needs, you should add them to your
-application's **config/bootstrap.php** file. This file is included before each
-request, and CLI command.
-
-This file is ideal for a number of common bootstrapping tasks:
-
-- Defining convenience functions.
-- Declaring constants.
-- Defining cache configuration.
-- Defining logging configuration.
-- Loading custom inflections.
-- Loading configuration files.
-
-It might be tempting to place formatting functions there in order to use them in
-your controllers. As you'll see in the :doc:`/controllers` and :doc:`/views`
-sections there are better ways you add custom logic to your application.
-
-.. _application-bootstrap:
-
-Application::bootstrap()
-------------------------
-
-In addition to the **config/bootstrap.php** file which should be used to
-configure low-level concerns of your application, you can also use the
-``Application::bootstrap()`` hook method to load/initialize plugins, and attach
-global event listeners::
-
- // in src/Application.php
- namespace App;
-
- use Cake\Core\Plugin;
- use Cake\Http\BaseApplication;
-
- class Application extends BaseApplication
- {
- public function bootstrap()
- {
- // Call the parent to `require_once` config/bootstrap.php
- parent::bootstrap();
-
- $this->addPlugin('MyPlugin', ['bootstrap' => true, 'routes' => true]);
- }
- }
-
-Loading plugins/events in ``Application::bootstrap()`` makes
-:ref:`integration-testing` easier as events and routes will be re-processed on
-each test method.
-
Disabling Generic Tables
========================
diff --git a/en/development/routing.rst b/en/development/routing.rst
index 975a0d9ada..01758abb30 100644
--- a/en/development/routing.rst
+++ b/en/development/routing.rst
@@ -21,7 +21,7 @@ Quick Tour
This section will teach you by example the most common uses of the CakePHP
Router. Typically you want to display something as a landing page, so you add
-this to your **routes.php** file::
+this to your **config/routes.php** file::
use Cake\Routing\Router;
diff --git a/en/development/testing.rst b/en/development/testing.rst
index 7c289c625d..35c255cb44 100644
--- a/en/development/testing.rst
+++ b/en/development/testing.rst
@@ -1094,16 +1094,12 @@ If you want to assert the presence of flash messages in the session and not the
rendered HTML, you can use ``enableRetainFlashMessages()`` in your tests to
retain flash messages in the session so you can write assertions::
+ // Enable retention of flash messages instead of consuming them.
$this->enableRetainFlashMessages();
$this->get('/bookmarks/delete/9999');
$this->assertSession('That bookmark does not exist', 'Flash.flash.0.message');
-As of 3.7.0 there are additional test helpers for flash messages::
-
- $this->enableRetainFlashMessages();
- $this->get('/bookmarks/delete/9999');
-
// Assert a flash message in the 'flash' key.
$this->assertFlashMessage('Bookmark deleted');
@@ -1216,7 +1212,7 @@ make testing responses much simpler. Some examples are::
// Check a part of the Location header
$this->assertRedirectContains('/articles/edit/');
- // Added in 3.7.0
+ // Assert location header does not contain
$this->assertRedirectNotContains('/articles/edit/');
// Assert not empty response content
@@ -1248,7 +1244,7 @@ make testing responses much simpler. Some examples are::
$this->assertHeader('Content-Type', 'application/json');
$this->assertHeaderContains('Content-Type', 'html');
- // Added in 3.7.0
+ // Assert content-type header doesn't contain xml
$this->assertHeaderNotContains('Content-Type', 'xml');
// Assert view variables
diff --git a/en/installation.rst b/en/installation.rst
index 4c71c4c873..d13ef35524 100644
--- a/en/installation.rst
+++ b/en/installation.rst
@@ -78,7 +78,7 @@ Create a CakePHP Project
------------------------
You can create a new CakePHP application using composer's ``create-project``
-command::
+command:
.. code-block:: bash
@@ -106,12 +106,12 @@ Keeping Up To Date with the Latest CakePHP Changes
By default this is what your application **composer.json** looks like::
"require": {
- "cakephp/cakephp": "3.7.*"
+ "cakephp/cakephp": "4.0.*"
}
Each time you run ``php composer.phar update`` you will receive patch
-releases for this minor version. You can instead change this to ``^3.7`` to
-also receive the latest stable minor releases of the ``3.x`` branch.
+releases for this minor version. You can instead change this to ``^4.0`` to
+also receive the latest stable minor releases of the ``4.x`` branch.
If you want to stay up to date with the latest unreleased changes in CakePHP,
designate **dev-master** as the package version in your application's
@@ -121,9 +121,9 @@ designate **dev-master** as the package version in your application's
"cakephp/cakephp": "dev-master"
}
-Be aware that this is not recommended, as your application can break when the next major
-version is released. Additionally, composer does not cache development
-branches, so it slows down consecutive composer installs/updates.
+Be aware that this is not recommended, as your application can break when the
+next major version is released. Additionally, composer does not cache
+development branches, so it slows down consecutive composer installs/updates.
Installation using Oven
-----------------------
@@ -247,7 +247,9 @@ production setup will look like this on the file system::
config/
logs/
plugins/
+ resources/
src/
+ templates/
tests/
tmp/
vendor/
diff --git a/en/intro/cakephp-folder-structure.rst b/en/intro/cakephp-folder-structure.rst
index 27ce16ef9f..2cedfe4f70 100644
--- a/en/intro/cakephp-folder-structure.rst
+++ b/en/intro/cakephp-folder-structure.rst
@@ -13,9 +13,9 @@ level folders you should see:
configuration.
- The *src* folder will be where your application’s source files will be placed.
- The *templates* folder has presentational files placed here:
- elements, error pages, layouts, and view template files.
+ elements, error pages, layouts, and view template files.
- The *resources* folder has sub folder for various types of resource files.
- The *locales** sub folder stores string files for internationalization.
+ The *locales** sub folder stores string files for internationalization.
- The *tests* folder will be where you put the test cases for your application.
- The *tmp* folder is where CakePHP stores temporary data. The actual data it
stores depends on how you have CakePHP configured, but this folder
diff --git a/en/tutorials-and-examples/cms/installation.rst b/en/tutorials-and-examples/cms/installation.rst
index f1f28ae263..fb348882de 100644
--- a/en/tutorials-and-examples/cms/installation.rst
+++ b/en/tutorials-and-examples/cms/installation.rst
@@ -72,7 +72,9 @@ completed, your directory setup should look something like the following::
/config
/logs
/plugins
+ /resources
/src
+ /templates
/tests
/tmp
/vendor
diff --git a/en/tutorials-and-examples/cms/tags-and-users.rst b/en/tutorials-and-examples/cms/tags-and-users.rst
index 71282df5fc..d52db15ac9 100644
--- a/en/tutorials-and-examples/cms/tags-and-users.rst
+++ b/en/tutorials-and-examples/cms/tags-and-users.rst
@@ -376,9 +376,9 @@ replace the existing ``tags._ids`` control with the following::
echo $this->Form->control('tag_string', ['type' => 'text']);
We'll also need to update the article view template. In
-**src/Template/Articles/view.ctp** add the line as shown::
+**src/Template/Articles/view.php** add the line as shown::
-
+
= h($article->title) ?>
= h($article->body) ?>