Lesson 5

データを扱う基本的な画面の追加

Lesson 5 Chapter 1
このLessonですること

前回のLesson4でプロジェクトの作成と、DBとの接続が完了し、CakePHPでの開発準備が整いましたので、このLessonからTodoアプリケーションを作成しながらハンズオン形式でCakePHPについて学んで行きましょう。

アプリケーションの概要としては、ユーザーが自分の「タスク」を一つ一つ登録していき、必要に応じてタスク内容の編集と削除が出来るようにします。

必要な画面は「一覧画面」「詳細画面」「編集画面」の3つです。一覧画面では全てのタスクの確認と、詳細画面・編集画面へのリンク、そしてタスクの削除を実行するリンクを置きます。

詳細画面では指定したタスク内容の表示、編集画面ではタスク内容の編集を行えるようにします。

また、タスクデータの管理はデータベースにテーブルを作成して行います。

上記の内容でアプリケーションの基本となるCRUD(生成、読み取り、更新、削除)が出来るようにしていきます。

それでは初めていきましょう。

Lesson 5 Chapter 2
モデルの作成

テーブルとエンティティ

まずはモデルから作り始めていきます

Lesson2でも触れましたが、モデルはデータベースのテーブルにアクセスするテーブルクラスと、テーブル内のデータであるレコード一つ一つをオブジェクトとして操作するためのエンティティクラスに分けられます。

実際にModelフォルダの中を見てみましょう。

5_2_1

テーブルとエンティティそれぞれのフォルダがあることが分かります。

テーブルの作成

テーブルのクラスを記述するphpファイルは TasksTable.phpとして src/Model/Tableの配下に作成します。(todo4の配下としてパスを表記しています。以降も同様に表記します。)classの中身は以下のように空で構いません。

TasksTable.php
<?php
namespace App\Model\Table;
use Cake\ORM\Table;

class TasksTable extends Table
{

}

1行名のnamespaceはアプリケーション内でのクラスやメソッドの名前の重複によるエラーを防ぐ役割を持っています、例えばPCのフォルダ(windowsならエクスプローラー)でも、全く同じ名前の2つのファイルを同じフォルダ内には存在させることができませんが、同じ名前でも片方が別のフォルダにある場合は問題ありません。

同じようにnamecpaceによってアプリケーション内を区分けしておくことで、異なる区分であれば同じ名前のクラスやメソッドも作成することが可能となります。

ひとつ決まりとして、CakePHPではsrcフォルダの配下に置かれるものは「App/」としてnamespaceを設定していきます。
また、2行目で使われているuse文は異なるnamespaceからクラスやメソッドを呼び出す仕組みのため、namespaceの宣言無しでは正しく動作しません。

use文では、cake/ORM/Tableを呼び出しています。これはcake/ORM/Table クラスに記述されている CakePHPのテーブル関連の機能を、TasksTableクラスに extend を使用して継承させるための記述となります。

エンティティの作成

エンティティも同様に作成していきましょう。src/Model/Entity/Task.phpとして作成します。

ファイル名はTask.phpとなり、Tasksの単数形を使用します。エンティティはテーブル内にある複数のレコードを1行ごとにオブジェクトとして表すため、複数ではなく単数形になると考えると覚えやすいかと思います。TasksEntity.php とはならないので注意しましょう。

Task.php

<?php
namespace App\Model\Entity;
use Cake\ORM\Entity;

class Task extends Entity
{

}

以上でテーブルとエンティティの作成は完了です。

Lesson 5 Chapter 3
一覧表示画面の作成

コントローラ

作成したモデルを元に「一覧表示画面」を表示出来るようにします。まずはコントローラから作成していきます。

src/Controller配下にTasksController.phpを作成しましょう。命名規約は大文字始まりのテーブル名+Controllerとなります。ほかにAppController.phpなどが最初から入っていますが、CakePHPが必要とするファイルなので削除などしないようにしましょう。

5_3_1

一覧表示画面のアクション

コントローラの中身については、以下のようにします。タスク一覧画面のために、indexアクションを作成しています。内容はモデルからデータを持ってきて、ビューにデータを渡すものとなっています。

TasksController.php
<?php
namespace App\Controller;
use App\Controller\AppController;

class TasksController extends AppController
{
  public function index()
  {
        $tasks = $this->Tasks->find('all');
        $this->set('tasks',$tasks);
  }
}

indexアクション内の $tasks = $this->Tasks->find('all'); はTasksテーブルのデータ全てをオブジェクトの形で取りだして、$tasksに格納しています。「オブジェクトの形で取り出して」という部分については、find()メソッドの詳細について扱うLesson6で改めて解説していきます。

また、$this->TasksのみでTasksテーブルクラスを呼び出せるのは命名規約で、モデルと紐づいているためとなります。

その後の$this->set('tasks',$tasks);ではset()メソッドを使用しており、次に説明をするビューテンプレート内で「tasks」というプロパティ名で$tasksの値をあつかえるようにしています。

一覧表示画面のテンプレート

モデル、コントローラと用意出来たので、最後にビューとなります。ビューのテンプレートには「レイアウト」と「ビューテンプレート」があり、ページの大枠となる「レイアウト」はヘッダーやフッダーなどページ間で共通して使用する部分を主に担当し、「ビューテンプレート」がページごとの内容を担当します。

そのため、「レイアウト」に「ビューテンプレート」を当て込む形で画面を作成していくのですが、「レイアウト」はCakePHPにもともと用意されているものを使用するため、「ビューテンプレート」のみの作成を行っていきます。

5_3_2

ビューテンプレートはtemplatesの配下にコントローラのクラス名に従ってフォルダを作り、さらにその配下にアクション名に従ったファイルを作成します。

今回だと、Tasksフォルダとindex.phpを作成することになります。

5_3_3

処理内容としては、コントローラーから受け取ったテーブルのデータを一覧表示させるものを作ります。

具体的には各データの項目名(フィールド名)の表示と、コントローラから受け取ったデータの表示を行います。

index.php
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="utf-8">
</head>

<h1>タスク一覧</h1>
<table>
  <tr>
    <th>id</th>
    <th>内容</th>
    <th>ステータス</th>
    <th>作成時間</th>
  </tr>

  <?php foreach ($tasks as $task): ?>
  <tr>
    <td>
      <?= h($task->id) ?>
    </td>
    <td>
      <?= h($task->content) ?>
    </td>
    <td>
      <?= h($task->created) ?>
    </td>
  </tr>
  <?php endforeach; ?>
</table>
                    

HTMLの設定と、タイトル、フィールド名の記述をした後に、foreachでコントローラから受け取ったtasksテーブルのデータを$taskとしてレコード 1行ごとに取り出し、フィールド名に合わせてデータをセットしています。

また h()メソッドが使われていますが、これは表示する文字列データにHTMLや特殊文字が含まれていた場合、それらをエスケープして表示するもので、ユーザーからの入力にプログラムを操作するような悪意ある記述が含まれる場合などを想定し、セキュリティ面を考慮して使用します。

動作確認

モデル・コントローラ・ビューの用意ができたので、http://localhost:8765/tasks をブラウザで開き、内容を確認してみましょう。コマンドライン上でCakePHPの内臓サーバーとMySQLを立ち上げておくことを忘れないようにしてください。

5_3_4

このように表示されれば成功です。

Lesson 5 Chapter 4
詳細表示画面の作成

詳細表示画面のアクション

次に各タスクの内容を表示する詳細画面を作成し、タスク一覧画面からリンクで飛べるようにしていきます。

まずはコントローラの編集を行うので、src/Controller/TasksController.phpを開きます。

indexアクションの下に、詳細画面用としてdetailアクションを追加します。処理内容は指定のidに紐づくデータを取得し、ビューテンプレートへと渡すようにしています。

TasksController.php

<?php

namespace App\Controller;
use App\Controller\AppController;

class TasksController extends AppController
{
  public function index()
  {
    $tasks = $this->Tasks->find('all');
    $this->set('tasks',$tasks);
  }

  public function detail()
  {
    $id = $this->request->getQuery('id');
    $task = $this->Tasks->get($id);
    $this->set('task',$task);
  }
}
                    

今回はタスク一覧画面からidの値をURLパラメータとして送るようにします。URLパラメータとはURLに含まれる変数のことで、URL上ではクエリ文字列というもので表されます。以下の例を見てみてください。

http://localhost:8765/tasks/detail?id=1

tasksコントローラのdetailアクションに「?id=1」という「キー=値」の形で変数データを送っています。複数の変数が必要な場合には ?id=1&type=2 などのように「&」を使用することが可能です。

コントローラでURLパラメーターを取得するにはgetQuery()メソッドを使う必要があり、パラメーターのキーを渡すことで、その値を取得することができます。今回はgetQuery()にキーである'id'を渡し、値である1を取得し$idへと代入しています。

$task = $this->Tasks->get($id); の部分では getQuery()メソッドで取得した値をget()メソッドに渡しており、tasksテーブルから、id フィールドの値が1のデータを取得しています。仮に対応するデータなかった場合にはエラーとなります。

最後は変数$taskを詳細画面のビューテンプレートへとset()メソッドで渡して終了です。

詳細表示画面のテンプレート

テンプレートはtemplates配下にコントローラのクラス名に従ったフォルダがあり、その配下にメソッド名のファイルを持つのでした。

そのため、今回はtemplates/Tasksの配下にdetail.phpを作成します。

5_4_1

中身はindex.phpとほぼ変わらずです。複数ではなく単体のエンティティデータの表示なので、foreachを外して編集時間のみ追加しました。

detail.php
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="utf-8">
</head>

<h1>タスク詳細</h1>
<table>
  <tr>
    <th>id</th>
    <th>内容</th>
    <th>作成時間</th>
    <th>編集時間</th>
  </tr>

  <tr>
    <td>
      <?= h($task->id) ?>
    </td>
    <td>
      <?= h($task->content) ?>
    </td>
    <td>
      <?= h($task->created) ?>
    </td>
    <td>
      <?= h($task->modified) ?>
    </td>
  </tr>
</table>
                    

これで編集画面のビューテンプレートは完了です。

リンクの作成

つぎにtemplates/Tasks/index.phpを編集し、Lesson2で簡単に触れたHTMLヘルパーが持つlink()メソッドというものを使ってタスク一覧画面から詳細画面へと遷移できるようにします。

index.php

  <?php foreach ($tasks as $task): ?>
  <tr>
    <td>
      <?= $this->Html->link($task->id , "tasks/detail?id=".$task->id) ?>
    </td>
    <td>
      <?= h($task->content) ?>
    </td>
    <td>
      <?= h($task->created) ?>
    </td>
  </tr>
  <?php endforeach; ?>
                    

HTMLヘルパーが持つlink()メソッドは以下の形をとります。

$this->Html->link(テキスト,リンク先)

出力としては以下と同様のものが出来上がります。

<a href = "リンク先">テキスト</a>

今回はtasks/detaiへURLパラメーターとして変数idを渡す形にするため、リンク先の指定でコントローラから受け取った変数 $task を使用しています。

動作確認

一通り作成出来たので、ブラウザでの動作確認を行いましょう。一覧表示画面を開き、各タスクのid 部分をクリックすると詳細画面へと遷移し、クリックしたidに紐づく内容が表示されます。

5_4_2

URLのid=1の部分をid=2に直打ちで変更することで、id2の内容が表示されることも合わせて確認しておきましょう。

Lesson 5 Chapter 5
新規作成画面の作成

新規作成画面のアクション

つぎに新しいタスクを追加できるよう、新規作成の機能を追加していきます。

タスクを新規で作成するため、tasksテーブルに新しいレコードを作成し、保存する必要があります。1行毎のレコードに対応しているのは「エンティティ」のため、今回は新規のエンティティを作成し、保存をする必要があるということになります。

コントローラが行う処理の流れとしては、HTMLのフォームに入力された値がブラウザからリクエストとして送信され、その内容をコントローラが受取り、新規作成した空のエンティティへと入れて、保存を実行する。といったものになります。

ではまず、TasksController.phpを開き、detailメソッドの下にaddメソッドを追加しましょう。

TasksController.php
  public function add()
  {
    $task = $this->Tasks->newEmptyEntity();
    if ($this->request->is('post')) {
      $this->Tasks->patchEntity($task, $this->request->getData());
      if ($this->Tasks->save($task)) {
          $this->Flash->success('タスクが登録されました');
          return $this->redirect(['action' => 'index']);
      }
      $this->Flash->error('新規作成に失敗しました');
    }
    $this->set('task', $task);
  }

$task = $this->Tasks->newEmptyEntity(); で新規のエンティティを作成しているのですが、エンティティの新規作成にはテーブルクラスの持つ newEntity()メソッドか、newEnptyEntity()メソッドを使用します。

newEntity()は引数に新規エンティティへと代入するデータを取ると、その場でバリデーション(入力データのチェック)を行います。対して、newEmptyEntity() は空のエンティティを作成するのみでバリデーションは実行されず、後のタイミングで空のエンティティへデータを入れる際にバリデーションを行うという違いがあります。

最初のif文では、条件部分でpostでのリクエストであることを確認し、その後 getData()で取り出したリクエストのデータを patchEntity()というメソッドで空の新規エンティティである$taskへと入れています。

patchEntity()は第一引数に指定したエンティティに向けて、第二引数で指定した配列データの当て込み(パッチ)をしてくれます。今回は$this->request->getData()で取得したリクエストのデータを空のtasksテーブルのエンティティが入っている$task変数にパッチしています。getData()メソッドはリクエストに含まれるフォーム入力で送られてきたデータを取得する際によく使われるので覚えておきましょう。

また、patchEntity()メソッドはエンティティにデータを入れるタイミングのため、バリデーションが実行される起点にもなっています。どのようなバリデーションを行うかについては本チャプターの最後で設定を行います。

次に2つめのif文の条件では、作成したエンティティを保存するためのsave()メソッドを使用しています。save()メソッドが成功した場合にはFlashコンポーネントのsuccessメソッドによる成功の表示と、コントローラクラスに標準で備わっているredirect()メソッドでの一覧画面へのリダイレクトを行っています。

save()メソッドはテーブルクラスが持つメソッドで、引数に取ったエンティティオブジェクトに含まれるデータを保存し、データベース上に反映します。仮にエンティティにデータが入っていない場合には使用することは出来ません。

また、保存に成功した場合は引数に取ったエンティティのオブジェクトを返し、失敗した場合には'false'が返されます、falseの場合には今回フラッシュでエラーの表示が出るようになっています。

その後、set()メソッドで変数$taskをビューテンプレートへ渡せるようにしています。

新規作成画面のテンプレート

コントローラで、フォームを受け取って処理するためのadd()アクションができたので、ビューテンプレートと新規タスクの内容を入力するためのフォームを作成していきましょう。フォームの作成にはCakePHPのフォームヘルパーを使用していきます。

templates/Tasks配下にadd.phpを作成し、以下の内容を記述します。

add.php
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="utf-8">
</head>

<h1>新規作成画面</h1>
<?php
   echo $this->Form->create($task);
   echo $this->Form->control('content');
   echo $this->Form->button('保存');
   echo $this->Form->end();
?>

フォームヘルパーを使ってフォームを作成する際にはForm->create()メソッドで始めます。第一引数にコントローラから渡されたエンティティのデータを取ることで、エンティティーの持つフィールドなどを認識します。エンティティ用のフォールではない場合にはnullとして作成することも出来ます。

第二引数にはフォームの種類(post、getなど)や送信先のURLが指定できます。指定しない場合にはpostで現在のページに向けて送信します。今回は第一引数のみを指定しているので、現在のページであるtasks/addへのPOST送信となります。

次に入力フォームを作成するためにForm->control()メソッドを使用しています。引数にcreate()メソッドに渡したエンティティが持つフィールド名を入力することで、自動的にフォームのタイプを決定して入力フォームを生成します。今回の'content'はMySQLでのテーブル作成時にtext型のフィールドとして作成しているため、textareaフォームが作成されます。

5_5_1

ほかにも、boolean型であればチェックボックスが自動で作成されるなど、型によって必要なフォームのタイプを呼び出します。

Form->button()では第一引数に表示するテキストを取り、第二引数にボタンのタイプ(sumit,buttonなど)を取ります。デフォルトではsubmitになるため、今回は第一引数のみを入れています。

最後にend()にてフォームを閉じるタグを生成しています。FormヘルパーについてはLesson10でより詳しく説明をしていきます。

リンクの作成

新規作成を行うための準備ができたので、tamplates/Tasks/index.phpを編集し、タスク一覧画面に新規作成ページへのリンクを設置します。一覧表示をしているリストの上にHTMLヘルパーのlinkメソッドを使って設置します。

index.php
  <tr>
  <th>id</th>
  <th>内容</th>
  <th>作成時間</th>
</tr>

<?= $this->html->link('新規作成',['action'=>'add'])?>

5_5_2

上記のようにリンクの作成が確認できたら、リンクから問題なく新規作成ページに飛べるか確認し、ブラウザの「検証」機能などでフォームヘルパーが実際にどのようなフォームタグを生成しているのかも合わせて確認しておきましょう。

CSRF対応について

新規作成画面のフォームタグがどのようになっているかを見てみると「_csrfToken」というものが付与されていることが分かるかと思います。

5_5_3

これは、WEBアプリケーションを作成するときにセキュリティ上で注意すべきものとして挙げられる CSRF(クロスサイトフォージェリ)への対応となります。

CSRFとは特定のサイトにログイン中に、メールなどで送られてきた悪意のあるURLなどを踏むことで、ログイン中のサイトで意図しない操作が勝手に行われてしまうといったものになります。

対策方法として、postでのフォーム送信を行う画面に入ったときに暗号となるトークンをフォーム内に付与すると同時に、セッションにもトークンを保存、その後に入力フォームの送信を行うとき、フォームに付与したトークンとセッションに保存されているトークンが一致するか照合するといった方法があります。

CakePHPではこのCSRF対策として、フォームヘルパーを使うことで自動的に暗号が付与されるようになっています。

CakePHPのCSRF対策についての設定はsrc\Application.phpにて行います。public function middlewareメソッド内にて、CsrfProtectionMiddlewareのインスタンスが生成されており、'httponly' => true の表示があれば有効となっています。

5_5_4

ミドルウェアについて詳しくはLesson11で解説していきます。

Flashコンポーネントについて

フラッシュはフォームの処理後やデータの確認などのために、一回限りの表示を行う機能を言います。仕組みとしては、Flashコンポーネントによってコントローラからセッションデータを格納する$__SESSIONにフラッシュ用の変数を書き込み、FlashHelperというヘルパーを通してビューで表示しています。

$this->Flash->success('タスクが登録されました');

今回addメソッド内で使用したこの形では、src/templates/element\flash配下に置いてある各種エレメントを呼び出してフラッシュを表示しています。element\flashの配下にsuccess.phpやerror.phpというファイルがあることが確認できるかと思います。

また、以下のようにsetを使用してエレメントを通さずに平易な文を表示することもできます。

$this->Flash->set('This is a message');

5_5_5 上がエレメントのsuccess.php、下がsetを使用

動作確認

ここまでで、新規作成機能の大部分が出来上がりました。実際に新規データを追加して動作を確認しましょう。

一覧画面から新規作成のリンクをクリックし、新規作成画面へと移動します。テキストエリアに適当な文字列を入力し、保存ボタンを押しましょう。

一覧画面へと戻り、successを使ったフラッシュの表示と、追加したデータの確認が出来ます。

5_5_6

バリデーション

入力フォームを作成した後には、バリデーションを施していきましょう。

CakePHPのバリデーションはModelのTableクラス内に記述していきます。src/Model/Table/TasksTable.phpを開き、クラス内にvalidationDefaultメソッドを記述します。

TasksTable.php
class TasksTable extends Table
{
  public function validationDefault(Validator $validator): Validator
  {
      $validator
          ->notEmptyString('content')
          ->minLength('content', 3)
          ->maxLength('content', 40);
  
      return $validator;
  }
}

validationDefaultメソッドでは、引数に取っている$validatorオブジェクトがもつバリデーション用のメソッドを呼び出すように記述をしていきます。

最初にcontentを対象にnotEmptyString()を使用しており、空でないかをチェックします。ただ、HTML5がすでにtextareaを空のまま送信しようとするとエラーを出す仕組みを持っているため、先にHTML5のエラーメッセージが出ることになります。

今回はバリデーションが効いていることの確認も行いたいため、あえてminLength('content', 3)の記述をいれて3文字未満をはじく用にしています。試しに1~2文字の入力をして送信してみましょう。

5_5_7

3文字以上にすると送信完了出来ることと、3文字以下で失敗することを確認しておきます。

$validatorオブジェクトはほかにもメソッドを持っており、以下のようなものがあります。

  • numeric('number')

    値が数字であることを確認する

  • inList('gender', ['male', 'female'])

    値が第二引数に渡したリスト内にあるかを確認する

  • range('age', [18, 65])

    値が第二引数に渡した値の範囲内にあるかを確認する

  • email('email')

    値が有効なメールアドレスの形になっているかを確認する

1つ重要な点として、validationDefault()でのバリデーションはコントローラでのnewEntity()もしくはpatchEntity()でエンティティにデータが入るタイミングで起こるということです。

今回作成したaddアクションではpatchEntity()が実行されるタイミングでバリデーションが実行されます。

Lesson 5 Chapter 6
編集画面の作成

つぎに作成したタスクの内容を編集出来るようにしていきましょう。タスク一覧画面からタスクの編集画面へと移動し、変更前のタスク内容を表示。編集内容をフォームに入力し送信すると、編集内容が保存され、タスクの内容が変更されるといった流れになります。

編集画面のアクション

src/Controller/TasksController.phpを開き、editメソッドを追加しましょう。

TasksController.php
  public function edit($id)
  {
    $task = $this->Tasks->findById($id)->firstOrFail();
    if ($this->request->is('post')) {
      $this->Tasks->patchEntity($task, $this->request->getData());
      if ($this->Tasks->save($task)) {
          $this->Flash->success('編集が完了しました');
          return $this->redirect(['action' => 'index']);
      }
      $this->Flash->error('編集に失敗しました');
    }
  
    $this->set('task', $task);
  }

最初にidの値を使って、編集を行うエンティティの取得を行っています。

$task = $this->Tasks->findById($id)->firstOrFail();

「findBy+フィールド名('値')」を使うことで指定したフィールドのみを対象にして、'値'と一致するデータを取得するためのSQL文が含まれるオブジェクトが取得出来ます。

今回の場合はtasksテーブルのidカラムを対象にして、$idの値で検索し、一致したレコードのエンティティを取得するためのSQL文が含まれたオブジェクトを取得しています。

その後のfirstOrFail()は、取得したオブジェクトに含まれるSQL文を実行し、取得したデータの1行目を返す役割を果たします。

わかりにくい部分かと思うのですが、findById($id)では希望するデータを取得するためのSQL文の発行までで止めているということになります。そして、その後のfirstOrFail()が実行されて初めてSQL文が実行され、その内容に沿ったデータが返ってくることになります。

find()などのテーブル検索用のメソッドについてはLesson6でも改めて説明をしていきます。

1行目の処理の後はaddアクションと同様の流れとなりますが、違いとして patchEntity()が取っているエンティティ $taskが空のエンティティではないため、上書きが行われる点となります。

editアクションの引数

editアクションではaddアクションとは違って、$idという引数を取っていることに気づいたでしょうか?編集機能では新規作成と違い、編集元となるデータを必ず取得しておく必要があります。そのため引数に$idを取るようにし、引数無しでは使うことの出来ないメソッドとなっています。

編集画面のテンプレート

続いてビューテンプレートの作成です。templates/Tasks配下にedit.phpを作成し、以下の内容を記述していきましょう。

edit.php
<h1>編集画面</h1>
<?php
  echo $this->Form->create($task,['type'=>'post'],['url'=>['action'=>'edit']]);
  echo $this->Form->control('content');
  echo $this->Form->button('保存');
  echo $this->Form->end();
?>

テンプレートについては新規作成画面のadd.phpとほぼ同様となります、送信先をeditに編集したのみとなります。

リンクの作成

src/templates/Tasks/index.phpを開き、タスク一覧画面に編集画面へのリンクを設置しましょう。各タスクの右端に編集画面へのリンクを置きます。

index.php
<td>
  <?= $this->Html->link('編集', ['action' => 'edit', h($task->id)]) ?>
</td>

上記をtrタグ内の最後に追加しましょう。

5_6_1

動作確認

作成した編集リンクをクリックし編集画面に入り、contentの内容を書き換えて保存してみましょう。
また、新規作成機能で追加したバリデーションも機能していることを確認しておきましょう。問題なく指定したタスクが編集されていれば完了です。

Lesson 5 Chapter 7
削除アクションの作成

Lesson5の最後に削除機能を追加します。タスク一覧画面に削除アクションへのリンクを設置し、押下することで画面の遷移なく削除が完了するように作成します。

deleteアクション

これまでの流れと同様に、まずはsrc/Controller/TasksController.phpを開き、deleteアクションを追加します。

TasksController.php
  public function delete($id)
  {
    $task = $this->Tasks->findById($id)->firstOrFail();
    if ($this->Tasks->delete($task)) {
        $this->Flash->success('id '.$task->id.' を削除しました');
        return $this->redirect(['action' => 'index']);
    }
  }

editアクション同様にidを引数に取り、指定のエンティティデータを取得しています。エンティティの内容を操作する必要などはないので、すぐにdelete()を行っています。削除完了後は一覧画面へと戻りフラッシュを表示します。

delete()メソッドを実行することで、データベース上のテーブルからレコードの削除を行います。

リンクの作成

src/templates/Tasks/index.phpを開き、編集リンクの隣に削除のリンクを作成しましょう。

index.php
    <td>
      <?= $this->Html->link('削除', ['action' => 'delete', h($task->id)]) ?>
    </td>

5_7_1

削除のリンクをクリックするとすぐに削除が行われ、成功のフラッシュが表示されます。

以上でCRUDを行う基本的な画面の作成は終了です。