From e7a4829ca8c8206a1cbc934ff107f1289a3bd0a8 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 26 Apr 2022 12:54:59 +0900 Subject: [PATCH] docs: add docs --- user_guide_src/source/changelogs/v4.2.0.rst | 24 ++- .../source/incoming/controllers.rst | 196 ++++++++++++++++-- .../source/incoming/controllers/014.php | 3 +- .../source/incoming/controllers/020.php | 11 + .../source/incoming/controllers/021.php | 16 ++ .../source/incoming/controllers/022.php | 11 + user_guide_src/source/incoming/routing.rst | 141 +++++++++++-- 7 files changed, 360 insertions(+), 42 deletions(-) create mode 100644 user_guide_src/source/incoming/controllers/020.php create mode 100644 user_guide_src/source/incoming/controllers/021.php create mode 100644 user_guide_src/source/incoming/controllers/022.php diff --git a/user_guide_src/source/changelogs/v4.2.0.rst b/user_guide_src/source/changelogs/v4.2.0.rst index 52cc16b86dc7..dd2044ff0ed2 100644 --- a/user_guide_src/source/changelogs/v4.2.0.rst +++ b/user_guide_src/source/changelogs/v4.2.0.rst @@ -19,11 +19,33 @@ BREAKING - The method signature of ``CodeIgniter\CLI\CommandRunner::_remap()`` has been changed to fix a bug. - The ``CodeIgniter\Autoloader\Autoloader::initialize()`` has changed the behavior to fix a bug. It used to use Composer classmap only when ``$modules->discoverInComposer`` is true. Now it always uses the Composer classmap if Composer is available. - The color code output by :ref:`CLI::color() ` has been changed to fix a bug. -- To prevent unexpected access from the web browser, if a controller is added to a cli route (``$routes->cli()``), all methods of that controller are no longer accessible via auto routing. +- To prevent unexpected access from the web browser, if a controller is added to a cli route (``$routes->cli()``), all methods of that controller are no longer accessible via auto-routing. Enhancements ************ +New Improved Auto Routing +========================= + +Added an optional new more secure auto router. These are the changes from the traditional auto-routing: + +- A controller method needs HTTP verb prefix like ``getIndex()``, ``postCreate()``. + - Developers always know HTTP method, so requests by unexpected HTTP method does not happen. +- The Default Controller (``Home`` by default) and the Default Method (``index`` by default) must be omitted in the URI. + - It restricts one-to-one correspondence between controller methods and URIs. + - E.g. by default, you can access ``/``, but ``/home`` and ``/home/index`` will be 404. +- It checks method parameter count. + - If there are more parameters in the URI than the method parameters, it results in 404. +- It does not support ``_remap()`` method. + - It restricts one-to-one correspondence between controller methods and URIs. +- Can't access controllers in Defined Routes. + - It completely separates controllers accessible via **Auto Routes** from those accessible via **Defined Routes**. + +See :ref:`auto-routing-improved` for the details. + +Others +====== + - Content Security Policy (CSP) enhancements - Added the configs ``$scriptNonceTag`` and ``$styleNonceTag`` in ``Config\ContentSecurityPolicy`` to customize the CSP placeholders (``{csp-script-nonce}`` and ``{csp-style-nonce}``) - Added the config ``$autoNonce`` in ``Config\ContentSecurityPolicy`` to disable the CSP placeholder replacement diff --git a/user_guide_src/source/incoming/controllers.rst b/user_guide_src/source/incoming/controllers.rst index 9074bf18046f..07926d61732e 100644 --- a/user_guide_src/source/incoming/controllers.rst +++ b/user_guide_src/source/incoming/controllers.rst @@ -109,20 +109,187 @@ then trying to access it using the following URL will not work:: example.com/index.php/helloworld/utility/ +.. _controller-auto-routing-improved: + +Auto Routing (Improved) +************************ + +Since v4.2.0, the new more secure Auto Routing has been introduced. + +This section describes the functionality of the new auto-routing. +It automatically routes an HTTP request, and executes the corresponding controller method +without route definitions. + +Since v4.2.0, the auto-routing is disabled by default. To use it, see :ref:`enabled-auto-routing-improved`. + +Consider this URI:: + + example.com/index.php/helloworld/ + +In the above example, CodeIgniter would attempt to find a controller named ``App\Controllers\Helloworld`` and load it, when auto-routing is enabled. + +.. note:: When a controller's short name matches the first segment of a URI, it will be loaded. + +Let's try it: Hello World! +========================== + +Let's create a simple controller so you can see it in action. Using your text editor, create a file called **Helloworld.php**, +and put the following code in it. You will notice that the ``Helloworld`` Controller is extending the ``BaseController``. you can +also extend the ``CodeIgniter\Controller`` if you do not need the functionality of the BaseController. + +The BaseController provides a convenient place for loading components and performing functions that are needed by all your +controllers. You can extend this class in any new controller. + +.. literalinclude:: controllers/020.php + +Then save the file to your **app/Controllers/** directory. + +.. important:: The file must be called **Helloworld.php**, with a capital ``H``. Controller class names MUST start with an uppercase letter and ONLY the first character can be uppercase. + +.. important:: A controller method that will be executed by Auto Routing (Improved) needs HTTP verb (``get``, ``post``, ``put``, etc.) prefix like ``getIndex()``, ``postCreate()``. + +Now visit your site using a URL similar to this:: + + example.com/index.php/helloworld + +If you did it right you should see:: + + Hello World! + +This is valid: + +.. literalinclude:: controllers/009.php + +This is **not** valid: + +.. literalinclude:: controllers/010.php + +This is **not** valid: + +.. literalinclude:: controllers/011.php + +Also, always make sure your controller extends the parent controller +class so that it can inherit all its methods. + +.. note:: + The system will attempt to match the URI against Controllers by matching each segment against + folders/files in **app/Controllers/**, when a match wasn't found against defined routes. + That's why your folders/files MUST start with a capital letter and the rest MUST be lowercase. + + Here is an example based on PSR-4 Autoloader: + + .. literalinclude:: controllers/012.php + + If you want another naming convention you need to manually define it using the + :ref:`Defined Route Routing `. + +Methods +======= + +In the above example, the method name is ``getIndex()``. +The method (HTTP verb + ``Index()``) is loaded if the **second segment** of the URI is empty. + +**The second segment of the URI determines which method in the +controller gets called.** + +Let's try it. Add a new method to your controller: + +.. literalinclude:: controllers/021.php + +Now load the following URL to see the ``getComment()`` method:: + + example.com/index.php/helloworld/comment/ + +You should see your new message. + +.. warning:: For security reasons be sure to declare any new utility methods as ``protected`` or ``private``. + +Passing URI Segments to Your Methods +==================================== + +If your URI contains more than two segments they will be passed to your +method as parameters. + +For example, let's say you have a URI like this:: + + example.com/index.php/products/shoes/sandals/123 + +Your method will be passed URI segments 3 and 4 (``'sandals'`` and ``'123'``): + +.. literalinclude:: controllers/022.php + +Defining a Default Controller +============================= + +CodeIgniter can be told to load a default controller when a URI is not +present, as will be the case when only your site root URL is requested. Let's try it +with the ``Helloworld`` controller. + +To specify a default controller open your **app/Config/Routes.php** +file and set this variable: + +.. literalinclude:: controllers/015.php + +Where ``Helloworld`` is the name of the controller class you want to be used. + +A few lines further down **Routes.php** in the "Route Definitions" section, comment out the line: + +.. literalinclude:: controllers/016.php + +If you now browse to your site without specifying any URI segments you'll +see the "Hello World" message. + +.. note:: The line ``$routes->get('/', 'Home::index');`` is an optimization that you will want to use in a "real-world" app. But for demonstration purposes we don't want to use that feature. ``$routes->get()`` is explained in :doc:`URI Routing ` + +For more information, please refer to the :ref:`routes-configuration-options` section of the +:doc:`URI Routing ` documentation. + +Organizing Your Controllers into Sub-directories +================================================ + +If you are building a large application you might want to hierarchically +organize or structure your controllers into sub-directories. CodeIgniter +permits you to do this. + +Simply create sub-directories under the main **app/Controllers/**, +and place your controller classes within them. + +.. important:: Folder names MUST start with an uppercase letter and ONLY the first character can be uppercase. + +When using this feature the first segment of your URI must +specify the folder. For example, let's say you have a controller located here:: + + app/Controllers/Products/Shoes.php + +To call the above controller your URI will look something like this:: + + example.com/index.php/products/shoes/show/123 + +.. note:: You cannot have directories with the same name in **app/Controllers/** and **public/**. + This is because if there is a directory, the web server will search for it and + it will not be routed to CodeIgniter. + +Each of your sub-directories may contain a default controller which will be +called if the URL contains *only* the sub-directory. Simply put a controller +in there that matches the name of your default controller as specified in +your **app/Config/Routes.php** file. + +CodeIgniter also permits you to map your URIs using its :ref:`Defined Route Routing `.. + .. _controller-auto-routing: -Auto Routing -************ +Auto Routing (Traditional) +************************** -This section describes the functionality of the auto-routing. +This section describes the functionality of Auto Routing (Traditional) that is a routing system from CodeIgniter 3. It automatically routes an HTTP request, and executes the corresponding controller method without route definitions. The auto-routing is disabled by default. .. warning:: To prevent misconfiguration and miscoding, we recommend that you do not use - the auto-routing feature. It is easy to create vulnerable apps where controller filters + Auto Routing (Traditional). It is easy to create vulnerable apps where controller filters or CSRF protection are bypassed. -.. important:: The auto-routing routes a HTTP request with **any** HTTP method to a controller method. +.. important:: Auto Routing (Traditional) routes a HTTP request with **any** HTTP method to a controller method. Consider this URI:: @@ -130,7 +297,7 @@ Consider this URI:: In the above example, CodeIgniter would attempt to find a controller named **Helloworld.php** and load it. -**When a controller's name matches the first segment of a URI, it will be loaded.** +.. note:: When a controller's short name matches the first segment of a URI, it will be loaded. Let's try it: Hello World! ========================== @@ -148,7 +315,7 @@ For security reasons be sure to declare any new utility methods as ``protected`` Then save the file to your **app/Controllers/** directory. -.. important:: The file must be called **Helloworld.php**, with a capital ``H``. +.. important:: The file must be called **Helloworld.php**, with a capital ``H``. Controller class names MUST start with an uppercase letter and ONLY the first character can be uppercase. Now visit your site using a URL similar to this:: @@ -158,8 +325,6 @@ If you did it right you should see:: Hello World! -.. important:: Controller class names MUST start with an uppercase letter and ONLY the first character can be uppercase. - This is valid: .. literalinclude:: controllers/009.php @@ -179,13 +344,14 @@ class so that it can inherit all its methods. The system will attempt to match the URI against Controllers by matching each segment against folders/files in **app/Controllers/**, when a match wasn't found against defined routes. That's why your folders/files MUST start with a capital letter and the rest MUST be lowercase. - If you want another naming convention you need to manually define it using the - :doc:`URI Routing ` feature. Here is an example based on PSR-4 Autoloader: .. literalinclude:: controllers/012.php + If you want another naming convention you need to manually define it using the + :ref:`Defined Route Routing `. + Methods ======= @@ -208,7 +374,7 @@ Now load the following URL to see the comment method:: You should see your new message. -Passing URI Segments to your methods +Passing URI Segments to Your Methods ==================================== If your URI contains more than two segments they will be passed to your @@ -222,10 +388,6 @@ Your method will be passed URI segments 3 and 4 (``'sandals'`` and ``'123'``): .. literalinclude:: controllers/014.php -.. important:: If you are using the :doc:`URI Routing ` - feature, the segments passed to your method will be the defined - ones. - Defining a Default Controller ============================= @@ -282,7 +444,7 @@ called if the URL contains *only* the sub-directory. Simply put a controller in there that matches the name of your default controller as specified in your **app/Config/Routes.php** file. -CodeIgniter also permits you to map your URIs using its :doc:`URI Routing ` feature. +CodeIgniter also permits you to map your URIs using its :ref:`Defined Route Routing `.. Remapping Method Calls ********************** diff --git a/user_guide_src/source/incoming/controllers/014.php b/user_guide_src/source/incoming/controllers/014.php index da295eb61836..18c076f5bc25 100644 --- a/user_guide_src/source/incoming/controllers/014.php +++ b/user_guide_src/source/incoming/controllers/014.php @@ -6,7 +6,6 @@ class Products extends BaseController { public function shoes($sandals, $id) { - return $sandals - . $id; + return $sandals . $id; } } diff --git a/user_guide_src/source/incoming/controllers/020.php b/user_guide_src/source/incoming/controllers/020.php new file mode 100644 index 000000000000..ff485a0327a5 --- /dev/null +++ b/user_guide_src/source/incoming/controllers/020.php @@ -0,0 +1,11 @@ +setAutoRoute(true); +And you need to change the property ``$autoRoutesImproved`` to ``true`` in **app/Config/Feature.php**:: + + public bool $autoRoutesImproved = true; + URI Segments ============ @@ -547,15 +560,15 @@ The segments in the URL, in following with the Model-View-Controller approach, u Consider this URI:: - example.com/index.php/helloworld/index/1 + example.com/index.php/helloworld/hello/1 -In the above example, CodeIgniter would attempt to find a controller named **Helloworld.php** -and executes ``index()`` method with passing ``'1'`` as the first argument. +In the above example, when you send a HTTP request with **GET** method, +Auto Routing would attempt to find a controller named ``App\Controllers\Helloworld`` +and executes ``getHello()`` method with passing ``'1'`` as the first argument. -We call this "**Auto Routes**". CodeIgniter automatically routes an HTTP request, -and executes the corresponding controller method. The auto-routing is disabled by default. +.. note:: A controller method that will be executed by Auto Routing (Improved) needs HTTP verb (``get``, ``post``, ``put``, etc.) prefix like ``getIndex()``, ``postCreate()``. -See :ref:`Auto Routing in Controllers ` for more info. +See :ref:`Auto Routing in Controllers ` for more info. Configuration Options ===================== @@ -565,7 +578,7 @@ These options are available at the top of **app/Config/Routes.php**. Default Controller ------------------ -When a user visits the root of your site (i.e., example.com) the controller to use is determined by the value set by +When a user visits the root of your site (i.e., **example.com**) the controller to use is determined by the value set by the ``setDefaultController()`` method, unless a route exists for it explicitly. The default value for this is ``Home`` which matches the controller at **app/Controllers/Home.php**: @@ -575,7 +588,10 @@ The default controller is also used when no matching route has been found, and t in the controllers directory. For example, if the user visits **example.com/admin**, if a controller was found at **app/Controllers/Admin/Home.php**, it would be used. -See :ref:`Auto Routing in Controllers ` for more info. +.. note:: You cannot access the default controller with the URI of the controller name. + When the default controller is ``Home``, you can access **example.com/**, but if you access **example.com/home**, it will be not found. + +See :ref:`Auto Routing in Controllers ` for more info. Default Method -------------- @@ -589,6 +605,87 @@ In this example, if the user were to visit **example.com/products**, and a ``Pro .. literalinclude:: routing/048.php +.. note:: You cannot access the controller with the URI of the default method name. + In the example above, you can access **example.com/products**, but if you access **example.com/products/listall**, it will be not found. + +.. _auto-routing: + +Auto Routing (Traditional) +************************** + +Auto Routing (Traditional) is a routing system from CodeIgniter 3. +It can automatically route HTTP requests based on conventions and execute the corresponding controller methods. + +It is recommended that all routes are defined in the **app/Config/Routes.php** file, +or to use :ref:`auto-routing-improved`, + +.. warning:: To prevent misconfiguration and miscoding, we recommend that you do not use + Auto Routing (Traditional) feature. It is easy to create vulnerable apps where controller filters + or CSRF protection are bypassed. + +.. important:: Auto Routing (Traditional) routes a HTTP request with **any** HTTP method to a controller method. + +Enable Auto Routing (Traditional) +================================= + +Since v4.2.0, the auto-routing is disabled by default. + +To use it, you need to change the setting ``setAutoRoute()`` option to true in **app/Config/Routes.php**:: + + $routes->setAutoRoute(true); + +URI Segments (Traditional) +========================== + +The segments in the URL, in following with the Model-View-Controller approach, usually represent:: + + example.com/class/method/ID + +1. The first segment represents the controller **class** that should be invoked. +2. The second segment represents the class **method** that should be called. +3. The third, and any additional segments, represent the ID and any variables that will be passed to the controller. + +Consider this URI:: + + example.com/index.php/helloworld/index/1 + +In the above example, CodeIgniter would attempt to find a controller named **Helloworld.php** +and executes ``index()`` method with passing ``'1'`` as the first argument. + +See :ref:`Auto Routing (Traditional) in Controllers ` for more info. + +Configuration Options (Traditional) +=================================== + +These options are available at the top of **app/Config/Routes.php**. + +Default Controller (Traditional) +-------------------------------- + +When a user visits the root of your site (i.e., example.com) the controller to use is determined by the value set by +the ``setDefaultController()`` method, unless a route exists for it explicitly. The default value for this is ``Home`` +which matches the controller at **app/Controllers/Home.php**: + +.. literalinclude:: routing/047.php + +The default controller is also used when no matching route has been found, and the URI would point to a directory +in the controllers directory. For example, if the user visits **example.com/admin**, if a controller was found at +**app/Controllers/Admin/Home.php**, it would be used. + +See :ref:`Auto Routing in Controllers ` for more info. + +Default Method (Traditional) +---------------------------- + +This works similar to the default controller setting, but is used to determine the default method that is used +when a controller is found that matches the URI, but no segment exists for the method. The default value is +``index``. + +In this example, if the user were to visit **example.com/products**, and a ``Products`` controller existed, the +``Products::listAll()`` method would be executed: + +.. literalinclude:: routing/048.php + Confirming Routes ***************** @@ -617,11 +714,11 @@ The output is like the following: | auto | home/index[/...] | \App\Controllers\Home::index | invalidchars | secureheaders toolbar | +--------+------------------+------------------------------------------+----------------+-----------------------+ -The *Method* column shows the HTTP method that the route is listening for. ``auto`` means that the route is discovered by auto routing, so it is not defined in **app/Config/Routes.php**. +The *Method* column shows the HTTP method that the route is listening for. ``auto`` means that the route is discovered by auto-routing, so it is not defined in **app/Config/Routes.php**. The *Route* column shows the URI path to match. The route of a defined route is expressed as a regular expression. But ``[/...]`` in the route of an auto route is indicates any number of segments. -.. note:: When auto routing is enabled, if you have the route ``home``, it can be also accessd by ``Home``, or maybe by ``hOme``, ``hoMe``, ``HOME``, etc. But the command shows only ``home``. +.. note:: When auto-routing is enabled, if you have the route ``home``, it can be also accessd by ``Home``, or maybe by ``hOme``, ``hoMe``, ``HOME``, etc. But the command shows only ``home``. .. important:: The system is not perfect. If you use Custom Placeholders, *Filters* might not be correct. But the filters defined in **app/Config/Routes.php** are always displayed correctly.