EC-CUBE2.12:「お問い合わせ管理機能」「返信機能」を追加する(「回答希望」が設定されている)

このサイトのカスタマイズ「お問い合わせに回答希望」が含まれています。
実装していない場合は、該当の箇所を削除する必要があります。

(1) 「お問い合わせ管理機能」作成のために、データベースにdtb_contactテーブルを作成する。下記SQLを実行する。

【MySQL・PostgreSQL】

CREATE TABLE dtb_contact (
contact_id serial NOT NULL,
name01 text,
name02 text,
zip01 text,
zip02 text,
pref integer,
addr01 text,
addr02 text,
tel01 text,
tel02 text,
tel03 text,
email text,
contents text,
kaitotel text,
kaitoemail text,
timezone text,
create_date timestamp,
del_flg integer DEFAULT 0,
customer_id integer,
status integer DEFAULT 0,
PRIMARY KEY (contact_id)
);

(2) 「返信機能」作成のために、データベースにdtb_contact_replyテーブルを作成する。下記SQLを実行する。

【MySQL・PostgreSQL】

CREATE TABLE dtb_contact_reply (
mail_id serial NOT NULL,
contact_id integer,
email text,
title text,
content text,
create_date timestamp,
del_flg integer DEFAULT 0,
PRIMARY KEY (mail_id)
);

(3) データベースに登録できるようにする。
■data/class/pages/contact/LC_Page_Contact.php

118行目あたり function actionメソッド内の「$this->arrForm = $objFormParam->getFormParamList();」の後に追加

// ▼データベースに登録する
$this->lfRegisterContactData();

class LC_Page_Contact extends LC_Page_Exクラス内の一番最後に追加

function lfRegisterContactData(){
$sqlval = array();//データベース登録用の配列を用意
$objQuery = new SC_Query();//データベース操作クラスをインスタンス化
//DB登録用の配列に値を代入
$sqlval['name01']      = $this->arrForm['name01']['value'];      //お名前(姓)
$sqlval['name02']      = $this->arrForm['name02']['value'];      //お名前(姓
$sqlval['email']       = $this->arrForm['email']['value'];       //メールアドレス
$sqlval['zip01']       = $this->arrForm['zip01']['value'];       //郵便番号上1
$sqlval['zip02']       = $this->arrForm['zip02']['value'];       //郵便番号下2
$sqlval['pref']        = $this->arrForm['pref']['value'];        //都道府県番号
$sqlval['addr01']      = $this->arrForm['addr01']['value'];      //住所1
$sqlval['addr02']      = $this->arrForm['addr02']['value'];      //住所2
$sqlval['tel01']       = $this->arrForm['tel01']['value'];       //お電話番号1
$sqlval['tel02']       = $this->arrForm['tel02']['value'];       //お電話番号2
$sqlval['tel03']       = $this->arrForm['tel03']['value'];       //お電話番号3
$sqlval['contents']    = $this->arrForm['contents']['value'];    //問い合わせ内容
$sqlval['kaitotel']    = $this->arrForm['kaitotel']['value'];    //回答方法(電話)
$sqlval['kaitoemail']    = $this->arrForm['kaitoemail']['value'];    //回答方法(メール)
$sqlval['timezone']    = $this->arrForm['timezone']['value'];    //ご希望の時間帯
$sqlval['create_date'] = $this->arrForm['create_date']['value']; //送信日時
if(isset($this->arrData['customer_id']) && !empty($this->arrData['customer_id'])){
// 会員番号が存在するのであれば、会員番号も登録
$sqlval['customer_id'] = $this->arrData['customer_id'];     //会員番号
}
$objQuery->insert("dtb_contact",$sqlval);//問い合わせ内容を登録
}

(4)管理画面で表示・処理するページを新規作成

 ■html/admin/customer/contact.php

<?php
/*
* This file is part of EC-CUBE
*
* Copyright(c) 2000-2011 LOCKON CO.,LTD. All Rights Reserved.
*
* http://www.lockon.co.jp/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

// {{{ requires
require_once '../require.php';
require_once CLASS_EX_REALDIR . 'page_extends/admin/customer/LC_Page_Admin_Customer_Contact_Ex.php';

// }}}
// {{{ generate page

$objPage = new LC_Page_Admin_Customer_Contact_Ex();
register_shutdown_function(array($objPage, 'destroy'));
$objPage->init();
$objPage->process();
?>

 ■html/admin/customer/contact_detail.php

<?php
/*
* This file is part of EC-CUBE
*
* Copyright(c) 2000-2011 LOCKON CO.,LTD. All Rights Reserved.
*
* http://www.lockon.co.jp/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

// {{{ requires
require_once '../require.php';
require_once CLASS_EX_REALDIR . 'page_extends/admin/customer/LC_Page_Admin_Customer_Contact_Detail_Ex.php';

// }}}
// {{{ generate page

$objPage = new LC_Page_Admin_Customer_Contact_Detail_Ex();
register_shutdown_function(array($objPage, 'destroy'));
$objPage->init();
$objPage->process();
?>

 ■data/class_extends/page_extends/admin\customer/LC_Page_Admin_Customer_Contact_Ex.php

<?php
/*
* This file is part of EC-CUBE
*
* Copyright(c) 2000-2011 LOCKON CO.,LTD. All Rights Reserved.
*
* http://www.lockon.co.jp/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

// {{{ requires
require_once CLASS_REALDIR . 'pages/admin/customer/LC_Page_Admin_Customer_Contact.php';

/**
* 顧客情報修正 のページクラス(拡張).
*
* LC_Page_Admin_Customer_Contact をカスタマイズする場合はこのクラスを編集する.
*
* @package Page
* @author LOCKON CO.,LTD.
* @version $Id: LC_Page_Admin_Customer_Contact_Ex.php 21118 2011-08-03 12:28:10Z kajiwara $
*/
class LC_Page_Admin_Customer_Contact_Ex extends LC_Page_Admin_Customer_Contact {

// }}}
// {{{ functions

/**
* Page を初期化する.
*
* @return void
*/
function init() {
parent::init();
}

/**
* Page のプロセス.
*
* @return void
*/
function process() {
parent::process();
}

/**
* デストラクタ.
*
* @return void
*/
function destroy() {
parent::destroy();
}
}
?>

 ■data/class_extends/page_extends/admin\customer/LC_Page_Admin_Customer_Contact_Detail_Ex.php

<?php
/*
* This file is part of EC-CUBE
*
* Copyright(c) 2000-2011 LOCKON CO.,LTD. All Rights Reserved.
*
* http://www.lockon.co.jp/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

// {{{ requires
require_once CLASS_REALDIR . 'pages/admin/customer/LC_Page_Admin_Customer_Contact_Detail.php';

/**
* 顧客情報修正 のページクラス(拡張).
*
* LC_Page_Admin_Customer_Contact_Detail をカスタマイズする場合はこのクラスを編集する.
*
* @package Page
* @author LOCKON CO.,LTD.
* @version $Id: LC_Page_Admin_Customer_Contact_Detail_Ex.php 21118 2011-08-03 12:28:10Z kajiwara $
*/
class LC_Page_Admin_Customer_Contact_Detail_Ex extends LC_Page_Admin_Customer_Contact_Detail {

// }}}
// {{{ functions

/**
* Page を初期化する.
*
* @return void
*/
function init() {
parent::init();
}

/**
* Page のプロセス.
*
* @return void
*/
function process() {
parent::process();
}

/**
* デストラクタ.
*
* @return void
*/
function destroy() {
parent::destroy();
}
}
?>

 ■data/class/pages/admin/customer/LC_Page_Admin_Customer_Contact.php

<?php
/*
* This file is part of EC-CUBE
*
* Copyright(c) 2000-2011 LOCKON CO.,LTD. All Rights Reserved.
*
* http://www.lockon.co.jp/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

// {{{ requires
require_once CLASS_EX_REALDIR . 'page_extends/admin/LC_Page_Admin_Ex.php';

/**
* お問い合わせ一覧 のページクラス.
*
* @package Page
* @author LOCKON CO.,LTD.
* @version $Id: LC_Page_Admin_Customer_Contact.php 21118 2011-08-03 12:28:10Z kajiwara $
*/
class LC_Page_Admin_Customer_Contact extends LC_Page_Admin_Ex {

// }}}
// {{{ functions

/**
* Page を初期化する.
*
* @return void
*/
function init() {
parent::init();//親クラスの"init"メソッドの呼び出し
$this->tpl_mainpage = 'customer/contact.tpl';//表示するtplの指定
$this->tpl_mainno = 'customer';//メニューのカテゴリの指定
$this->tpl_subnavi = 'customer/subnavi.tpl';//メニューtplの指定
$this->tpl_subno = 'contact';//自身のページの指定
$this->tpl_pager = 'pager.tpl';//ページ送りのtplの指定
$this->tpl_subtitle = '問い合わせ管理';//ページタイトルの指定

$masterData = new SC_DB_MasterData_Ex();//マスターデータ管理クラスのインスタンス化
$this->arrPageMax = $masterData->getMasterData("mtb_page_max");//ページ送り情報をマスターデータから取得
$this->arrPref = $masterData->getMasterData("mtb_pref", array("pref_id", "pref_name", "rank"));//都道府県データをマスターデータから取得
}

/**
* Page のプロセス.
*
* @return void
*/
function process() {
$this->action();
$this->sendResponse();
}

/**
* Page のアクション.
*
* @return void
*/
function action() {
// 認証可否の判定
$objSess = new SC_Session();//セッションクラスのインスタンス化
SC_Utils_Ex::sfIsSuccess($objSess);//認証に失敗していればエラーページを表示

// モードチェック
if(!isset($_POST['mode'])) {//"mode"がNULLならば
$_POST['mode'] = "";//空を入力
} elseif($_POST['mode'] == 'delete') {//"mode"が"delete"であれば
if(SC_Utils_Ex::sfIsInt($_POST['contact_id'])) {//"contact_id"が数字ならば
$objQuery = new SC_Query();//データベース操作クラスをインスタンス化
$where = "contact_id = ?";
$sqlval['del_flg'] = '1';
//"contact_id"を検索条件として、"del_flg"を"1"とするSQLを実行
$objQuery->update("dtb_contact", $sqlval, $where, array($_POST['contact_id']));
}
}

// 表示順の指定
$order = "create_date DESC";
// 読み込む列とテーブルの指定
$col = "*";
$from = "dtb_contact";
$where = "del_flg = 0";
$objQuery = new SC_Query();
// 消去状態になっていない問い合わせの件数の取得
$linemax = $objQuery->count($from, $where);
$this->tpl_linemax = $linemax;//tplで件数表示用変数

// ページ送り用
if(is_numeric($_POST['search_page_max'])) {//数字ならば
$page_max = $_POST['search_page_max'];//POSTされた値を最大表示数とする
} else {//数字でなければ
$page_max = SEARCH_PMAX;//定数"SEARCH_MAX"を最大表示数とする
}

// ページ送りの取得
$this->arrHidden['search_pageno'] =isset($_POST['search_pageno']) ? $_POST['search_pageno'] : "";
// ページ送りの情報を設定
$objNavi = new SC_PageNavi($this->arrHidden['search_pageno'],$linemax, $page_max,"fnNaviSearchPage", NAVI_PMAX);
// 開始番号行の取得
$startno = $objNavi->start_row;
// ページ数の取得
$this->arrPagenavi = $objNavi->arrPagenavi;

// 取得範囲の指定(開始行番号、行数のセット)
$objQuery->setlimitoffset($page_max, $startno);
// 表示順序
$objQuery->setorder($order);
// 検索結果の取得
$this->arrResults = $objQuery->select($col, $from, $where);
}

/**
* デストラクタ.
*
* @return void
*/
function destroy() {
parent::destroy();
}

}
?>

 ■data/class/pages/admin/customer/LC_Page_Admin_Customer_Contact_Detail.php

<?php
/*
* This file is part of EC-CUBE
*
* Copyright(c) 2000-2011 LOCKON CO.,LTD. All Rights Reserved.
*
* http://www.lockon.co.jp/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

// {{{ requires
require_once CLASS_EX_REALDIR . 'page_extends/admin/LC_Page_Admin_Ex.php';

/**
* お問い合わせ詳細 のページクラス.
*
* @package Page
* @author LOCKON CO.,LTD.
* @version $Id: LC_Page_Admin_Customer_Contact_Detail.php 21118 2011-08-03 12:28:10Z kajiwara $
*/
class LC_Page_Admin_Customer_Contact_Detail extends LC_Page_Admin_Ex {

// }}}
// {{{ functions

/**
* Page を初期化する.
*
* @return void
*/
function init() {
parent::init();
$this->tpl_mainpage = 'customer/contact_detail.tpl';
$this->tpl_mainno = 'customer';
$this->tpl_subnavi = 'customer/subnavi.tpl';
$this->tpl_subno = 'index';
$this->tpl_pager = 'pager.tpl';
$this->tpl_subtitle = 'お問い合わせ詳細';

$masterData = new SC_DB_MasterData_Ex();
//都道府県データをマスターデータから取得する。
$this->arrPref = $masterData->getMasterData("mtb_pref", array("pref_id", "pref_name", "rank"));
}

/**
* Page のプロセス.
*
* @return void
*/
function process() {
$this->action();
$this->sendResponse();
}

/**
* Page のアクション.
*
* @return void
*/
function action() {
// 認証可否の判定
$objSess = new SC_Session();
SC_Utils_Ex::sfIsSuccess($objSess);

$this->objQuery = new SC_Query_Ex();
//問合せ編集情報"contact_id"取得
//GET値→POST値の順に"contact_id"が存在するかチェックし、あれば取得
if(isset($_GET["contact_id"]) && is_numeric($_GET["contact_id"])) {
$contact_id = $_GET["contact_id"];
} elseif(isset($_POST["contact_id"]) && is_numeric($_POST["contact_id"])) {
$contact_id = $_POST["contact_id"];
}

if($contact_id) {
$sql = "SELECT * FROM dtb_contact WHERE del_flg = 0 AND contact_id = ?";
//消去状態になっていない、問合せデータ取得
$result = $this->objQuery->getAll($sql,array($contact_id));
//取得したデータの1つ目の要素を取り出す
$this->list_data = $result[0];

if($this->list_data["status"] == 0 && !isset($_POST["status"])) {//ステータスが未読("status"が"0")でステータスの変更がなければ
$this->list_data["status"] = 1;
$this->lfRegiserData(array("status"=>1),array(array("column"=>"status")));//ステータスを既読("status"が"1")に変更
} elseif($_POST["mode"] == "confirm") {
// 入力データの変換内容の指定
$arrRegisterColumn = array(array(  "column" => "status", "convert" => "n" ),
array(  "column" => "del_flg", "convert" => "n"),
);
$this->arrForm = $_POST;
$this->arrForm = $this->lfConvertParam($this->arrForm, $arrRegisterColumn);//入力データの変換
// 入力チェック
$this->arrErr = $this->lfErrorCheck($this->arrForm);
if ($this->arrErr) {// 入力エラー発生
foreach($this->arrForm as $key => $val) {
$this->list_data[ $key ] = $val;
}
} else {
$this->list_data["status"] = $this->arrForm["status"];
$this->lfRegiserData(array("status"=>$this->arrForm["status"]),array(array("column"=>"status")));//ステータスを変更
}
}
//問合せ履歴情報の取得
$this->arrContactHistory = $this->lfContactHistory($this->list_data['customer_id']);
} else {
$this->list_data = array();
}
}

/**
* デストラクタ.
*
* @return void
*/
function destroy() {
parent::destroy();
}


// 編集登録
function lfRegiserData($array, $arrRegisterColumn) {

foreach ($arrRegisterColumn as $data) {
if($array[$data["column"]] != "") {
$arrRegist[$data["column"]] = $array[$data["column"]];
} else {
unset($arrRegist[$data["column"]]);
}
}

//-- 編集登録実行
$this->objQuery->update("dtb_contact", $arrRegist, "contact_id = ?",array($this->list_data["contact_id"]));
}


//---- 取得文字列の変換
function lfConvertParam($array, $arrRegisterColumn) {
/*
*    文字列の変換
*    K :  「半角(ハンカク)片仮名」を「全角片仮名」に変換
*    C :  「全角ひら仮名」を「全角かた仮名」に変換
*    V :  濁点付きの文字を一文字に変換。"K","H"と共に使用します
*    n :  「全角」数字を「半角(ハンカク)」に変換
*  a :  全角英数字を半角英数字に変換する
*/
// カラム名とコンバート情報
foreach ($arrRegisterColumn as $data) {
$arrConvList[ $data["column"] ] = $data["convert"];
}
// 文字変換
foreach ($arrConvList as $key => $val) {
// POSTされてきた値のみ変換する。
if(strlen(($array[$key])) > 0) {
$array[$key] = mb_convert_kana($array[$key] ,$val);
}
}
return $array;
}

//---- 入力エラーチェック
function lfErrorCheck($array) {

$objErr = new SC_CheckError($array);

$objErr->doFunc(array("対応状態", 'status'), array("EXIST_CHECK"));
return $objErr->arrErr;

}

//問合せ履歴情報の取得
function lfContactHistory($customer_id){
$this->tpl_pageno = $_POST['search_pageno'];
$this->edit_customer_id = $customer_id;

// ページ送りの処理
$page_max = SEARCH_PMAX;
//問合せ履歴の件数取得
$this->tpl_linemax = $this->objQuery->count("dtb_contact","customer_id=? AND del_flg = 0 ", array($customer_id));
$linemax = $this->tpl_linemax;

// ページ送りの取得
$objNavi = new SC_PageNavi($_POST['search_pageno'], $linemax, $page_max, "fnNaviSearchPage2", NAVI_PMAX);
$this->arrPagenavi = $objNavi->arrPagenavi;
$this->arrPagenavi['mode'] = '';
$startno = $objNavi->start_row;

// 取得範囲の指定(開始行番号、行数のセット)
$this->objQuery->setlimitoffset($page_max, $startno);
// 表示順序
$order = "contact_id DESC";
$this->objQuery->setorder($order);
//問合せ履歴情報の取得
$arrContactHistory = $this->objQuery->select("*", "dtb_contact", "customer_id=? AND del_flg = 0 ", array($customer_id));
return $arrContactHistory;
}
}
?>

 ■data/Smarty/templates/admin/customer/contact.tpl

<!--{if count($arrErr) == 0}-->

<form name="form1" id="form1" method="post" action="<!--{$smarty.server.PHP_SELF|escape}-->">
<!--modeとトランザクションIDをhidden要素としてPOSTする-->
<input type="hidden" name="mode" value="search">
<input type="hidden" name="<!--{$smarty.const.TRANSACTION_ID_NAME}-->" value="<!--{$transactionid}-->" />
<input type="hidden" name="contact_id" value="">
<!--他にもPOSTする値があればhidden要素として繰り返す-->
<!--{foreach key=key item=item from=$arrHidden}-->
<input type="hidden" name="<!--{$key}-->" value="<!--{$item|escape}-->">
<!--{/foreach}-->
<h2>検索結果一覧</h2>
<p><span class="attention"><!--検索結果数--><!--{$tpl_linemax}-->件</span>&nbsp;が該当しました。</p>
<table class="list">
<!--デーブルの横幅の指定-->
<col width="10%">
<col width="10%">
<col width="20%">
<col width="15%">
<col width="15%">
<col width="15%">
<col width="10%">
<col width="5%">
<tr>
<th rowspan="2">状況</th>
<th>名前</th>
<th rowspan="2">内容</th>
<th>メールアドレス</th>
<th rowspan="2">受信日時</th>
<th rowspan="2">住所</th>
<th>回答方法</th>
<th rowspan="2">操作</th>
</tr>
<tr>
<th>会員ID</th>
<th>TEL</th>
<th>時間帯</th>
</tr>
<!--問い合わせ件数分だけ表示する-->
<!--{section name=cnt loop=$arrResults}-->
<tr>
<td rowspan="2">
<a href   = "./contact_detail.php?contact_id=<!--{$arrResults[cnt].contact_id }-->">
<!--{if $arrResults[cnt].status == 0}-->
未読
<!--{elseif $arrResults[cnt].status == 1}-->
既読
<!--{elseif $arrResults[cnt].status == 2}-->
対応中
<!--{elseif $arrResults[cnt].status == 3}-->
対応済み
<!--{/if}-->
</a>
</td>
<td><!--{$arrResults[cnt].name01}--><!--{$arrResults[cnt].name02}--></td>
<td rowspan="2"><!--{$arrResults[cnt].contents|truncate:60}--></td>
<td><!--{$arrResults[cnt].email}--></td>
<td rowspan="2"><!--{$arrResults[cnt].create_date}--></td>
<!--{assign var=pref value=$arrResults[cnt].pref}-->
<td rowspan="2">〒<!--{$arrResults[cnt].zip01}-->-<!--{$arrResults[cnt].zip02}--><br /><!--{$arrPref[$pref]}--><!--{$arrResults[cnt].addr01}--><!--{$arrResults[cnt].addr02}--></td>
<td><!--{if $arrResults[cnt].kaitotel == 1}-->電話 <!--{/if}--><!--{if $arrResults[cnt].kaitoemail == 1}-->E-Mail<!--{/if}--></td>
<td><a href = "./contact_reply.php?contact_id=<!--{$arrResults[cnt].contact_id }-->">返信</a></td>
</tr>
<tr>
<td>
<!--会員の問い合わせなら会員番号を表示する-->
<!--{if $arrResults[cnt].customer_id  != NULL && $arrResults[cnt].customer_id != "" }-->
<!--{$arrResults[cnt].customer_id}-->
<!--{else}-->
非会員
<!--{/if}-->
</td>
<td><!--{$arrResults[cnt].tel01}-->-<!--{$arrResults[cnt].tel02}-->-<!--{$arrResults[cnt].tel03}--></td>
<td><!--{if $arrResults[cnt].timezone == 1}-->午前(9:00~10:30)<!--{elseif $arrResults[cnt].timezone == 2}-->午前(10:30~12:00)<!--{elseif $arrResults[cnt].timezone == 3}-->お昼(12:00~13:00)<!--{elseif $arrResults[cnt].timezone == 4}-->午後(13:00~15:00)<!--{elseif $arrResults[cnt].timezone == 5}-->午後(15:00~17:00)<!--{elseif $arrResults[cnt].timezone == 6}-->特になし<!--{/if}--></td>
<td><a href="./contact.php?contact_id=<!--{$arrResults[cnt].contact_id}-->" onclick="fnModeSubmit('delete', 'contact_id', <!--{$arrResults[cnt].contact_id }-->);return false;"><span class="icon_delete">削除</span></a></td>
</tr>
<!--{/section}-->
</table>
<!--{include file=$tpl_pager}-->
</form>
<!--{/if}-->

 ■data/Smarty/templates/admin/customer/contact_detail.tpl

<h2>問い合わせ詳細</h2>


<form name="form2" id="form2" method="post" action="<!--{$smarty.server.PHP_SELF|escape}-->">
<!--modeとトランザクションIDと会員番号をhidden要素としてPOSTする-->
<input type="hidden" name="mode" value="confirm">
<input type="hidden" name="contact_id" value="<!--{$list_data.contact_id|escape}-->">
<input type="hidden" name="<!--{$smarty.const.TRANSACTION_ID_NAME}-->" value="<!--{$transactionid}-->" />

<table class="form">
<tr>
<th>送信日時</th>
<td colspan="3"><!--{$list_data.create_date}--></td>
</tr>
<tr>
<th>対応状況</th>
<td align = "center">
<select name="status" id="status">
<option value="1" <!--{if $list_data.status eq 1}-->selected="selected"<!--{/if}--> >既読 </option>
<option value="2" <!--{if $list_data.status eq 2}-->selected="selected"<!--{/if}--> >対応中</option>
<option value="3" <!--{if $list_data.status eq 3}-->selected="selected"<!--{/if}--> >対応済</option>
</select>
<input type="submit" alt="変更する" name="subm" value="変更する">
</td>
<th>顧客ID</th>
<td>
<!--会員の問い合わせなら会員番号を表示する-->
<!--{if $list_data.customer_id  != NULL && $list_data.customer_id != "" }-->
<!--{$list_data.customer_id}-->
<!--{else}-->
非会員
<!--{/if}-->
</td>
</tr>
<tr>
<th>お名前</th>
<td width="40%"><!--{$list_data.name01}--><!--{$list_data.name02}--></td>
<th>電話番号</th>
<td width="20%"><!--{$list_data.tel01}-->-<!--{$list_data.tel02}-->-<!--{$list_data.tel03}--></td>
</tr>
<tr>
<th>ご住所</th>
<td colspan = "3">〒<!--{$list_data.zip01}-->-<!--{$list_data.zip02}--><!--{$arrPref[$list_data.pref]}-->&nbsp;<!--{$list_data.addr01}--></td>
</tr>
<tr>
<th>メールアドレス</th>
<td colspan = "3"><!--{$list_data.email}--></td>
</tr>
<tr>
<th colspan = "4">お問い合わせ内容</th>
</tr>
<tr>
<td colspan = "4"><!--{$list_data.contents|nl2br}--></td>
</tr>
<tr>
<th>回答方法・時間帯</th>
<td colspan = "3"><!--{if $list_data.kaitotel == 1}-->電話 <!--{/if}--><!--{if $list_data.kaitoemail == 1}-->E-Mail<!--{/if}--> ・ <!--{if $list_data.timezone == 1}-->午前(9:00~10:30)<!--{elseif $list_data.timezone == 2}-->午前(10:30~12:00)<!--{elseif $list_data.timezone == 3}-->お昼(12:00~13:00)<!--{elseif $list_data.timezone == 4}-->午後(13:00~15:00)<!--{elseif $list_data.timezone == 5}-->午後(15:00~17:00)<!--{elseif $list_data.timezone == 6}-->特になし<!--{/if}--></td>
</tr>
<tr>
<td colspan = "4" align = "center">
<!--▼検索結果へ戻る-->
<a class="btn-action" href="<!--{$smarty.const.ROOT_URLPATH}--><!--{$smarty.const.ADMIN_DIR}-->customer/contact.php"><span>検索画面に戻る</span></a>
<!--▲検索結果へ戻る-->
<!--▼返信する-->
<a class="btn-action" href="<!--{$smarty.const.ROOT_URLPATH}--><!--{$smarty.const.ADMIN_DIR}-->customer/contact_reply.php?contact_id=<!--{$list_data.contact_id }-->"><span>返信する</span></a>
<!--▲返信する-->
</td>
</tr>
</table>
</form>


<h2>問い合わせ履歴一覧</h2>
<p><span class="attention"><!--検索結果数--><!--{$tpl_linemax}-->件</span>&nbsp;が該当しました。</p>
<!--{if $tpl_linemax > 0}-->
<form name="form1" id="form1" method="post" action="<!--{$smarty.server.PHP_SELF|escape}-->?contact_id=<!--{$list_data.contact_id}-->">
<!--modeと会員番号とトランザクションIDと指定したページNoをhidden要素としてPOSTする-->
<input type="hidden" name="mode" value="">
<input type="hidden" name="contact_id" value="<!--{$list_data.contact_id}-->">
<input type="hidden" name="search_pageno" value="<!--{$tpl_pageno}-->">
<input type="hidden" name="<!--{$smarty.const.TRANSACTION_ID_NAME}-->" value="<!--{$transactionid}-->" />
<!--{include file=$tpl_pager}-->
</form>
<table class="form">
<tr>
<th>日付</th>
<th>問合せ番号</th>
<th>内容</th>
<th>対応状況</th>
</tr>
<!--{section name=cnt loop=$arrContactHistory}-->
<tr>
<td><!--{$arrContactHistory[cnt].create_date|sfDispDBDate}--></td>
<td><a href="contact_detail.php?contact_id=<!--{$arrContactHistory[cnt].contact_id}-->"><!--{$arrContactHistory[cnt].contact_id}--></a></td>
<td><!--{$arrContactHistory[cnt].contents|truncate:60}--></td>
<td>
<!--{if $arrContactHistory[cnt].status eq 1}-->
既読
<!--{elseif $arrContactHistory[cnt].status eq 2}-->
対応中
<!--{elseif $arrContactHistory[cnt].status eq 3}-->
対応済
<!--{else}-->
未読
<!--{ /if }-->
</td>
</tr>
<!--{/section}-->
</table>
<!--{else}-->
<p>問合せ履歴はありません。</p>
<!--{/if}-->

(5)■data/Smarty/templates/admin/customer/subnavi.tplに追加

<!--▼お問い合わせメール管理-->
<li<!--{if $tpl_subno == 'contact'}--><!--{/if}--> id="navi-customer-contact"><a href="<!--{$smarty.const.ROOT_URLPATH}--><!--{$smarty.const.ADMIN_DIR}-->customer/contact.php"><span>お問い合わせメール管理</span></a></li>
<!--▲お問い合わせメール管理-->

(6)管理画面からお問い合わせに返信するページを作成する。

 ■html/admin/customer/contact_reply.php

<?php
// {{{ requires
require_once '../require.php';
require_once CLASS_EX_REALDIR . 'page_extends/admin/customer/LC_Page_Admin_Customer_Contact_Reply_Ex.php';

// }}}
// {{{ generate page

$objPage = new LC_Page_Admin_Customer_Contact_Reply_Ex();
register_shutdown_function(array($objPage, 'destroy'));
$objPage->init();
$objPage->process();
?>

 ■data/class_extends/page_extends/admin\customer/LC_Page_Admin_Customer_Contact_Reply_Ex.php

<?php
// {{{ requires
require_once CLASS_REALDIR . 'pages/admin/customer/LC_Page_Admin_Customer_Contact_Reply.php';

/**
* 問い合わせ返信 のページクラス(拡張).
*
* LC_Page_Admin_Customer_Contact_Reply をカスタマイズする場合はこのクラスを編集する.
*
* @package Page
* @author LOCKON CO.,LTD.
* @version $Id: LC_Page_Admin_Customer_Contact_Reply_Ex.php 21118 2011-08-03 12:28:10Z kajiwara $
*/
class LC_Page_Admin_Customer_Contact_Reply_Ex extends LC_Page_Admin_Customer_Contact_Reply {

// }}}
// {{{ functions

/**
* Page を初期化する.
*
* @return void
*/
function init() {
parent::init();
}

/**
* Page のプロセス.
*
* @return void
*/
function process() {
parent::process();
}

/**
* デストラクタ.
*
* @return void
*/
function destroy() {
parent::destroy();
}
}
?>

 ■data/class/pages/admin/customer/LC_Page_Admin_Customer_Contact_Reply.php

<?php
// {{{ requires
require_once CLASS_EX_REALDIR . 'page_extends/admin/LC_Page_Admin_Ex.php';

/**
* お問い合わせ返信のページクラス.
*/
class LC_Page_Admin_Customer_Contact_Reply extends LC_Page_Admin_Ex {

// }}}
// {{{ functions

/**
* Page を初期化する.
*
* @return void
*/
function init() {
parent::init();
$this->tpl_mainpage = 'customer/contact_reply.tpl';
$this->tpl_mainno = 'customer';
$this->tpl_subnavi = 'customer/subnavi.tpl';
$this->tpl_subno = 'index';
$this->tpl_subtitle = 'お問い合わせ返信';

$masterData = new SC_DB_MasterData_Ex();
$this->arrMailTemplate = $masterData->getMasterData("mtb_mail_template");
}

/**
* Page のプロセス.
*
* @return void
*/
function process() {
$this->action();
$this->sendResponse();
}

/**
* Page のアクション.
*
* @return void
*/
function action() {

// 認証判定
$objSess = new SC_Session();
SC_Utils_Ex::sfIsSuccess($objSess);

// contact_idの取得
//GET値に"contact_id"があり、数字であるならば
if(isset($_GET['contact_id']) && SC_Utils_Ex::sfIsInt($_GET['contact_id'])) {
//tpl用に値を格納
$this->contact_id = $_GET['contact_id'];
} elseif(isset($_POST['contact_id']) && SC_Utils_Ex::sfIsInt($_POST['contact_id'])) {
//POST値に"contact_id"があり、数字であるならば
//tpl用に値を格納
$this->contact_id = $_POST['contact_id'];
}

$objQuery = new SC_Query();

// 取得した"contact_id"と一致するお問合せ内容の取得
$this->contact_data = $objQuery->select("*", "dtb_contact", "contact_id=?", array($this->contact_id));

// modeの判定
if(isset($_POST['mode'])) {
//モードが"send"ならば
if($_POST['mode']=="send") {
//POST値を格納
$this->arrForm = $_POST;

// 入力値のチェック
// 文字列変換
/*
*  文字列の変換
*  K :  「半角(ハンカク)片仮名」を「全角片仮名」に変換
*  C :  「全角ひら仮名」を「全角かた仮名」に変換
*  V :  濁点付きの文字を一文字に変換。"K","H"と共に使用します
*  n :  「全角」数字を「半角(ハンカク)」に変換
*  a :  「全角」英数字を「半角」に
*/
//入力の変換方法を指定
$arrConvList['contact_id'] = "n";
$arrConvList['title']      = "KV";
$arrConvList['content']    = "KV";
foreach ($arrConvList as $key => $val) {
//指定した方法で文字列を変換
$this->arrForm[$key] = mb_convert_kana($this->arrForm[$key] ,$val);
}
// 値チェック
// 値が存在しているか、最大文字数を超えていないかチェック
$objErr = new SC_CheckError($this->arrForm);
$objErr->doFunc(array("タイトル", 'title', STEXT_LEN), array("EXIST_CHECK", "MAX_LENGTH_CHECK"));
$objErr->doFunc(array("本文", 'content', LTEXT_LEN), array("EXIST_CHECK", "MAX_LENGTH_CHECK"));
$this->arrErr = $objErr->arrErr;
if(!$this->arrErr) {
//エラーがないならば
// メール送信
$objDB = new SC_Helper_DB();
// $objSiteInfo["email01"]:"商品注文受付メールアドレス"
// $objSiteInfo["email02"]:"問い合わせ受付メールアドレス"
// $objSiteInfo["email03"]:"メール送信元メールアドレス"
// $objSiteInfo["email04"]:"送信エラー受付メールアドレス"
//店舗基本情報を取得
$arrInfo = $objDB->sfGetBasisData();
$objSendMail = new SC_SendMail_Ex();
//送信メールの準備
$to          = $this->contact_data[0]['email'];//送信相手のアドレス
$subject     = $_POST['title'];//タイトル
$body        = $_POST['content'];//本文
$fromaddress = $arrInfo['email03'];//送信者のアドレス
$from_name   = $arrInfo['shop_name'];//店名
$reply_to    = $arrInfo['email02'];//送信メールの返信先のアドレス
$return_path = $arrInfo['email04'];//エラーメールの送信先のアドレス
$errors_to   = $arrInfo['email04'];//エラーメールの送信先のアドレス
$bcc         = $arrInfo['email02'];//bccの送信アドレス
//値をセット
$objSendMail->setItem($to, $subject, $body, $fromaddress, $from_name, $reply_to, $return_path, $errors_to, $bcc);//
//宛先をセット
$objSendMail->setTo($to, $this->contact_data[0]["name01"] . $this->contact_data[0]["name02"] . " 様");//
//メールを送信
$objSendMail->sendMail();//

// データベースにメールを登録するための配列
$sqlval['contact_id']  = $this->contact_id;//返信元のメールID
$sqlval['email']       = $this->contact_data[0]['email'];//送信相手のアドレス
$sqlval['title']       = $_POST['title'];//タイトル
$sqlval['content']     = $_POST['content'];//本文
$sqlval['create_date'] = 'NOW()';//送信日時
$objQuery->begin();
$objQuery->insert("dtb_contact_reply", $sqlval);//メールの登録
$objQuery->commit();
}
} elseif($_POST['mode']=="template" && SC_Utils_Ex::sfIsInt($_POST['template_id'])) {
//"mode"変数が"template"であり、"template_id"が数字ならば
$this->mailTemplateId = $_POST['template_id'];
}
}

// メールテンプレート内容取得
$objQuery->setOrder();
//"template_id"と一致するメールテンプレートを取得
$this->mail_template = $objQuery->select("subject, header, footer", "dtb_mailtemplate", "template_id=?", array($this->mailTemplateId));

// GETから(初めてのページ表示時)またはテンプレート変更時は$arrFormと$arrErrを用意
if(isset($_GET['contact_id']) || $_POST['mode']=="template") {
$this->arrForm['title']   = $this->mail_template[0]['subject'];//タイトル
$this->arrForm['content'] = $this->contact_data[0]['name01'] . $this->contact_data[0]['name02'] . '様' . $this->mail_template[0]['header'] . '' . $this->mail_template[0]['footer'];//本文
$this->arrErr['title'] = '';//エラーなし
$this->arrErr['content'] = '';//エラーなし
}

// 返信一覧の取得
//送信日時が近い順
$objQuery->setorder("create_date DESC");
//"contact_id"と一致する返信メールを取得
$this->arrReply = $objQuery->select("*", "dtb_contact_reply", "contact_id = ?", array($this->contact_id));
//返信メールの数を取得
$this->replyCount = $objQuery->count("dtb_contact_reply","contact_id = ?",array($this->contact_id));
}

/**
* デストラクタ.
*
* @return void
*/
function destroy() {
parent::destroy();
}

}
?>

 ■data/Smarty/templates/admin/customer/contact_reply.tpl

<script type="text/javascript">
function confirm_send() {
res = confirm('この内容で送信しますか?');
if(res) {
document.form1.mode.value = 'send';
document.form1.submit();
}
return false;
}
</script>

<h2>返信内容</h2>
<form name="form1" id="form1" method="post" action="<!--{$smarty.server.PHP_SELF|escape}-->">
<input type="hidden" name="mode" value="">
<input type="hidden" name="<!--{$smarty.const.TRANSACTION_ID_NAME}-->" value="<!--{$transactionid}-->" />
<input type="hidden" name="contact_id" value="<!--{$contact_id}-->">
<table class="form">
<tr>
<th>テンプレート</th>
<td>
<select name="template_id" onChange="return fnSetvalAndSubmit('form1', 'mode', 'template');">
<!--{foreach from=$arrMailTemplate key="key" item="value"}-->
<option value="<!--{$key}-->" <!--{if $key==$mailTemplateId}-->selected<!--{/if}-->><!--{$value|escape}-->
<!--{/foreach}-->
</td>
</tr>
<tr>
<th>宛先</th>
<td><!--{$contact_data[0].email|escape}--></td>
</tr>
<tr>
<th>タイトル</th>
<td><input type="text" name="title" value="<!--{$arrForm.title|escape}-->" size="<!--{$smarty.const.STEXT_LEN}-->" maxlength="<!--{$smarty.const.STEXT_LEN}-->"><!--{$arrErr.title}--></td>
</tr>
<tr>
<th>本文</th>
<td><!--{$arrErr.content}--><textarea name="content" cols="72" rows="10"><!--{$arrForm.content|escape}--></textarea></td>
</tr>
<tr>
<th>お名前</th>
<td><!--{$contact_data[0].name01|escape}--><!--{$contact_data[0].name02|escape}--> 様</td>
</tr>
<tr>
<th>お問い合わせ内容</th>
<td><!--{$contact_data[0].contents|escape|nl2br}--></td>
</tr>
<tr>
<th colspan="2" align="center"><input type="button" name="send" value="送信する" onclick="return confirm_send();"></th>
</tr>
</table>
</form>
<!--{if $replyCount > 0}-->
<h2>送信履歴</h2>
<!--{foreach from=$arrReply key="key" item="value"}-->
<table class="list">
<tr>
<th>送信日時</th>
<td><!--{$value.create_date|sfDispDBDate}--></td>
</tr>
<tr>
<th>タイトル</th>
<td><!--{$value.title|escape}--></td>
</tr>
<tr>
<th style="background-color:#F4F5F5;">本文</th>
<td><!--{$value.content|escape|nl2br}--></td>
</tr>
</table>
<!--{/foreach}-->
<!--{/if}-->