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:: - +

title) ?>

body) ?>