QuictyによるPHP Webアプリの超高速開発-(5)tableのJOINとプルダウンメニュー

 データベースを使ったWebアプリケーションでは、テーブルに別のテーブルを結合して、仮想的な大きなテーブルとして利用する「JOIN」の機能が欠かせない。
また、レストランに対する料理の種類のように、1対多で関連づけられる可能性のあるものは、関連づけテーブルを別に用意すれば、容易に拡張できる。

この例では、Quictyの以下の機能の使い方を紹介する。

  • Virtualフィールドの利用とバインドされていないデータセットの登録、更新
  • list_optionsクラスモジュールを使ったテーブルのJOIN
  • info.htmlとedit.htmlを分離し、部品テンプレートform_view.incを作成して読み込み
  • info.htmlではform_view.incでlist_optionsによるJOINの結果を表示

今回は、以下のページとデータセットを作成する。

データセット マスタメンテページクラス ページクラスモジュール
restaurant restaurant index.class.php
category category category.class.php
category2restaurant category2restaurant category2restaurant.class.php

各データセットは以下のように設定する

restaurantデータセット

Name(カラム名) タイトル DB型 Quicty型
id - int id
name 店名 text text
category_id 料理の種類 - select_from_table(Virtual)

category_idはVirtual指定なので、フォームに表示されるが、テーブルにカラムは作成されない。

categoryデータセット

Name(カラム名) タイトル DB型 Quicty型
id - int id
name 店名 text text
category_id 料理ID int int

category2restaurantデータセット

Name(カラム名) タイトル DB型 Quicty型
id - int id
restaurant_id レストランID int int
category_id 料理ID int int

サンプルコードrestaurant03.zip
展開したrestaurant03フォルダをQTフォルダの中において、「アプリケーションの読み込み」で読み込んでください。

ご注意:このブログのサンプルコードは、シングルクオートやダブルクオートなどがスマートクオートに変換されているため、コピペしてもそのままではエラーになることが多いです(エディタによる)。
なるべく、サンプルコードをダウンロードしてご利用ください。


アプリの登録

Qtビルダーのトップページで「アプリケーションの追加」をクリック。
サイト名「レストラン03」
Name「restaurant03」
で登録。
screenshot_18.xyYwnBtbchER.jpg

ページとデータセットの作成

アプリケーション「restaurant03」の設定画面で「ページの追加」をクリック。
screenshot_19.lEsoeHYlAdoI.jpg

タイトル「料理の種類」
Name「category」
ページの種類「マスタメンテ/マルチページ」
で登録。
screenshot_20.MiHxNjWBTlAA.jpg

データセット「category」にtext型フィールドを追加。
タイトル「料理名」
Name「name」
で登録。
screenshot_21.4IMQEtE8ihcs.jpg

データセット「category」にint型フィールドを追加。
screenshot_22.YbU6wPr9trAH.jpg

タイトル「料理ID」
Name「category_id」
maxlength「4」
minlength「1」
で登録。
screenshot_23.w40rLXbpl79c.jpg

「料理名」と「料理ID」フィールドを確認し、テーブル関連設定ファイルの保存とテーブルの作成を実行。
screenshot_25.EkAvEFS40aSk.jpg

アプリの設定画面に戻って「ページの追加」。
タイトル「レストランの料理の種類」
Name「category2restaurant」
ページの種類「マスタメンテ/マルチページ」
で登録。
screenshot_26.NST7cu6r0fQR.jpg

データセット「category2restaurant」にint型フィールドを追加。
タイトル「レストランID」
Name「restaurant_id」
maxlength「4」
minlength「1」
で登録。
screenshot_27.cl65qXKpGXzQ.jpg

データセット「category2restaurant」にint型フィールドを追加。
タイトル「料理ID」
Name「category_id」
maxlength「4」
minlength「1」
で登録。
screenshot_28.uqRMpCB5zIei.jpg

「レストランID」と「料理ID」フィールドを確認し、テーブル関連設定ファイルの保存とテーブルの作成を実行。
screenshot_29.ywguFsRKlhh3.jpg

アプリ「restaurant03」のページで「トップページに機能を追加」をクリック。
screenshot_30.HZJ5ojNTSmzh.jpg

タイトル「レストラン」
Name「restaurant」
ページの種類「マスタメンテ/マルチページ」
で登録。
screenshot_31.NJPyI5YGLSfR.jpg

データセット「restaurant」にtext型フィールドを追加。
タイトル「店名」
Name「name」
で登録。
screenshot_32.BEXtYxiUm14L.jpg

データセット「restaurant」にselect_from_table型のフィールドを追加。
screenshot_36.opnyotgspqiQ.jpg

タイトル「料理の種類」
Name「category_id」
VirtualFieldをチェック
Value=>(key=>value)は以下の通り。
_TABLEの右の欄「category」
_VALUEの右の欄「category_id」
で登録。
登録が終わったら、restaurantデータセットのテーブル関連設定ファイルを保存。テーブルの作成を実行。
screenshot_51.zOV0dkienzt4.jpg

料理の種類を登録する

アプリケーション「restaurant03」を開き、右メニューの「料理の種類 追加」をクリック。
料理名「和食」、料理ID「100」で登録。
screenshot_38.MeF5uIKLTEJJ.jpg
同様に、
料理名「西洋料理」、料理ID「200」
料理名「中華料理」、料理ID「300」
で登録しておく。
screenshot_39.pDJHzCQpXM2v.jpg

レストラン登録時にレストランIDと料理IDの関係を、「category2restaurant」データセットに登録するように変更

QTフォルダの下のrestauant03フォルダ。
screenshot_40.vtn8TtiIZoGW.jpg

lib/Pages/index_classes/_base.class.phpをテキストエディタ開き修正。
screenshot_49.h2hivqyVBCqQ.jpg

「function display_record」の「return $result;」の前に以下のコードを追加。
————————————————————-
require_once ‘Pages/category2restaurant.class.php';
$category2restaurant = new category2restaurant($this->home_dir);
$category2restaurant->QuictyStatus = $this->QuictyStatus;
if($this->QuictyStatus==’INSERT’ ) {
$_POST[‘restaurant_id’] = $this->restaurant[‘id’];
$category2restaurant->display_record();
} elseif ($this->QuictyStatus==’UPDATE’ OR $this->QuictyStatus==’DELETE’) {
$_POST[‘restaurant_id’] = $_POST[‘id’];
$condition = ‘restaurant_id=’.$_POST[‘id’];
$category2restaurant->display_record($condition);
}
————————————————————-

(追加した状態)
screenshot_50.6PMRPqd69KLx.jpg

テーブルのJOINを設定

アプリケーション「restaurant03」の右メニューから「レストラン 追加」をクリック。
店名を登録し、料理の種類を選択する。
screenshot_46.vhxK0j18yfVb.jpg

登録後の一覧。「料理の種類」が表示されない。
screenshot_52.aucg2bRkknDH.jpg

確認のため、右メニューから「レストランの料理の種類 一覧」をクリック。
category2restaurantには、ちゃんとレストランIDと料理IDの組み合わせが登録されている。
screenshot_48.Hf9wLdRbDgvq.jpg

lib/Pages/indes_classes/list_options.class.phpをテキストエディタで開いて修正する。
screenshot_53.ilP4hdFPb2RJ.jpg

以下の4つのメソッドを修正する。

  • make_where_condition() 検索条件の設定
  • make_join_condition() JOINの設定
  • make_select_fields() 取得するカラム名(フィールド名)の設定
  • make_sort_condition ソート(ORDER BY)の設定

make_where_condition

————————————————————-
function make_where_condition($add_condition=”,$cond=’AND’) {
$search_system_file = $this->page->home_dir.’/etc/search_view/restaurant.sys';
if(file_exists($search_system_file)) {
$search_system = read_data_array($search_system_file);
} else {
$search_system = array(
‘keyword’=>array(‘title’=>’restaurant.name’,’url’=>’restaurant.url’), // keyword search target column
‘condition’=>array(‘id’=>’restaurant.id’,’application_id’=>’restaurant.application_id’), // id search target column
//’period’=>array(‘start_date’=>array(‘column’=>’date’,’end’=>’end_date’))
);
}
return $this->list->make_condition($search_system,$add_condition,$cond);
}
————————————————————-
↓(修正)
————————————————————-
function make_where_condition($add_condition=”,$cond=’AND’) {
$search_system = array(
‘keyword’=>array(‘title’=>’restaurant.name’,’category’=>’category.name’),
‘condition’=>array(‘category_id’=>’category.category_id’),
);
return $this->list->make_condition($search_system,$add_condition,$cond);
}

————————————————————-

make_join_condition
————————————————————-
function make_join_condition() {
//$this->list->real_count = true; // set this flag if join other table
//$joins[] = “LEFT JOIN {table_name} ON restaurant.{table_name}_id={table_name}.id”;
//$join_condition = implode(‘ ‘,$joins);
return $join_condition;
}
————————————————————-
↓(修正)
————————————————————-
function make_join_condition() {
//$this->list->real_count = true; // set this flag if join other table
$joins[] = “LEFT JOIN category2restaurant ON restaurant.id=category2restaurant.restaurant_id”;
$joins[] = “LEFT JOIN category ON category2restaurant.category_id=category.category_id”;
$join_condition = implode(‘ ‘,$joins);
return $join_condition;
}
————————————————————-

make_select_fields
————————————————————-
function make_select_fields() {
$this->select_system = array(
‘restaurant’=>’*’, // specify all column
//’restaurant’=>array(‘id’,’name’,’url’), // specify each column
//’restaurant’=>array(‘id’=>’restaurant_id’), //specify another column name
);
return $this->list->make_select_fields($this->select_system);
}
————————————————————-
↓(修正)
————————————————————-
function make_select_fields() {
$this->select_system = array(
‘restaurant’=>’*’, // specify all column
‘category’=>array(‘category_id’=>’category_id’,’name’=>’category_name’,),
);
return $this->list->make_select_fields($this->select_system);
}
————————————————————-

make_sort_condition
————————————————————-
function make_sort_condition() {
$sort_system = array(
‘default’=>’ order by id’,
// sort keys
‘columns’=>’*’, // specify all column
//’columns’=>array(‘id’,’name’,’url’), // specify each column
);
if($this->page->sort_option) {
$this->list->set_sort_option($this->page->sort_option,$this->page->order_option);
}
return $this->list->make_order($sort_system);
}
————————————————————-
↓(修正)
————————————————————-
function make_sort_condition() {
$sort_system = array(
‘default’=>’ order by restaurant_id’,
‘columns’=>array(‘id’=>’restaurant.id’,’category_id’=>’category.category_id’,),
);
if($this->page->sort_option) {
$this->list->set_sort_option($this->page->sort_option,$this->page->order_option);
}
return $this->list->make_order($sort_system);
}
————————————————————-

(修正後の画面)
screenshot_56.cBQiDbCPPdoS.jpg

一覧でJOINの結果を確認

restaurant03のトップページを開くと、今度は「料理の種類」が表示されている。
screenshot_58.l6JkRF0GKagp.jpg

詳細表示(データ別表示)にもJOINを適用

店名の前の番号をクリックし、詳細表示(データ別表示)画面を開く。
料理の種類が表示されていない。
screenshot_59.kTdcsYhsdZy2.jpg

表示用のview/info.htmlをカスタマイズして、JOINの結果を表示できるようにする。
現在インクルードしている「inbcludes/common/auto_input_form.inc」ではJOINに対応できないため、
カスタムの部品テンプレートを作成する。
「restaurant」データセットのページを開く。
screenshot_60.D6vq0WfWExc9.jpg

一番下までスクロール。
「フォーム/テーブル表示テンプレートの作成」で
「input_form.inc」にチェックを入れて、「保存」をクリック。
「input_form.inc」を保存すると「form_view.inc」も同時に作成される。
今回は、「form_view.inc」を使う。
screenshot_62.yewHsNtX9b7m.jpg

view/info.htmlを詳細表示画面専用にし、それ以外の登録、更新、削除は、edit.htmlに切り分けることにする。
screenshot_63.mQDeqvISRdDo.jpg

view/info.htmlを複製し、edit.htmlとファイル名を変える。
screenshot_65.zGJdfgtWZRr0.jpg

view/info.htmlをテキストエディタで修正。
screenshot_67.yys8c4wxMxo9.jpg

「includes/common/auto_input_form.inc」を呼び出しているところを
「includes/restaurant/form_view.inc」に変更する。
不要なコメントアウトも削除。
————————————————————-

<div id=”contents-main”>

{include file=’includes/common/auto_search_form.inc’}
{*include file=’includes/restaurant/search_form.inc’*}
{include file=’includes/common/messages.inc’}
{include file=’includes/common/auto_input_form.inc’}
{*include file=’includes/restaurant/input_form.inc’*}

</div>
————————————————————-
↓(修正)
————————————————————-

<div id=”contents-main”>

{include file=’includes/common/auto_search_form.inc’}
{*include file=’includes/restaurant/search_form.inc’*}
{include file=’includes/common/messages.inc’}
{include file=’includes/restaurant/form_view.inc’}

</div>
————————————————————-

screenshot_69.BjY2E4zDOIaN.jpg

info.htmlの表示を行う「dispatch_info()」を以下のように修正。
————————————————————-
function dispatch_info() {
$this->assign_search_form();
$result = $this->display_record();

$this->assign_form(‘input_form’,$this->form);
$this->assign_page_and_pathlist($this->W[‘restaurant’].’ ‘.$this->W[‘display’]);
return $this->display($this->current_template);
}
————————————————————-
↓(修正)
————————————————————-
function dispatch_info() {
$this->assign_search_form();
$result = $this->display_record();
$list_table = $this->list_records(‘restaurant.id=’.$_GET[‘id’]);

$this->assign_form(‘input_form’,$this->form);
$this->assign(‘restaurant_form_view’,$this->list->display_table_value($list_table));
$this->assign_page_and_pathlist($this->W[‘category’].’ ‘.$this->W[‘display’]);
return $this->display($this->current_template);
}
————————————————————-

(修正後)
screenshot_70.plDqyeue4Gag.jpg

修正後は、詳細ページでも「料理の種類」が表示された。
screenshot_71.2CsvdhdztY03.jpg

「フォーム/テーブル表示テンプレートの作成」で作成するカスタム部品テンプレートは、シンプルなSmartyのテンプレートファイルで、
複雑な条件分岐やループはないので手直ししやすい。
デザインの変更が必要な場合などはカスタム部品テンプレートで行う。

以上。

関連記事

投稿者:

ともゆき@zubapita

ともゆき@zubapita

作ったモノ 雑誌:月刊アスキー(デスク)、アスキー.PC(副編集長)、インターネットアスキー(編集長)、アスキーPCエクスプローラー(編集長) Webサイト:東京グルメ/ライブドアグルメ、映画を語ろう、本が好き 著書:「Twitter 使いこなし術」「facebook 使いこなし術」 最近は、株式会社ブックウォーカーにて、「BWインディーズ」をやってます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>