User:
Pass:
Keep:   
Xoops Cube Project
XOOPS Cube Project Site
Powered by Google


Powered by XOOPS Cube Legacy 2.1.8
PukiWikiMod 1.5.1
WordPress Module 0.6.0 Alpha
Counter: 12072, today: 1, yesterday: 1

XOOPS用汎用TebleObject

XOOPSでは、モジュールでのDBのハンドリングのために、XoopsObjectとXoopsObjectHandlerというひな形となるクラスが用意されているけど、結局はXoopsObjectHandlerの派生クラスにてSQL文を生成するロジックを書いてやらないといけない。
ということで、試しに汎用的なTable操作を可能にしたXoopsTableObject及びXoopsTableObjectHandlerクラスというのを試作してテーブルによる、アクセスを簡便化してみた。
これを使うと、たとえば id,name,telnumという項目を持つ、modsample0_table1というテーブルに対して、

<?php
include_once XOOPS_ROOT_PATH."/util/xoopstableobject.php";

/**
 * サンプルテーブルオブジェクト
 * 
 * @copyright copyright (c) 2000-2003 Kowa.ORG
 * @author Nobuki Kowa <[email protected]> 
 * @package ModSample0l
 */
class ModSample0Table1  extends XoopsTableObject
{
    /**
     * コンストラクタ
     */
    function ModSample0Table1()
    {
    ////////////////////////////////////////
    // 各クラス共通部分(書換不要)
    ////////////////////////////////////////
        
        //親クラスのコンストラクタ呼出
        $this->XoopsTableObject();

    ////////////////////////////////////////
    // 派生クラス固有の定義部分
    ////////////////////////////////////////

        //各オブジェクト要素の定義
        $this->initVar('id', XOBJ_DTYPE_INT, NULL, false);
        $this->initVar('name', XOBJ_DTYPE_TXTBOX, NULL, true, 20);
        $this->initVar('telnum', XOBJ_DTYPE_TXTBOX, NULL, false,13);

        //プライマリーキーの定義
        $this->setKeyFields(array('id'));

        //AUTO_INCREMENT属性のフィールド定義
        // - 一つのテーブル内には、AUTO_INCREMENT属性を持つフィールドは
        //   一つしかない前提です。
        $this->setAutoIncrementField('id');

        $this->assignEditFormElement('id','Hidden', array('id',0));
        $this->assignEditFormElement('name','Text',array('名前','name',20,20));
        $this->assignEditFormElement('telnum','Text',array('電話番号','telnum',15,13));
        
        $this->assignListTableElement('name','Link','名前');
        $this->assignListTableElement('telnum','Text','電話番号');
    }
}

/**
 * サンプルテーブルハンドラオブジェクト
 * 
 * @copyright copyright (c) 2000-2003 Kowa.ORG
 * @author Nobuki Kowa <[email protected]> 
 * @package ModSample0l
 */
class ModSample0Table1Handler  extends XoopsTableObjectHandler
{
    /**
     * コンストラクタ
     */
    function ModSample0Table1Handler($db)
    {
    ////////////////////////////////////////
    // 各クラス共通部分(書換不要)
    ////////////////////////////////////////

        //親クラスのコンストラクタ呼出
        $this->XoopsTableObjectHandler($db);
        
    ////////////////////////////////////////
    // 派生クラス固有の定義部分
    ////////////////////////////////////////

        //ハンドラの対象テーブル名定義
        $this->tableName = $this->db->prefix('modsample0_table1');

        //関連クラス名称を小文字で定義
        // - 標準のネーミングに準拠している場合には設定不要
//      $this->objectClassName = 'modsample0table1';
    }
    
    /**
     * レコードの取得(プライマリーキーによる一意検索)
     * 
     * @param   string $key 検索キー
     *
     * @return  object  {@link ModSample0Table1}, FALSE on fail
     */
/*テーブルに固有の処理が必要な時以外は不要
    function &get($key)
    {
        return parent::get($key);
    }
*/

    /**
     * レコードの保存
     * 
     * @param   object  &$record    {@link ModSample0Table1} object
     * @param   bool    $force      POSTメソッド以外で強制更新する場合はture
     * 
     * @return  bool    成功の時は TRUE
     */
/*テーブルに固有のデータ処理が必要な時以外は不要
    function insert(&$record,$force=false)
    {
        return parent::insert($record,$force);
    }
*/

    /**
     * レコードの削除
     * 
     * @param   object  &$record  {@link ModSample0Table1} object
     * @param   bool    $force      POSTメソッド以外で強制更新する場合はture
     * 
     * @return  bool    成功の時は TRUE
     */
/*テーブルに固有のデータ処理が必要な時以外は不要
    function delete(&$record,$force=false)
    {
        return parent::delete($record,$force);
    }
*/
    /**
     * テーブルの条件検索による複数レコード取得
     * 
     * @param   object  $criteria   {@link CriteriaElement} 検索条件
     * @param   bool $id_as_key     プライマリーキーを、戻り配列のキーにする場合はtrue
     * @return  mixed Array         検索結果レコードの配列
     */
/*テーブルに固有のデータ処理が必要な時以外は不要
    function &getObjects($criteria = null, $id_as_key = false)
    {
        return parent::getObjects($criteria, $id_as_key);
    }
*/
}
?>
というコードを書くだけで、基本的なDBアクセスが可能になって、
このクラスを使って、たとえば、モジュールのindex.phpに
<?PHP
    global $xoopsDB;
    // XOOPSの環境設定ファイルの読込
    require( '../../mainfile.php' ) ;

    // 使用するSmartyテンプレートの宣言
    
    // XOOPSの共通ヘッダー部分の描画
    include( XOOPS_ROOT_PATH.'/header.php' ) ;
    include_once XOOPS_ROOT_PATH.'/modules/ModSample0/class/ModSample0_Table1.php';
    
    //実際のデータ処理を記述します。
    $handler = new ModSample0Table1Handler($xoopsDB);
    $op = array_key_exists('op',$_POST) ? $_POST['op'] : ( array_key_exists('op',$_GET) ? $_GET['op'] :'');

    switch ($op) {
        case 'insert':
            $record =& $handler->create();
            $record->setFormVars($_POST,'');
            $handler->insert($record,true);
            redirect_header("",1,$title);
            exit();
            break;
        case 'save':
            $record =& $handler->create();
            $record->setFormVars($_POST,'');
            $record->unsetNew();
            $handler->insert($record,true);
            redirect_header("",1,$title);
            exit();
            break;
        case 'edit':
            $xoopsOption['template_main']= 'ModSample0_main.html';
            $record =& $handler->get($_GET);
            $body = $record->renderEditForm("登録","edit",XOOPS_URL."/modules/ModSample0/index.php");
            $xoopsTpl->assign('body', $body);
            break;  
        default :
            $xoopsOption['template_main']= 'ModSample0_list.html';
            $new_record =& $handler->create();
            $insertform = $new_record->renderEditForm("新規登録","insert",XOOPS_URL."/modules/ModSample0/index.php");

            $criteria = new CriteriaElement();
            $criteria->setSort('name');
            $criteria->setStart(1);
            $criteria->setLimit(10);
    
            $recordobjs =& $handler->getObjects($criteria);
            foreach ($recordobjs as $record) {
                foreach($record->getvars() as $k=>$v) {
                    $rec[$k]=$record->getVar($k);
                }
                $records[] = $rec;
            }
            $xoopsTpl->assign('insertform', $insertform);
            $xoopsTpl->assign('lang_list_title','一覧');
            $xoopsTpl->assign('lang_name','氏名');
            $xoopsTpl->assign('lang_telnum','電話番号');
            $xoopsTpl->assign('records', $records);
    
    }
    
    // XOOPSの共通フッター部分の描画
    include( XOOPS_ROOT_PATH.'/footer.php' ) ;
?>
と定義する事によって、レコードの新規登録、一覧表示、編集機能を実現できるようになる。
とりあえず現状出来ている暫定的な、XoopsTableObject クラスは以下のようなものである。
<?php
include_once XOOPS_ROOT_PATH."/class/xoopsobject.php";

/**
 * 汎用テーブル操作XoopsObject
 * 
 * @copyright copyright (c) 2000-2003 Kowa.ORG
 * @author Nobuki Kowa <[email protected]> 
 * @package ModSample0l
 */
class XoopsTableObject  extends XoopsObject
{
    var $_keys;
    var $_autoIncrement;
    var $_formElements;
    var $_listTableElements;
    
    function XoopsTableObject()
    {
        //親クラスのコンストラクタ呼出
        $this->XoopsObject();
    }

    function setKeyFields($keys)
    {
        $this->_keys = $keys;
    }
    
    function getKeyFields()
    {
        return $this->_keys;
    }
    
    function isKey($field)
    {
        return in_array($field,$this->_keys);
    }
    //AUTO_INCREMENT属性のフィールドはテーブルに一つしかない前提
    function setAutoIncrementField($fieldName)
    {
        $this->_autoIncrement = $fieldName;
    }
    
    function &getAutoIncrementField()
    {
        return $this->_autoIncrement;
    }

    function isAutoIncrement($fieldName)
    {
        return ($fieldName == $this->_autoIncrement);
    }
    
    function resetChenged()
    {
        foreach($this->vars as $k=>$v) {
            $this->vars[$k]['changed'] = false;
        }
    }
    
    function assignEditFormElement($name,$class,$params)
    {
        include_once XOOPS_ROOT_PATH.'/class/xoopsform/formelement.php';
        include_once XOOPS_ROOT_PATH.'/class/xoopsform/form'. strtolower($class) .'.php';
        $className = "XoopsForm". $class;
        $callstr = '$this->_formElements["'.$name.'"] = new XoopsForm'.$class.'(';
        $delim = '';
        for ($i=0;$i<count($params);$i++) {
            if (gettype($params[$i]) == "string") {
                $callstr .= $delim. '"'. $params[$i].'"';
            } else {
                $callstr .= $delim. $params[$i];
            }
            $delim = ', ';
        }
        $callstr .= ');';
//      echo "$callstr<br>";
        eval($callstr);
    }
    
    function renderEditForm($caption,$name,$action)
    {
        include_once XOOPS_ROOT_PATH.'/class/xoopsform/form.php';
        include_once XOOPS_ROOT_PATH.'/class/xoopsform/themeform.php';
        include_once XOOPS_ROOT_PATH.'/class/xoopsform/formhidden.php';
        include_once XOOPS_ROOT_PATH.'/class/xoopsform/formbutton.php';
        
        $formEdit =& new XoopsThemeForm($caption,$name,$action);
        foreach ($this->_formElements as $key=>$formElement) {
            if (!$this->isNew()) {
                $formElement->setValue($this->getVar($key));
            }
            $formEdit->addElement(&$formElement,$this->vars[$key]['required']);
//          echo "$key - " .get_class($formElement) ."<br/>";
            unset($formElement);
        }
        
        if ($this->isNew()) {
            $formEdit->addElement(new XoopsFormHidden('op','insert'));
        } else {
            $formEdit->addElement(new XoopsFormHidden('op','save'));
        }
        $formEdit->addElement(new XoopsFormButton('', 'submit', 'OK', 'submit'));

        $str = $formEdit->render();
        unset($formEdit);
        return $str;
    }

    function assignListTableElement($name,$type, $caption) {
        $_listTableElements[$name]['type'] = $type;
        $_listTableElements[$name]['caption'] = $caption;
    }
}

class XoopsTableObjectHandler  extends XoopsObjectHandler
{
    var $tableName;
    var $entityClassName;
    var $keyClassName;
    
    function XoopsTableObjectHandler($db)
    {
        $this->entityClassName = preg_replace("/handler/","", get_class($this));
        $this->keyClassName = $this->entityClassName .'key';
        $this->XoopsObjectHandler($db);
    }
    
    function &create($isNew = true)
    {
        $perm = new $this->entityClassName;
        if ($isNew) {
            $perm->setNew();
        }
        return $perm;
    }

    /**
     * レコードの取得(プライマリーキーによる一意検索)
     * 
     * @param   mixed $key 検索キー
     * 
     * @return  object  {@link XoopsTableObject}, FALSE on fail
     */
    function &get($keys)
    {
        $record =  new $this->entityClassName;
        $recordKeys = $record->getKeyFields();
        $recordVars = $record->getVars();
        if (gettype($keys) != 'array') {
            if (count($recordKeys) == 1) {
                $keys = array($recordKeys[0] => $keys);
            }
        }
        $whereStr = "";
        $whereAnd = "";
        foreach ($record->getKeyFields() as $k => $v) {
            if (array_key_exists($v, $keys)) {
                $whereStr = $whereAnd . "`$v` = ";
                if ($recordVars[$v]['data_type'] == XOBJ_DTYPE_INT) {
                    $whereStr .= $keys[$v];
                } else {
                    $whereStr .= $this->db->quoteString($keys[$v]);
                }
                $whereAnd = " AND ";
            } else {
                return false;
            }
        }
        $sql = sprintf("SELECT * FROM %s WHERE %s",$this->tableName, $whereStr);
//      echo $sql."<br/>";

        if ( !$result = $this->db->query($sql) ) {
            return false;
        }
        $numrows = $this->db->getRowsNum($result);
        if ( $numrows == 1 ) {
            $record->assignVars($this->db->fetchArray($result));
            return $record;
        }
        unset($record);
        return false;
    }
    /**
     * Store a {@link XoopsTableObject} 
     * 
     * @param   object  &$record  {@link XoopsTableObject} object
     * 
     * @return  bool    TRUE on success
     */
    function insert(&$record,$force=false,$updateOnlyChanged=false)
    {
        if ( get_class($record) != $this->entityClassName ) {
            return false;
        }
        if ( !$record->isDirty() ) {
            return true;
        }
        if (!$record->cleanVars()) {
            return false;
        }
        $vars = $record->getVars();
        if ($record->isNew()) {
            $fieldList = "(";
            $valueList = "(";
            $delim = "";
            foreach ($record->cleanVars as $k => $v) {
                $fieldList .= $delim ."`$k`";
                if ($record->isAutoIncrement($k)) {
                    $v = $this->getAutoIncrementValue();
                }
                if ($vars[$k]['data_type'] == XOBJ_DTYPE_INT) {
                    $valueList .= $delim . $v;
                } else {
                    $valueList .= $delim . $this->db->quoteString($v);
                }
                $delim = ", ";
            }
            $fieldList .= ")";
            $valueList .= ")";
            $sql = sprintf("INSERT INTO %s %s VALUES %s", $this->tableName,$fieldList,$valueList);
        } else {
            $setList = "";
            $setDelim = "";
            $whereList = "";
            $whereDelim = "";
            foreach ($record->cleanVars as $k => $v) {
                if ($vars[$k]['data_type'] == XOBJ_DTYPE_INT) {
                    $value = $v;
                } else {
                    $value = $this->db->quoteString($v);
                }
                if ($record->isKey($k)) {
                    $whereList .= $whereDelim . "`$k` = ". $value;
                    $whereDelim = " AND ";
                } else {
                    if ($updateOnlyChanged && !$vars[$k]['changed']) {
                        continue;
                    }
                    $setList .= $setDelim . "`$k` = ". $value . " ";
                    $setDelim = ", ";
                }
            }
            $sql = sprintf("UPDATE %s SET %s WHERE %s", $this->tableName, $setList, $whereList);
        }
//      echo $sql."<br/>";
        if ($force) {
            if (!$result = $this->db->queryF($sql)) {
                return false;
            }
        } else {
            if (!$result = $this->db->query($sql)) {
                return false;
            }
        }
        $idField=$record->getAutoIncrementField();
        if (empty($$idField)) {
            $$idField = $this->db->getInsertId();
        }
        $record->assignVar($idField,$$idField);
        $record->resetChenged();
        return true;
    }

    /**
     * Delete a {@link ModSample0Table1} 
     * 
     * @param   object  &$modsample0table1  
     * 
     * @return  bool    TRUE on success
     */
    function delete(&$record,$force=false)
    {
        if ( get_class($record) != $this->entityClassName ) {
            return false;
        }
        $vars = $record->getVars();
        $whereList = "";
        $whereDelim = "";
        foreach ($record->cleanVars as $k => $v) {
            if ($record->isKey($k)) {
                if ($vars[$k]['data_type'] == XOBJ_DTYPE_INT) {
                    $value = $v;
                } else {
                    $value = $this->db->quoteString($v);
                }
                $whereList .= $whereDelim . "`$k` = ". $value;
                $whereDelim = " AND ";
            }
        }
        $sql = sprintf("DELETE FROM %s WHERE %s", $this->tableName, $whereList);
        if ($force) {
            if (!$result = $this->db->queryF($sql)) {
                return false;
            }
        } else {
            if (!$result = $this->db->query($sql)) {
                return false;
            }
        }
        return true;
    }

    /**
     * retrieve groups from the database
     * 
     * @param object $criteria {@link CriteriaElement} with conditions for the groups
     * @param bool $id_as_key should the groups' IDs be used as keys for the associative array?
     * @return mixed Array of groups
     */
    function &getObjects($criteria = null, $id_as_key = false)
    {
        $ret = array();
        $limit = $start = 0;
        $sql = 'SELECT * FROM '.$this->tableName;
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
            $sql .= ' '.$criteria->renderWhere();
        }
        if (isset($criteria) && (is_subclass_of($criteria, 'criteriaelement')||get_class($criteria)=='criteriaelement')) {
            if ($criteria->getSort() != '') {
                $sql .= ' ORDER BY '.$criteria->getSort().' '.$criteria->getOrder();
            }
            $limit = $criteria->getLimit();
            $start = $criteria->getStart();
        }
//      echo $sql."<br />";
        $result = $this->db->query($sql, $limit, $start);
        if (!$result) {
            return $ret;
        }
        while ($myrow = $this->db->fetchArray($result)) {
            $record = new $this->entityClassName;
            $record->assignVars($myrow);
            if (!$id_as_key) {
                $records[] =& $record;
            } else {
                $id =$record->getIdKeyField();
                if ($id) {
                    $records[$myrow[$id]] =& $record;
                }
            }
            unset($record);
        }
        return $records;
    }

    function getAutoIncrementValue()
    {
        return $this->db->genId(get_class($this).'_id_seq');
    }

}
?>
なんかのヒントになるかなぁ?


コメント

  • 参考の為にModSample0を添付しておきます。 -- nobunobu 2004-07-29 (木) 13:44:37
  • 先日メールで問い合わさせて頂いたものです。試験モジュールでも見れるようにして頂いてありがとうございます。構造がようやく飲み込めてきました。ありがとうございました。 -- taraki 2004-08-12 (木) 07:14:49


添付ファイル: fileModSample0.lzh 2236件 [詳細]

ページコメント
投稿された内容の著作権はコメントの投稿者に帰属します。

トラックバック [ トラックバック(1) ]
トラックバック URL: http://www.kowa.org/modules/pukiwiki/tb/280
XOOPS用汎用TebleObject
要約: XOOPS用汎用TebleObject (のぶのぶXOOPS) 汎用的なテーブル操作のコード付きのXoopsObjectとXoopsObjectHandlerといったところでしょうか。 私も毎度毎度同じようなコードを書くのは無駄だなぁと思って、汎用的なコードを書こうとしたことがあったんですが、あれこれ欲張りすぎてわけわからんものになってしまい、途中で放り出したことがあります(^^; このぐらいシンプルな方が使い勝手良さそうです
Weblog: XOOPS MEMO
日時: 2004年5月11日 15:58:41