前回に引き続き、今回は新規登録と更新処理を実装します。
理解度優先のため、バリデーションはなし。SQLはメソッド(関数)内に直書きとします。
(本当はmodelやRepositoryを使用して管理したほうが可読性が上がります。また別の機会に記事にします。)
実装する流れ
登録してから登録したデータを更新するというような流れを想定しています。
- 新規登録リンクを押下
- 新規登録画面(更新画面と共通)を表示
- データ入力後、DBにinsert
- 一覧画面へリダイレクト
- 更新リンク(ID)を押下
- 更新画面(新規登録画面と共通)を表示
- データ入力後、DBにupdate
新規登録処理の実装
一覧画面に新規登録リンクを追加
<body>
<h1>ユーザ一覧</h1>
<table border="">
<thead>
<tr>
<td>ID</td>
<td>ユーザ名</td>
<td>年齢</td>
</tr>
</thead>
<tbody>
<?php foreach($userList as $user): ?>
<tr>
<td><?= $user['id']; ?></td>
<td><?= $user['user_nm']; ?></td>
<td><?= $user['age']; ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<a href="/test/detail">新規登録</a> <?php //←リンクを追加 ?>
</body>一覧画面に新規登録画面へ遷移するためのリンクを追加します。リンク先は「/test/detail」

ルートを追加
Route.phpに追加します。
<?php
use CodeIgniter\Router\RouteCollection;
/**
* @var RouteCollection $routes
*/
$routes->get('/', 'Home::index');
$routes->get('/test', 'TestController::index');
$routes->get('/test/detail', 'TestController::detail'); //←追加
$routes->post('/test/save', 'TestController::save');//←追加コントローラ追加
<?php
namespace App\Controllers;
use App\Controllers\BaseController;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Database;
class TestController extends BaseController
{
public function index()
{
$query = $this->db->query("SELECT * FROM AC_M_USER ORDER BY ID");
$userList = $query->getResultArray();
return view('test', [
'userList' => $userList,
]);
}
//↓detailメソッドを追加
/**
* 詳細画面
* @param $id
*/
public function detail($id = null)
{
$formObj = [
"id" => null,
"user_nm" => null,
"age" => null,
];
return view('save', [
'formObj' => $formObj,
]);
}
/**
* 登録・更新
*/
public function save()
{
//postされた値を取得
$formObj = $this->request->getPost();
if ($formObj["id"] == '') {
//idがない場合は登録とする
$params = [];
$sql = "";
$sql .= " INSERT INTO ac_m_user ( ";
$sql .= " user_nm ";
$sql .= " ,age ";
$sql .= " ) VALUES ( ";
$sql .= " ? "; $params[] = $formObj["user_nm"];
$sql .= " ,? "; $params[] = $formObj["age"];
$sql .= " ) ";
$query = $this->db->query($sql, $params);
}
return redirect()->to('/test');
}
}
detailメソッド
「/** */」を使用してこのメソッドの概要を一言でコメントを書いておきましょう。後から見やすくなります。
画面側で使用する情報は「null」で初期化しておきましょう。
saveメソッド
getPostでpostされてきた値をすべて取得して変数に格納します。
その後、idがない場合は新規登録とみなし、insert文で登録をします。
(お気づきかもですが、更新モードの際はelseを使用してupdateをします。)
登録(更新)後は一覧画面にリダイレクトします。
ビューの作成
次にsave.phpを作成します。
methodは「POST」、actionは「/test/save」とします。
先の初期化しておいた変数をinputのvalue値に初期値として設定しておきます。そうすることで更新モードで表示した際にそのデータを最初から表示しておくことができます。コントローラでDBからselectする処理は後述します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Welcome to CodeIgniter 4!</title>
<meta name="description" content="The small framework with powerful features">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" type="image/png" href="/favicon.ico">
</head>
<body>
<h1>新規登録・更新</h1>
<form action="/test/save" method="POST">
<?= csrf_field() ?>
<input type="hidden" name="id" value="<?= $formObj["id"] ?>">
<div>
ユーザ名<input type="text" name="user_nm" value="<?= $formObj["user_nm"] ?>">
</div>
<br>
<div>
年齢<input type="text" name="age" value="<?= $formObj["age"] ?>">
</div>
<input type="submit" value="更新">
</form>
</body>
</html>

更新処理の実装
一覧画面にidのリンクを追加
<body>
<h1>ユーザ一覧</h1>
<table border="">
<thead>
<tr>
<td>ID</td>
<td>ユーザ名</td>
<td>年齢</td>
</tr>
</thead>
<tbody>
<?php foreach($userList as $user): ?>
<tr>
<?php //↓aタグでリンクを追加 ?>
<td><a href="/test/detail/<?= $user['id']; ?>"><?= $user['id']; ?></a></td>
<td><?= $user['user_nm']; ?></td>
<td><?= $user['age']; ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<a href="/test/detail">新規登録</a>
</body>一覧のidにリンクを追加します。リンクは「/test/detail/1」のような形で最後にidを設定します。
この引数を使用し、DBからそのidと紐づく情報を取得し、更新するといった流れになります。
ルートの追加
先ほど同様に以下をRoute.phpに追加します。
<?php
use CodeIgniter\Router\RouteCollection;
/**
* @var RouteCollection $routes
*/
$routes->get('/', 'Home::index');
$routes->get('/test', 'TestController::index');
$routes->get('/test/detail', 'TestController::detail');
$routes->get('/test/detail/(:num)', 'TestController::detail/$1');//←追加
$routes->post('/test/save', 'TestController::save');コントローラ追加
detailメソッドにselect文を追加
/**
* 詳細画面
* @param $id
*/
public function detail($id = null)
{
$formObj = [
"id" => null,
"user_nm" => null,
"age" => null,
];
//↓追加
if (!is_null($id)) {
$params = [];
$sql = "";
$sql .= " SELECT ";
$sql .= " id ";
$sql .= " ,user_nm ";
$sql .= " ,age ";
$sql .= " FROM ";
$sql .= " ac_m_user ";
$sql .= " WHERE ";
$sql .= " id = ? "; $params[] = $id;
$query = $this->db->query($sql, $params);
$userObj = $query->getRowArray();
$formObj = [
"id" => $userObj["id"],
"user_nm" => $userObj["user_nm"],
"age" => $userObj["age"],
];
}
return view('save', [
'formObj' => $formObj,
]);
}ここでidをwhere句で指定して、選択した明細の情報を取得します。
その後、$formObjに上書きすることで取得した情報を初期表示することができます。
saveメソッドにはelseを追加し、update文を追加
/**
* 登録・更新
*/
public function save()
{
//postされた値を取得
$formObj = $this->request->getPost();
if ($formObj["id"] == '') {
//idがない場合は登録とする
$params = [];
$sql = "";
$sql .= " INSERT INTO ac_m_user ( ";
$sql .= " user_nm ";
$sql .= " ,age ";
$sql .= " ) VALUES ( ";
$sql .= " ? "; $params[] = $formObj["user_nm"];
$sql .= " ,? "; $params[] = $formObj["age"];
$sql .= " ) ";
$query = $this->db->query($sql, $params);
} else {
//それ以外は更新
$params = [];
$sql = "";
$sql .= " UPDATE ac_m_user SET ";
$sql .= " user_nm = ? "; $params[] = $formObj["user_nm"];
$sql .= " ,age = ? "; $params[] = $formObj["age"];
$sql .= " WHERE ";
$sql .= " id = ? "; $params[] = $formObj["id"];
$query = $this->db->query($sql, $params);
}
return redirect()->to('/test');
}$this->db->queryの第二引数にSQLで使用する引数を配列型で渡します。
「?」はプレースホルダといい、SQLインジェクション対策で必須です。こちらについてはまた今度。
また、トランザクションを使用することでエラーとなった際、巻き戻すみたいな動きをすることができます。(複数件同時登録とかしようとしたときに)
こちらもまた今度。
ビューはすでに共通化されているのでこれで表示できます。


まとめ
今回は CodeIgniter4 を使った新規登録・更新処理を実装しました。
他にもSQLインジェクション対策や、トランザクションなど考慮が必要なことがありますが、まずは基本から!
いきなり頭に詰め込むとわけわかんなくなりますからね。。
画面の作成からルート、コントローラでの SQL 実行までの流れが分かれば、CRUD の半分をクリアしたことになります。
次回は削除処理に進みます。
