質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.48%

  • PHP

    20834questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

ショッピングサイトをつくっていて、クラスを別に分けたいのですが、分け方がわかりません。

受付中

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 976

KazumuneKori

score 1

データベースに接続するコネクトの部分を別クラスに分けたいのですが、方法につまっています。
分けたクラスには別の名前をつけて、読み込みもしたいです。

分かる方おしえてください。

class PDODatabase{

        private  $dbh     = NULL;
        private  $db_host = "";
        private  $db_user = "";
        private  $db_pass = "";
        private  $db_name = "";
        private  $db_type = "";

        private  $order   = '';
        private  $limit   = '';
        private  $offset  = '';
        private  $groupby = '';

        public function __construct( $db_host, $db_user, $db_pass, $db_name, $db_type )
        {
            $this->dbh     = $this->connectDB( $db_host, $db_user, $db_pass, $db_name, $db_type );
            $this->db_host = $db_host;
            $this->db_user = $db_user;
            $this->db_pass = $db_pass;
            $this->db_name = $db_name;

            //SQL関連
            $this->order   = '';
            $this->limit   = '';
            $this->offset  = '';
            $this->groupby = '';
        }

    private function connectDB( $db_host, $db_user, $db_pass, $db_name, $db_type)
    {
        try{
            switch( $db_type)
            {
            case'mysql':
                $dsn = 'mysql:host='.$db_host.';dbname='.$db_name;
                $dbh = new PDO($dsn,$db_user,$db_pass);
                $dbh->query('SET NAMES utf8');
                break;

                case'pgsql';
                $dsn = 'pgsql:dbname='.$db_name.'host='.$db_host.'port=5432';
                $dbh = new PDO($dsn,$db_user,$db_pass);
                break;
            }
        }
        catch(PDOException $e)
        {
            var_dump($e->getMessage());
            exit;

        }
        return $dbh;
    }
 ----------------------------------------------------------------------------------------------
★★ここから上を別のクラスに分けたい★★

//thisの部分を新しい変数名に変える

        public function setQuery( $query='', $arrVal = array() )
        {
            $stmt = $this->dbh->prepare($query);   //変えた
            $stmt->execute($arrVal);

        }

        public function select( $table, $column ='',$where = '', $arrVal = array())
        {
            $sql = $this->getSql( 'select', $table, $where, $column);

            $stmt = $this->dbh->prepare($sql); //変えた
            $stmt->execute($arrVal);

            //データを連想配列に格納
            $data = array();
            while($result = $stmt->fetch(PDO::FETCH_ASSOC))
            {
                array_push($data , $result);
            }

            return $data;
        }

        public function count( $table, $where='', $arrVal=array())
        {
            $sql = $this->getSql('count',$table, $where );
            $stmt = $this->dbh->prepare($sql);    //変えた

            $stmt->execute($arrVal);

            $result = $stmt->fetch(PDO::FETCH_ASSOC);

            return intval($result['NUM']);
        }

        public function setOrder( $order ='' )
        {
            if( $strOrder !== '' ) $this->order = ' OREDER BY ' . $strOrder;
        }

        public function setLimitOff( $limit ='', $offset ='' )
        {
            if( $limit !== "" )  $this->limit = " LIMIT " . $limit ;

            if( $offset !== "" )  $this->offset = " OFFSET ". $offset ;

        }

        public function setGroupBy( $groupby )
        {
            if( $groupby !== "" ) $this->groupby = ' GROUP BY ' . $groupby;
        }

        private function getSql( $type,$table,$where='',$column='')
        {

            switch( $type )
            {
            case 'select':
                $columnKey =( $column !=='') ? $column : "*" ; 
                break;

            case 'count':
                $columnKey = 'COUNT(*) AS NUM ';
                break;

            default:
                break;
            }

            $whereSQL = ( $where !== '' )?' WHERE  ' . $where :'';

            $other = $this->groupby . "  " . $this->order ."  " . $this->limit . "  " . $this->offset;

            //sql文の作成
            $sql = " SELECT "
                 .      $columnKey 
                 . " FROM "
                 .      $table
                 .      $whereSQL
                 .      $other;

            return $sql;
        } 

        public function insert($table, $insData=array() )
        {

            list( $preSt, $insDataVal, $columns) = $this->getPreparedStatement( 'insert', $insData, $table );

            $sql = " INSERT INTO " . $table . " (" 
                 .      $columns 
                 . ") VALUES (" 
                 .      $preSt 
                 . ") " ;

            $stmt = $this->dbh->prepare( $sql );  //変えた
            $res  = $stmt->execute($insDataVal);

            return $res;
        }

        public function update($table ,$insData = array() ,$where, $arrWhereVal=array())
        {
            list( $preSt, $insDataVal) = $this->getPreparedStatement( 'update', $insData, $table );

            //sql文の作成
            $sql = " UPDATE "
                 .      $table
                 . " SET "
                 .      $preSt
                 . " WHERE "
                 .      $where ;

            $updateData = array_merge($insDataVal,$arrWhereVal);
            $stmt       = $Data->dbh->prepare( $sql );
            $res        = $stmt->execute($updateData);

            return $res ;
        }

        public function getPreparedStatement( $mode, $insData, $table )
        {

            if( !empty($insData) )
            {

                $insDataKey = array_keys($insData);
                $insDataVal = array_values($insData);
                $preCnt     = count( $insDataKey );

                switch( $mode )
                {
                case 'insert':

                    $columns  = implode(",",$insDataKey);
                    $arrPreSt = array_fill( 0, $preCnt,'?');
                    $preSt    = implode(",",$arrPreSt);

                    return array($preSt, $insDataVal, $columns);

                    break;

                case 'update':

                    for( $i=0;$i < $preCnt; $i++ )
                    {
                        $arrPreSt[$i] = $insDataKey[$i] ." =? ";
                    }

                    $preSt =implode(",",$arrPreSt);

                    return array($preSt, $insDataVal);

                    break;
                }

            }
            else
            {
                return false;
            }

        }

        public function getLastId()
        {
            return $this->dbh->lastInsertId(); 
        }
}

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Z-TALBO

    2016/05/08 10:53

    コードブロックで囲まれたほうが良いですよ。

    キャンセル

回答 3

+1

用途に応じてDBを切り替える必要がある、という事でよろしいでしょうか。
個人的には接続情報等をパラメータとして渡すのは
コードの可読性やメンテナンス性を下げる要因と成りうるので利用しません。
子クラスから取得とか、クラス名にルールを設けて判断とかします。

親クラス
interface IDataObject
{
    public function execute();
}
親クラス
abstract class BaseDatabase implements IDataObject
{
    public function __construct()
    {
        $this->_db = NULL;
    }
    public function execute()
    {
        try
        {
            $this->connect();
            $this->executeImp();
        }
        catch (Exception $e)
        {
            throw $e;
        }
        finally
        {
            $this->disconnect();
        }
    }
    private $_db;
    protected function getResult()
    {
        return $this->_db->query的なメソッド($this->getSql());
    }
    protected function escape($value)
    {
        return $this->_db->escape的なメソッド($value);
    }
    private function connect()
    {
        $this->_db = new DB的なメソッド($this->getDsn());
    }
    private function disconnect()
    {
    }
    abstract protected function getDsn();
    abstract protected function executeImp();
    abstract protected function getSql();
}
このクラスをDB別に作り、子クラスは自分が利用するDBに応じて継承先を変える。
複数DBから持ってくる場合は違う設計にします!

クラス名にルールを設けて親クラスでget_called_class等でクラス名からDBを分ける方法もありかと。
私はよくこちらを利用します。

abstract class AppDatabaseMySql extends BaseDatabase
{
    public function __construct()
    {
        parent::__construct();
    }
    protected function getDsn()
    {
        $dsn = 'dsndesuyo';
        return $dsn;
    }
}
子クラス
MySQLを意識するのはイヤだなぁ
final class HogeHoge extends AppDatabaseMySql
{
    public function __construct(DBレコード格納用のリストクラス $hogeList)
    {
        parent::__construct();
        $this->_hogeList = $hogeList;
    }
    private $_hogeList;
    protected function executeImp()
    {
        while ($result = $this->getResult())
        {
            レコードセットから展開
            $hoge = new Hoge();
            $hoge->loadFromResultSet($result);
            $this->_hogeList->add($hoge);
        }
    }
    protected function getSql()
    {
        $sql = 'SELECT * FROM HOGE';
        return $sql;
    }
}

とすると、機能別に応じた子クラスだけ作ればDB接続を考えなくても良いかな~とか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

あくまで例なので、使いやすいように修正してください。

class PDOconnnect {
    private  $dbh = NULL; 

    public function __construct( $db_host, $db_user, $db_pass, $db_name, $db_type ) 
    { 
        $this->dbh = $this->connectDB( $db_host, $db_user, $db_pass, $db_name, $db_type ); 
    }

    public function getHandle()
    {
        return $this->dbh;
    }

    private function connectDB( $db_host, $db_user, $db_pass, $db_name, $db_type) 
    { 
        try{ 
            switch( $db_type) 
            { 
            case'mysql': 
                $dsn = 'mysql:host='.$db_host.';dbname='.$db_name; 
                $dbh = new PDO($dsn,$db_user,$db_pass); 
                $dbh->query('SET NAMES utf8'); 
                break;

                case'pgsql'; 
                $dsn = 'pgsql:dbname='.$db_name.'host='.$db_host.'port=5432'; 
                $dbh = new PDO($dsn,$db_user,$db_pass); 
                break; 
            } 
        } 
        catch(PDOException $e) 
        { 
            var_dump($e->getMessage()); 
            exit;

        } 
        return $dbh; 
    } 
}

class PDODatabase {
    private  $dbh     = NULL; 
    private  $order   = ''; 
    private  $limit   = ''; 
    private  $offset  = ''; 
    private  $groupby = '';

    public function __construct( $dbh)
    { 
        $this->dbh = $dbh;
    }

    public function setQuery( $query='', $arrVal = array() ) 
    { 
        $stmt = $this->dbh->prepare($query);
        $stmt->execute($arrVal);
    }
//以下略

//使い方
$obj1 = new PDOconnnect($db_host, $db_user, $db_pass, $db_name, $db_type);
$obj2 = new PDODatabase($obj1->getHandle());

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

クラスを2つに分けた時の呼び出し側の記述方法をイメージしてみてください。
↓現状はこんな実装イメージかと思います。
$db = new PDODatabase( $db_host, $db_user, $db_pass, $db_name, $db_type ) ;
$db->setQuery("select * from table ") ;

これをどういう風な表現に変えたいのでしょう?

変えたくないのであれば、
「★★ここから上を別のクラスに分けたい★★」から上を親クラス
そこから下を子クラスとして分けたら良いと思います。
ちなみに、親クラスのメンバ変数で子クラスで使用したいものはprivateではなくprotectedに替える必要があります。

接続情報を明示的に記述したいのであれば、
$dbh = new ConnectDB( $db_host, $db_user, $db_pass, $db_name, $db_type ) ; 
$db = new PDODatabase( $dbh ) ; 
$db->setQuery("select * from table ") ;

みたいな書き方をできるように、クラスを分割修正したら良いと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    PHPでページングのやり方

    あるDBからSELECtで検索をかけて結果を 配列$resultに入れているとします。 ページングの関数を作って処理したいのですが、 このあとどのようなプログラムを書けばよいのか

  • 解決済

    phpでメールアドレスの重複確認

    Webユーザー管理の作り方をドットインストールで勉強しています いわゆる写経なのですが メールアドレス重複確認の関数を作ったところで急にわからなくなりました。 function 

  • 解決済

    MySQLでINSERTできない。(PHP)

    MysqlでINSERTを行ったのですが、データが登録できないです。 DB接続はうまくいっているっぽい。 インサート文もテストとして、そのままコピーして PHPAdmin上で直接実

  • 解決済

    画面遷移なしで編集したいのですが、書き方が全くわかりません。。

    「編集」と「削除」を画面遷移なしで実行したいのですが、ajaxが分からず困っています。どうすれば、意図した結果が得られるでしょうか?>< PHPとMySQLを使っています。 PH

  • 解決済

    PHP DBから抽出データ、配列、SESSION、class

    はじめに たぶん、何やってんだろう?という質問内容かと思いますが、アドバイスをいただければと思います。 やりたいこと 漠然としてはいますが、たぶんclassを作るのに、す

  • 解決済

    sql文のセキュリティ 配列での受け渡し

    sql文の配列のへバインドがうまくいきません。 $cont=array(1,2,3,4,);//ここは常に変わる数値 $count_box=5;//ここは常に変わる数値 $i

  • 解決済

    オブジェクト指向について(PDOのDB接続クラスの自作)

    phpのPDOでのデータベースへの接続をクラス化するものを自作しています。 その中でオブジェクト指向について疑問ができたので質問させてください。 最初は下記のように ・ホ

  • 解決済

    executeで渡せない

    try { $dbh = new PDO('mysql:host=localhost; dbname=pagenation_sumple; charset=utf8', $

同じタグがついた質問を見る

  • PHP

    20834questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • トップ
  • PHPに関する質問
  • ショッピングサイトをつくっていて、クラスを別に分けたいのですが、分け方がわかりません。