@@ -6,9 +6,10 @@ methods, to prepare the response. We'll place this new controller in a file
66called ** ArticlesController.php** inside the ** src/Controller** directory.
77Here's what the basic controller should look like:
88
9- ``` php
9+ ``` php {3}
1010<?php
1111// src/Controller/ArticlesController.php
12+ declare(strict_types=1);
1213
1314namespace App\Controller;
1415
@@ -25,15 +26,16 @@ have routes connected to them. For example, when a user requests
2526a response by rendering a Template in the View. The code for that action would
2627look like this:
2728
28- ``` php
29+ ``` php {3,9}
2930<?php
3031// src/Controller/ArticlesController.php
32+ declare(strict_types=1);
3133
3234namespace App\Controller;
3335
3436class ArticlesController extends AppController
3537{
36- public function index()
38+ public function index(): void
3739 {
3840 $articles = $this->paginate($this->Articles);
3941 $this->set(compact('articles'));
@@ -126,10 +128,10 @@ correctly formatted with the title and table listing of the articles.
126128If you were to click one of the 'view' links in our Articles list page, you'd
127129see an error page saying that action hasn't been implemented. Lets fix that now:
128130
129- ``` php
131+ ``` php {3}
130132// Add to existing src/Controller/ArticlesController.php file
131133
132- public function view($slug = null)
134+ public function view(?string $slug): void
133135{
134136 $article = $this->Articles->findBySlug($slug)->firstOrFail();
135137 $this->set(compact('article'));
@@ -153,7 +155,7 @@ page telling us we're missing a view template; let's fix that.
153155Let's create the view for our new 'view' action and place it in
154156** templates/Articles/view.php**
155157
156- ``` php
158+ ``` php {3-4}
157159<!-- File: templates/Articles/view.php -->
158160
159161<h1 ><?= h($article->title) ?></h1 >
@@ -162,6 +164,10 @@ Let's create the view for our new 'view' action and place it in
162164<p ><?= $this->Html->link('Edit', ['action' => 'edit', $article->slug]) ?></p >
163165```
164166
167+ ::: tip Security: XSS Protection
168+ The ` h() ` helper function escapes output to prevent XSS (Cross-Site Scripting) attacks. Always use it when outputting user-generated content.
169+ :::
170+
165171You can verify that this is working by trying the links at ` /articles/index ` or
166172manually requesting an article by accessing URLs like
167173` /articles/view/first-post ` .
@@ -172,28 +178,30 @@ With the basic read views created, we need to make it possible for new articles
172178to be created. Start by creating an ` add() ` action in the
173179` ArticlesController ` . Our controller should now look like:
174180
175- ``` php
181+ ``` php {3,11,17,23}
176182<?php
177183// src/Controller/ArticlesController.php
184+ declare(strict_types=1);
185+
178186namespace App\Controller;
179187
180188use App\Controller\AppController;
181189
182190class ArticlesController extends AppController
183191{
184- public function index()
192+ public function index(): void
185193 {
186194 $articles = $this->paginate($this->Articles);
187195 $this->set(compact('articles'));
188196 }
189197
190- public function view($slug)
198+ public function view(?string $slug): void
191199 {
192200 $article = $this->Articles->findBySlug($slug)->firstOrFail();
193201 $this->set(compact('article'));
194202 }
195203
196- public function add()
204+ public function add(): void
197205 {
198206 $article = $this->Articles->newEmptyEntity();
199207 if ($this->request->is('post')) {
@@ -215,10 +223,11 @@ class ArticlesController extends AppController
215223}
216224```
217225
218- > [ !NOTE]
219- > You need to include the [ Flash] ( ../../controllers/components/flash ) component in
220- > any controller where you will use it. Often it makes sense to include it in
221- > your ` AppController ` , which is there already for this tutorial.
226+ ::: info Flash Component
227+ You need to include the [ Flash] ( ../../controllers/components/flash ) component in
228+ any controller where you will use it. Often it makes sense to include it in
229+ your ` AppController ` , which is there already for this tutorial.
230+ :::
222231
223232Here's what the ` add() ` action does:
224233
@@ -304,15 +313,15 @@ creating a slug attribute, and the column is `NOT NULL`. Slug values are
304313typically a URL-safe version of an article's title. We can use the
305314[ beforeSave() callback] ( ../../orm/table-objects#table-callbacks ) of the ORM to populate our slug:
306315
307- ``` php
316+ ``` php {3,7-9,13}
308317<?php
309318// in src/Model/Table/ArticlesTable.php
319+ declare(strict_types=1);
320+
310321namespace App\Model\Table;
311322
312323use Cake\ORM\Table;
313- // the Text class
314324use Cake\Utility\Text;
315- // the EventInterface class
316325use Cake\Event\EventInterface;
317326
318327// Add the following method.
@@ -335,12 +344,10 @@ fix that later on.
335344Our application can now save articles, but we can't edit them. Lets rectify that
336345now. Add the following action to your ` ArticlesController ` :
337346
338- ``` php
347+ ``` php {3}
339348// in src/Controller/ArticlesController.php
340349
341- // Add the following method.
342-
343- public function edit($slug)
350+ public function edit(?string $slug): void
344351{
345352 $article = $this->Articles
346353 ->findBySlug($slug)
@@ -430,11 +437,11 @@ articles:
430437Up until this point our Articles had no input validation done. Lets fix that by
431438using [ a validator] ( ../../orm/validation#validating-request-data ) :
432439
433- ``` php
440+ ``` php {5,8}
434441// src/Model/Table/ArticlesTable.php
435442
436- // add this use statement right below the namespace declaration to import
437- // the Validator class
443+ // add this use statement right below the namespace declaration
444+ // to import the Validator class
438445use Cake\Validation\Validator;
439446
440447// Add the following method.
@@ -472,12 +479,10 @@ automatically.
472479Next, let's make a way for users to delete articles. Start with a
473480` delete() ` action in the ` ArticlesController ` :
474481
475- ``` php
482+ ``` php {3}
476483// src/Controller/ArticlesController.php
477484
478- // Add the following method.
479-
480- public function delete($slug)
485+ public function delete(?string $slug): void
481486{
482487 $this->request->allowMethod(['post', 'delete']);
483488
@@ -499,10 +504,11 @@ error page is displayed. There are many built-in
499504[ Exceptions] ( ../../development/errors ) that can be used to indicate the various
500505HTTP errors your application might need to generate.
501506
502- > [ !WARNING]
503- > Allowing content to be deleted using GET requests is * very* dangerous, as web
504- > crawlers could accidentally delete all your content. That is why we used
505- > ` allowMethod() ` in our controller.
507+ ::: danger Security Warning
508+ Allowing content to be deleted using GET requests is * very* dangerous, as web
509+ crawlers could accidentally delete all your content. That is why we used
510+ ` allowMethod() ` in our controller.
511+ :::
506512
507513Because we're only executing logic and redirecting to another action, this
508514action has no template. You might want to update your index template with links
@@ -548,19 +554,21 @@ Using `Cake\View\Helper\FormHelper::deleteLink()` will create a link
548554that uses JavaScript to do a DELETE request deleting our article.
549555Prior to CakePHP 5.2 you need to use ` postLink() ` instead.
550556
551- > [ !NOTE]
552- > This view code also uses the ` FormHelper ` to prompt the user with a
553- > JavaScript confirmation dialog before they attempt to delete an
554- > article.
555-
556- > [ !TIP]
557- > The ` ArticlesController ` can also be built with ` bake ` :
558- >
559- > ``` bash
560- > /bin/cake bake controller articles
561- > ` ` `
562- >
563- > However, this does not build the ** templates/Articles/\* .php** files.
557+ ::: info FormHelper Confirmation
558+ This view code also uses the ` FormHelper ` to prompt the user with a
559+ JavaScript confirmation dialog before they attempt to delete an
560+ article.
561+ :::
562+
563+ ::: tip Use Bake to Generate Controllers
564+ The ` ArticlesController ` can also be built with ` bake ` :
565+
566+ ``` bash
567+ bin/cake bake controller articles
568+ ```
569+
570+ However, this does not build the ** templates/Articles/\* .php** files.
571+ :::
564572
565573With a basic articles management setup, we'll create the [ basic actions
566574for our Tags and Users tables] ( ../../tutorials-and-examples/cms/tags-and-users ) .
0 commit comments