目次


CodeIgniter を使って動的 Web サイトを作成する

CRUD 操作に MVC フレームワークを使用して作業を効率化する

Comments

CodeIgniter は、PHP で作成されたオープンソースの Web アプリケーション・フレームワークであり、MySQL、DB2® Express-C を始めとする多くのデータベース・アプリケーションを扱うことができます。CodeIgniter は MVC デザイン・パターンを使用しています。MVC デザイン・パターンの主要な目標は、ソフトウェア・アプリケーションのデータ・レイヤーとプレゼンテーション・レイヤーを分離することです。MVC (Model-View-Controller) パターンでは、モデルはデータ・レイヤーを管理し、データベースとの通信を行います。ビューはプレゼンテーション・レイヤーを管理し、UI とコンテンツを表示します。そしてコントローラーはビューとモデルとの間の通信を管理します。

この記事では、動的な Web サイトまたはアプリケーションの基礎を CodeIgniter を使って作成するために必要なステップの概要を説明します。この記事の前提として、CodeIgniter V1.7.2 以降と MySQL V4.1 以降がインストールされており、読者がその両方を基本的に理解しているものとします。CodeIgniter を初めて扱う人、あるいは簡単な復習が必要な人は、「参考文献」を参照してください。

サイトの基礎: ウィジェットと CRUD

当然のことですが、ほとんどの動的 Web サイトは、この記事で取り上げる例とは異なります (大抵は大きく異なります)。ただし、すべての動的 Web サイトには 2 つの重要な共通点、つまりデータベースと、そのデータベースから (動的に) 取得される対象があります。この議論を一般化するために、この動的に取得される対象をウィジェットと呼ぶことにします。ウィジェットは、販売される本、レシピ、ブログのエントリー、プレス・リリースなど、ほとんど何でも構いません。ウィジェットがどのようなものであるかによらず、ウィジェットを定義するためには一貫性のある情報セットが必要です。例えば、あるレシピに必要な情報セットとしては、料理名、材料、作り方、栄養成分などが考えられます。

データベースからウィジェットを取得するためには、まずウィジェットを作成する必要があります (そして更新や、さらには削除も必要かもしれません)。そこに CRUD が登場します。CRUD は、データベースの中にあるウィジェットの管理に必要な 4 つの基本的な操作を表します。CRUD はウィジェットと共にすべての動的 Web サイトの基礎をなしています。

データベースをセットアップする

この記事では例として、ある生徒のグループとその親の連絡先情報 (子供のスポーツ・チーム、YMCA のグループ、学校のクラスなど) を管理する Web アプリケーションを作成します。

まず、ウィジェットのデータ・モデルを作成します。このウィジェットに必要な情報セットは以下のとおりです。

  • 生徒の名前
  • 親の名前
  • 住所
  • 市町村名
  • 郵便番号
  • 電話番号
  • E メール・アドレス

このウィジェットを保存するために、student というテーブルを作成します。このテーブルのフィールドは上述の情報セットに対応しています。MySQL のデータベースとテーブルを作成するためのスクリプトをリスト 1 に示します。

リスト 1. MySQL のデータベースとテーブルを作成するためのスクリプト
CREATE DATABASE classroom;

USE classroom;

CREATE TABLE IF NOT EXISTS `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `s_name` varchar(64) DEFAULT NULL,
  `p_name` varchar(64) DEFAULT NULL,
  `address` varchar(128) DEFAULT NULL,
  `city` varchar(32) DEFAULT NULL,
  `state` char(2) DEFAULT NULL,
  `zip` char(10) DEFAULT NULL,
  `phone` char(20) DEFAULT NULL,
  `email` varchar(64) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

CodeIgniter の初期設定

データベースとテーブルを作成したら、CodeIgniter のデータベース変数を .\system\application\config\database.php で設定し、ベース URL を .\system\application\config\config.php で設定します。この記事では、ベース URL を http://127.0.0.1/codeigniter/ とします。

デフォルトのコントローラーとビュー

次に、デフォルトのコントローラーとビューを作成します (コントローラーとビューが用意できると、作成されたコードすべての効果を見ることができます)。このプロジェクトでは、student.php というコントローラーを .\system\application\controllers\ フォルダーに作成し (リスト 2)、この student.php を .\system\application\config\routes.php でデフォルトのコントローラーとして設定します。

リスト 2. デフォルトのコントローラー: Student
<?php

class Student extends Controller {

  function Student()
  {
    parent::Controller();  
  }
  
  function index()
  {
    // display information for the view
    $data['title'] = "Classroom: Home Page";
    $data['headline'] = "Welcome to the Classroom Management System";
    $data['include'] = 'student_index';

    $this->load->view('template', $data);
  }
}

/* End of file student.php */
/* Location: ./system/application/controllers/student.php */

index() 関数によって data という配列を作成しており、この配列に 3 つのインデックスが含まれていることに注意してください (インデックスの名前は、titleheadlineinclude です)。この配列は、template というビューに渡され、template.php (リスト 3) として .\system\application\views\ フォルダーに保存されます。

リスト 3. デフォルトのビュー: template.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />

<title><?php echo $title;?></title>
</head>
<body>

<h1><?php echo $headline;?></h1>

<?php $this->load->view($include);?>

</body>
</html>

このビューは、この Web サイトのすべてのページに対する HTML シェルまたは視覚的なラッパーになります。このビューには標準的な HTML の設定が含まれており、コントローラーからの、titleheadlineinclude という 3 つの値を想定しています。title、headline、include はそれぞれ、ページのタイトル、ページの見出し、コンテンツを表示するために含めるビュー・ファイルに対応します。

初期設定の最後のステップでは、template.php (上記のリスト 2) で宣言されているように、このビュー・ファイルに student_index.php という名前を付け、.\system\application\views\ フォルダーに保存します。リスト 4 はこのビュー・ファイルのソース・コードです。

リスト 4. 基本的な「Hello World」テキスト
<p>Congratulations. Your initial setup is complete!</p>

HTML の標準的な構造タグが何もないことに注意してください。これは、template.php ビューによって student_index.php が含められ、student_index.php は template.php ビューの HTML ラッパーと表示の一部になっているためです。

ここで、http://127.0.0.1/codeigniter/ にアクセスすると、ブラウザーにロードされるページには、ページのタイトル、「Welcome to the Classroom ...」という見出し、そして「Congratulations …」というメッセージが含まれています。

4 つの CRUD 操作

では、この Web アプリケーションを CRUD 操作の面から見てみましょう。

ウィジェットを作成する

初期設定は完了したので、ウィジェットを操作するコードを作成する必要があります。まず、4 つの CRUD 操作の 1 つ目、Create (作成) から始めましょう。このコードにより、ユーザー入力をウィジェットとしてデータベースに保存する必要があります。

まず、student テーブルの構造に対応するフィールドを持つ HTML フォームを作成します。student_add.php というビュー・ファイルを .\system\application\views\ フォルダーに作成します (リスト 5)。

リスト 5. 作成操作のための HTML フォーム・フィールドを生成する
<?php 

echo form_open('student/create');

// an array of the fields in the student table
$field_array = array('s_name','p_name','address','city','state','zip','phone','email');
foreach($field_array as $field)
{
  echo '<p>' . $field;
  echo form_input(array('name' => $field)) . '</p>';
}

// not setting the value attribute omits the submit from the $_POST array
echo form_submit('', 'Add'); 

echo form_close();

?>

このファイルに関して注意点が 2 つあります。1 つ目は、このファイルで form_input() 関数を使用していることです。この関数は CodeIgniter の Form ヘルパーの一部であり、この関数を利用すると大半のフォームに必要な HTML を短時間で生成することができます。form_input() 関数は 3 つの引数を取ります (フィールド名、フィールドの値、任意の追加データ (JavaScript など))。

2 つ目の注意点は、form_input() 関数と同じ 3 つの引数を取る form_submit() 関数のフィールド名が空のストリングになっていることです。フィールド名が空のため、submit フィールドはフォームのポスト用の配列には含まれません。モデルはデータベースにレコードを追加する際、この配列を使用します。submit フィールドがこの配列に含まれている場合、データベースへの挿入が失敗します。

次に、HTML フォームを表示できるように、Student コントローラーに関数を追加する必要があります (リスト 6)。

リスト 6. Student コントローラーの add() 関数
  function add()
  {
    $this->load->helper('form');
    
    // display information for the view
    $data['title'] = "Classroom: Add Student";
    $data['headline'] = "Add a New Student";
    $data['include'] = 'student_add';

    $this->load->view('template', $data);
  }

student_add.php ビューで使えるように、この関数が CodeIgniter の Form ヘルパーをロードしていることに注意してください。

ここで、http://127.0.0.1/codeigniter/index.php/student/add にアクセスすると、ブラウザーには student テーブルのレコードを表すフィールドを含んだ HTML フォームがロードされます。このフォームを送信するとエラーになりますが、それはフォームの POST 送信を受信する関数をまだ作成していないからです。そこで、Student コントローラーに create() 関数を追加します (リスト 7)。

リスト 7. Student コントローラーの create() 関数
  function create()
  {
    $this->load->helper('url');
    
    $this->load->model('MStudent','',TRUE);
    $this->MStudent->addStudent($_POST);
    redirect('student/add','refresh');
  }

この関数 (URL としては http://127.0.0.1/codeigniter/index.php/student/create に対応します) はまず、MStudent というモデルをロードします (このモデルは次のステップで作成します)。次に addStudent() 関数を実行し、student_add.php ページに作成された post 配列を渡します。最後に、URL ヘルパー・ファイルの一部である redirect() 関数を使ってユーザーを student_add.php ページにリダイレクトします。

MStudent モデルはデータベースの student テーブルを操作します。.\system\application\models フォルダーの中に mstudent.php というファイルを作成します (ファイル名には、そのファイルがモデルであることを示す何らかの文字 (つまり m) をファイル名の先頭または末尾に追加しておくのが望ましいです)。このモデルのコードをリスト 8 に示します。

リスト 8. データ・レイヤーを処理する MStudent モデル
<?php 

class MStudent extends Model{

  // Create student record in database
  function addStudent($data)
  {
    $this->db->insert('student', $data);
  }

}

/* End of file mstudent.php */
/* Location: ./system/application/models/mstudent.php */

このモデルは db->insert() 関数を使って post 配列のデータを student テーブルに挿入します。db->insert() 関数は 2 つの引数を取ります (テーブルの名前と、フィールドの名前と値の連想配列)。この関数は CodeIgniter の Active Record クラスの一部です。Active Record クラスは開発時間を短縮するために CodeIgniter に用意されているショートカットの 1 つであり、自動的にロードされます。

また、先ほど触れたように、post 配列に Submit ボタンがフィールドとして含まれていると、テーブルの中に submit というフィールドはないため、その挿入は失敗します。

再度 http://127.0.0.1/codeigniter/index.php/student/add にアクセスします。今度はフィールドに何らかのデータを追加し、Submit をクリックします。ページが更新され、すべてのフィールドが空になります。しかしデータベースを調べてみると、先ほど送信したデータが student テーブルに追加されていることがわかります。

ウィジェットを取得する

CRUD 操作の 2 つ目は Read (読み取り) です。このコードは単純にウィジェットのレコードをデータベースから読み取る必要があります。もちろん、これらの読み取ったレコードは、表示するのが一般的であるため、多くの人々はこの操作を「読み取り」とは呼ばず、「取得」と呼んでいます。

まず、student テーブルのレコードを取得する関数によって MStudent モデルを更新します (リスト 9)。

リスト 9. MStudent 関数によって student テーブルのレコードを取得する
  // Retrieve all student records
  function listStudents()
  {
    return $this->db->get('student');
  }

このコードは、同じく CodeIgniter の Active Record クラスに含まれる db->get() 関数を使用し、この関数の引数で指定されたテーブル (student) に対する SELECT * クエリーを生成しています。

次に、listing() という関数を Student コントローラーに追加します。この関数は MStudent モデルをロードして listStudents() 関数を実行します (リスト 10)。

リスト 10. student レコードを表示する HTML テーブルを作成する
  function listing()
  {
    $this->load->library('table');
    
    $this->load->model('MStudent','',TRUE);
    $students_qry = $this->MStudent->listStudents();

    // generate HTML table from query results
    $students_table = $this->table->generate($students_qry);
    
    // display information for the view
    $data['title'] = "Classroom: Student Listing";
    $data['headline'] = "Student Listing";
    $data['include'] = 'student_listing';

    $data['data_table'] = $students_table;

    $this->load->view('template', $data);
  }

listing() 関数は HTML テーブル・クラスの table->generate() 関数 (CodeIgniter のショートカット) を使っています。table->generate() 関数によって生成される HTML テーブルでは、クエリーの実行結果オブジェクトのフィールド名をヘッダー行に使用し、それに続けて各レコードを表示します。生成された HTML テーブルは data 配列の template ビューに渡されます。

最後に、この HTML テーブルを表示するビューが必要です。.\system\application\views\ フォルダーの中に student_listing.php というファイルを作成します (リスト 11)。

リスト 11. HTML テーブルを表示する
<?php echo $data_table; ?>

これらの操作の結果を見るためには、http://127.0.0.1/codeigniter/index.php/student/listing にアクセスします。するとデータベースから取得された生徒の一覧が表示されます。今度は少し時間をかけ、入力フォームを使って、あるいは入力フォームと同じことをするリスト 12 の SQL スクリプトを実行して、さらに生徒のレコードを追加します。

リスト 12. 生徒のレコードを追加する SQL スクリプト
INSERT INTO classroom.student 
	(id, s_name, p_name, address, city, state, zip, phone, email) 
	VALUES
(NULL, 'Peter Green', 'Len & Natalie Green', '480 West Broad Street', 
	'Eastbrook Canyon', 'PA', '19104', '(215) 900-2341', 
	'greenery@timewarner.dsl.com'),
(NULL, 'Jonah Ross', 'Robert & Linda Ross', '1293 Law Street', 
	'Eastbrook Village', 'PA', '19105', '(215) 907-1122', 'ross_boss@gmail.com'),
(NULL, 'Rebecca Dillon', 'Lainie and Howard Dillon', '12 Flamingo Drive', 
	'Westbrook Village', 'PA', '19103', '(215) 887-4313', 'ld_1975@yahoo.com'),
(NULL, 'Noah Singer', 'Carolyn & Peter Singer', '393 Green Lake Road, 8th Floor', 
	'Eastbrook Village', 'PA', '19105', '(215) 907-2344', 'candp@gmail.com'),
(NULL, 'Trevor Lee Logan', 'Steven Logan', '400 Green Lake Road, 9th Floor', 
	'Eastbrook Village', 'PA', '19105-6541', '(828) 299-9885', 
	'misterSAL@sbcglobal.net'),
(NULL, 'Audrey Christiansen', 'Lovey Christiansen', '1993 East Sunnyside Lane', 
	'Eastbrook Canyon', 'PA', '19104', '(215) 887-5545', 
	'lovey@christiansen-clan.com');

次の CRUD 操作に進む前に、サイトにアクセスしやすくするために、.\system\application\views フォルダーの中にある template.php ファイルの <h1> タグの上に、一連のグローバル・ナビゲーション・リンクを追加します。このコードがリスト 13 です。

リスト 13. グローバル・ナビゲーション・リンク
<div class="navigation">
<?php 
  // nav bar
  echo anchor('student/index', 'Home');
  echo (' | ');
  echo anchor('student/add', 'Add a New Student');
  echo (' | ');
  echo anchor('student/listing', 'List All Students');
?>
</div>

このコードは、CodeIgniter の URL ヘルパー・ファイルの一部である、anchor() 関数というショートカットを使っています。そして、Student コントローラーのすべての関数は template ビューを使用するので、Student コンストラクターの一部として URL ヘルパーをロードする必要があります (リスト 14)。また、ヘルパー・ファイルを 2 度ロードすることがないように、create() 関数からヘルパー・ファイルを削除する必要があります。

リスト 14. コンストラクターにヘルパーをロードする
  function __construct()
  {
    parent::Controller();

    // load helpers
    $this->load->helper('url');
  }

ウィジェットを更新する

今度は、CRUD 操作の 3 つ目、Update (更新) を行います。更新新操を行うコードでは、以下を行う必要があります。

  • データベースから 1 つのウィジェットのレコードを読み取る
  • そのレコードを表示し、編集できるようにする
  • 更新した情報をユーザーがデータベースに返送できるようにする

まず、生徒のリストを編集するための「edit」リンクを各行に含めるように更新することから始めましょう。この場合にも、このテーブルに必要な HTML の大部分を HTML テーブル・クラスを使って生成することができます。ただしこの場合には、データベース・クエリーの実行結果のオブジェクトに明示的にループ処理を行ってテーブルの行を作成し、それから「edit」リンクを追加する必要があります。Student コントローラーの listing() 関数に対する変更の詳細をリスト 15 に示します。

リスト 15. HTML テーブル・クラスを使ってテーブルを作成する
    // generate HTML table from query results
    $tmpl = array (
      'table_open' => '<table border="0" cellpadding="3" cellspacing="0">',
      'heading_row_start' => '<tr bgcolor="#66cc44">',
      'row_start' => '<tr bgcolor="#dddddd">' 
      );
    $this->table->set_template($tmpl); 
    
    $this->table->set_empty("&nbsp;"); 
  
    $this->table->set_heading('', 'Child Name', 'Parent Name', 'Address', 
        'City', 'State', 'Zip', 'Phone', 'Email');
  
    $table_row = array();
    foreach ($students_qry->result() as $student)
    {
      $table_row = NULL;
      $table_row[] = anchor('student/edit/' . $student->id, 'edit');
      $table_row[] = $student->s_name;
      $table_row[] = $student->p_name;
      $table_row[] = $student->address;
      $table_row[] = $student->city;
      $table_row[] = $student->state;
      $table_row[] = $student->zip;
      $table_row[] = $student->phone;
      $table_row[] = mailto($student->email);

      $this->table->add_row($table_row);
    }    

    $students_table = $this->table->generate();

この変更されたコードでは以下のように、より詳細な HTML の制御を行っています。

  • ヘッダー行を含める際に適切なフィールド名と背景色を指定しています。
  • ID フィールドを表示しません。
  • 1 行ごとに背景色を変更しています。

次に、edit() という関数を Student コントローラーに追加します。この edit() 関数を「edit」リンクが指すようにします。この edit() 関数のコードをリスト 16 に示します。

リスト 16. Student コントローラーの edit() 関数
  function edit()
  {
    $this->load->helper('form');

    $id = $this->uri->segment(3);
    $this->load->model('MStudent','',TRUE);
    $data['row'] = $this->MStudent->getStudent($id)->result();

    // display information for the view
    $data['title'] = "Classroom: Edit Student";
    $data['headline'] = "Edit Student Information";
    $data['include'] = 'student_edit';

    $this->load->view('template', $data);
  }

edit」リンクは、生徒のレコードの ID を URL の 3 番目のセグメント (http://127.0.0.1/codeigniter/index.php/ の後) として渡します。uri->segment(3) 関数 (CodeIgniter の URL ヘルパー・ファイルの一部) は、URL に含まれる ID を解析して MStudent モデルの関数に渡し、その関数がその生徒のレコードを取得します (リスト 17)。

リスト 17. データベースから生徒のレコードを取得する
  // Retrieve one student record
  function getStudent($id)
  {
    return $this->db->get_where('student', array('id'=> $id));
  }

次に、この生徒のレコードを表示、編集できるように、student_edit.php という HTML フォームを作成します (リスト 18)。

リスト 18. 生徒を編集するための HTML フォームのビューを作成する
<?php 

echo form_open('student/update');

echo form_hidden('id', $row[0]->id);

// an array of the fields in the student table
$field_array = array('s_name','p_name','address','city','state','zip','phone','email');
foreach($field_array as $field_name)
{
  echo '<p>' . $field_name;
  echo form_input($field_name, $row[0]->$field_name) . '</p>';
}

// not setting the value attribute omits the submit from the $_POST array
echo form_submit('', 'Update'); 

echo form_close();

?>

このファイルが student_add.php とほとんど同じであることに注意してください。多くの開発者は、2 つの別々のファイルを持つよりも追加/編集用に 1 つのファイル構成体を使いたがります。最終的に、これはスタイルの問題であり、どちらの方法にも長所/短所があります。

次に、POST されたフォームを受信するために、Student コントローラーに update() 関数を追加します。この関数のコードをリスト 19 に示します。

リスト 19. Student コントローラーの update() 関数
  function update()
  {
    $this->load->model('MStudent','',TRUE);
    $this->MStudent->updateStudent($_POST['id'], $_POST);
    redirect('student/listing','refresh');
  }

最後に、データベースの生徒のレコードを更新する関数を使って MStudent モデルを更新します。この関数をリスト 20 に示します。

リスト 20. 生徒のレコードを更新する
  // Update one student record
  function updateStudent($id, $data)
  {
    $this->db->where('id', $id);
    $this->db->update('student', $data); 
  }

これで更新操作が完了しました。生徒の一覧にアクセスしていずれかの生徒のレコードを編集し、フォームを送信すると、更新された情報が生徒の一覧に反映されることがわかります。

ウィジェットを削除する

CRUD 操作の最後は Delete (削除) です。削除操作では、ユーザーが一覧からレコードを選択し、そのレコードを削除できる必要があります。また、実際にレコードを削除する前に、(ユーザーが誤ってリンクをクリックした場合のために) ユーザーの意思を確認する必要があります。

まず、Student コントローラーの listing() 関数内の「edit」リンクを作成するコードを、リスト 21 のコードで置き換えます。

リスト 21. 生徒の一覧に「delete」リンクを追加する
      $table_row[] = '<nobr>' . 
        anchor('student/edit/' . $student->id, 'edit') . ' | ' .
        anchor('student/delete/' . $student->id, 'delete',
          "onClick=\" return confirm('Are you sure you want to '
            + 'delete the record for $student->s_name?')\"") .
        '</nobr>';

次に、Student コントローラーに delete() 関数を追加し、「delete」リンクがこの delete() 関数を指すようにします。この関数のコードをリスト 22 に示します。

リスト 22. Student コントローラーの delete() 関数
  function delete()
  {
    $id = $this->uri->segment(3);
    
    $this->load->model('MStudent','',TRUE);
    $this->MStudent->deleteStudent($id);
    redirect('student/listing','refresh');
  }

最後に、レコードを削除する関数を使って MStudent モデルを更新します。この関数をリスト 23 に示します。

リスト 23. 生徒のレコードを削除する
  // Delete one student record
  function deleteStudent($id)
  {
    $this->db->where('id', $id);
    $this->db->delete('student'); 
  }

では、試してみましょう。生徒の一覧にアクセスし、1 人の生徒のレコードを削除できるか試してみます。JavaScript によって表示されるウィンドウで「OK」をクリックすると、生徒の一覧が更新され、その生徒のレコードが削除されていることがわかります。

まとめ

おめでとうございます。これで CodeIgniter を使った動的 Web サイトについての説明は終わりです。この Web サイトは MVC パターンを使用しているため、プレゼンテーション・レイヤーとデータ・レイヤーが非常に明確に分離されています。また、CodeIgniter に用意されたコーディング用のショートカットを含めることで、開発時間が短縮され、必要なコードの行数も最小限になっています。実際、このアプリケーションが、たった 1 つのコントローラーと 1 つのモデル、5 つのビューのみで完成されたことに気付いたでしょうか。これは非常に効率的なコーディングです。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source
ArticleID=619312
ArticleTitle=CodeIgniter を使って動的 Web サイトを作成する
publish-date=01122010