前回の記事、CodeIgniter4でMySQLのDB構築の続きです。
#DBの操作はModelに書こう
MVCモデルにおけるModelとは、通常DBの操作や入力されたデータのやり取りや加工など所謂ビジネスロジックと呼ばれるものを担当するところとなります。CI4においては通常app/Models/
配下に記述します。
###まずはModelのファイルを作る。
今回はapp/Models/InitDB.php
というファイルを作って前回のDB生成、テーブル生成、接続テストを各々メソッドとして用意します。
特段の事情がない限りファイル名とClass名
は一致させたほうが良いでしょう。
<?php
namespace App\Models;
use CodeIgniter\Model;
use Config\Database;
use Exception;
class InitDB extends Model{
public function createDB(){
try{
$conf = [
'hostname' => $_ENV['database.default.hostname'] ,
'database' => '' ,
'username' => $_ENV['database.default.username'] ,
'password' => $_ENV['database.default.password'] ,
'DBDriver' => $_ENV['database.default.DBDriver'] ,
'charset' => $_ENV['database.default.charset'] ,
'DBCollat' => $_ENV['database.default.DBCollat'] ,
];
$forge = Database::Forge( $conf );
$forge->createDatabase( $_ENV['database.default.database'] );
}catch( Exception $e ){
throw $e;
}
return "データベース生成成功\n";
}
public function createTable(){
try{
$forge = Database::Forge();
$fields = [
'id' => [
'type' => 'INT' ,
'unsigned' => true ,
'auto_increment' => true ,
] ,
'login_id' => [
'type' => 'VARCHAR' ,
'constraint' => 100 ,
'null' => false ,
'unique' => true ,
] ,
'login_pw' => [
'type' => 'VARCHAR' ,
'constraint' => 100 ,
'null' => false ,
] ,
];
$forge->addField( $fields );
$forge->addPrimaryKey( 'id' );
$forge->createTable( 'users' );
}catch( Exception $e ){
throw $e;
}
return "テーブル生成成功\n";
}
public function connectionTest(){
try{
$db = Database::connect();
}catch( Exception $e ){
throw $e;
}
return "このDBのテーブル=" . implode( ',' , $db->listTables() );
}
public function dropDB(){
try{
$forge = Database::Forge();
$forge->dropDatabase( $_ENV['database.default.database'] );
}catch( Exception $e ){
throw $e;
}
return "データベース削除成功\n";
}
}
namespace
はこのファイルに使用する名前空間を指定します。ここではApp\Models
と記述していますが、Modelsディレクトリ配下のファイルは基本的にこの名前空間で問題ないと思います。
use
はインポートする名前空間を指定します。
名前空間についてはこの記事が大変わかりやすく書いてありおすすめです。
クラスは\CodeIgniter\Model
を継承して作ります。
はじめにuse CodeIgniter\Model;
をしてるので
class InitDB extends \CodeIgniter\Model
としなくても
class InitDB extends Model
だけで通じます。
各メソッドの内容はほぼ前回のものと同様なので説明は割愛します。
ソースの最尾部には前回なかったメソッドdropDB()
を追加しましたが、これは見ての通りDBを削除するためのメソッドです。
###次はControllerのファイル
これに合わせて、Controllerも書き換えます。前回書いていたファイルは次のものに差し替えてください。
<?php
namespace App\Controllers;
use App\Models\InitDB;
use Exception;
class Home extends BaseController{
public function index(){
return view( 'welcome_message' );
}
public function dbinit(){
try{
$result = '<html lang="ja"><pre>';
$initdb = new InitDB();
$result .= $initdb->createDB();
$result .= $initdb->createTable();
$result .= $initdb->connectionTest();
$result .= '</pre></html>';
}catch( Exception $e ){
return $e->getMessage();
}
return $result;
}
public function db_delete(){
try{
$result = '<html lang="ja"><pre>';
$initdb = new InitDB();
$result .= $initdb->dropDB();
$result .= '</pre></html>';
}catch( Exception $e ){
return $e->getMessage();
}
return $result;
}
}
ここではnamespaceがApp\Controllers
となっていて、利用したいModelとは名前空間が違うので、これを使えるようにuse App\Models\InitDB;
で、モデルのクラスをインポートしてやります。
実際にインスタンスを作っているところは、new InitDB();
です。
なおこれは、useを使わずに都度名前空間を書いてもOKなので、new InitDB();
はnew \App\Models\InitDB();
とした上でuse App\Models\InitDB;
の行を取り去っても同じ内容となります。
例外の名前空間Exception
も同様です。
<?php
namespace App\Controllers;
class Home extends BaseController{
public function index(){
return view( 'welcome_message' );
}
public function dbinit(){
try{
$result = '<html lang="ja"><pre>';
$initdb = new \App\Models\InitDB(); // <--階層も記述する
$result .= $initdb->createDB();
$result .= $initdb->createTable();
$result .= $initdb->connectionTest();
$result .= '</pre></html>';
}catch( \Exception $e ){ // <-- 頭に\がついている点に注意
return $e->getMessage();
}
return $result;
}
public function db_delete(){
try{
$result = '<html lang="ja"><pre>';
$initdb = new \App\Models\InitDB();
$result .= $initdb->dropDB();
$result .= '</pre></html>';
}catch( \Exception $e ){
return $e->getMessage();
}
return $result;
}
}
http://example.com/Home/dbinit
にアクセスすると、DBやテーブルがない場合は、
データベース生成成功
テーブル生成成功
このDBのテーブル=users
となるはずです。
(1度目のアクセスで上記画面が出た後リロードした場合など)すでにDBとテーブルができている場合は次の表示になるはずです。
Table 'users' already exists
再度試す場合は
http://example.com/Home/db_delete
にアクセスしてDBを削除した後、再度http://example.com/Home/dbinit
にアクセスします。
#テーブルにデータを出し入れするモデルも作ろう
次に、DBへのデータのInsert/Select/Update/Deleteの操作を極力簡略化した記述で書いてみます。
<?php
namespace App\Models;
use CodeIgniter\Model;
class Users extends Model{
protected $table = 'users';
protected $primaryKey = 'id';
protected $allowedFields = [ 'login_id' , 'login_pw' ];
}
たったこれだけです。
CIのモデルにはDBへの入出力をするメソッドがすでに用意されているので、簡単なDB操作ならば、ここで定義している操作するテーブル名の指定する $table
PKEYのフィールド名を指定する $primaryKey
操作を許可するフィールド名を指定する $allowedFields
といった親クラスに用意されているメンバ変数を上書きするだけで実現可能です。
これをコントローラから呼び出すには次のような書き方でOKです。
public function add_test( $id , $pw ){
try{
$db = new \App\Models\Users();
$db->insert( [ 'login_id' => $id , 'login_pw' => $pw ] );
}catch( Exception $e ){
die( $e->getMessage() );
}
return "Add OK";
}
試す場合はhttp://example.com/Home/add_test/追加したいID/追加したいPW
です。
以前の記事で述べたとおり、CIではメソッドの引数はURLのパスの第3階層以降と一致しますので、追加したいID
は$id
に追加したいPW
は$pw
に渡されます。
なお、前回の記事で作ったusers
テーブルではlogin_idはunique制約を付加しているので、同じURLに2度アクセスするとDBがエラーが出るはずですので、何度も試す場合は都度URLを変えてアクセスしてみてください。
このあたりのDB操作の詳細は次回の記事で、Viewの説明と共にまとめて記したいと思います。
現在の記事までのコントローラでは直接HTMLを作り、組み上がったHTMLの格納された変数や文字列をreturn
でCIのエンジンに返すことで出力を行っていますが、例によって本来HTMLの組み上げはコントローラの仕事ではなくView
の仕事なので、次の記事ではViewでコンテンツを出力することを目指します。