質問

PHP でのデータベース接続にグローバルではなくシングルトンを使用する利点は何ですか?グローバルの代わりにシングルトンを使用すると、コードが不必要に複雑になるように感じます。

グローバルを使用したコード化

$conn = new PDO(...);

function getSomething()
{
    global $conn;
    .
    .
    .
}

シングルトンを使用したコード

class DB_Instance
{
    private static $db;

    public static function getDBO()
    {
        if (!self::$db)
            self::$db = new PDO(...);

        return self::$db;
    }
}

function getSomething()
{
    $conn = DB_Instance::getDBO();
    .
    .
    .
}

データベース接続を初期化するグローバルまたはシングルトン以外のより良い方法がある場合は、その方法について言及し、グローバルまたはシングルトンに比べてどのような利点があるかを説明してください。

役に立ちましたか?

解決

これが古いことは承知していますが、Dr8k の答えは次のとおりです。 ほとんど そこには。

コードの作成を検討するときは、コードが変更されることを想定してください。それは、将来のある時点でどのような変化がもたらされるかを想定しているという意味ではなく、何らかの形の変化が起こるだろうということです。

それを目標にして、将来変更を加える際の苦痛を軽減します。グローバルは 1 か所で管理するのが難しいため危険です。将来、データベース接続のコンテキストを認識できるようにしたい場合はどうすればよいですか?5 回使用するたびに自動的に閉じて再度開くようにしたい場合はどうすればよいでしょうか。アプリをスケーリングするために、10 個の接続のプールを使用することにした場合はどうすればよいですか?それとも接続数を設定できるのでしょうか?

シングルトン工場 その柔軟性を与えてくれます。特別な複雑さをほとんど加えずにセットアップすると、同じ接続にアクセスできるだけでなく、それ以上の効果が得られます。私は、そのつながりが後で私にどのように渡されるかを簡単な方法で変更できるようになります。

私が言うことに注意してください シングルトン工場 単にではなく シングルトン. 。確かに、シングルトンとグローバルの間にはほとんど違いがありません。そのため、シングルトン接続を使用する理由はありません。通常のグローバルを作成できるのに、なぜその設定に時間を費やすのでしょうか?

工場があなたに提供するものは、接続を取得する理由と、どのような接続 (または複数の接続) を取得するかを決定するための別の場所です。

class ConnectionFactory
{
    private static $factory;
    private $db;

    public static function getFactory()
    {
        if (!self::$factory)
            self::$factory = new ConnectionFactory(...);
        return self::$factory;
    }

    public function getConnection() {
        if (!$this->db)
            $this->db = new PDO(...);
        return $this->db;
    }
}

function getSomething()
{
    $conn = ConnectionFactory::getFactory()->getConnection();
    .
    .
    .
}

その後、6 か月後、アプリが非常に有名になり、掘り下げられ、複数の接続が必要になったときに、必要なのは getConnection() メソッドにプーリングを実装することだけです。または、SQL ログを実装するラッパーが必要な場合は、PDO サブクラスを渡すことができます。または、呼び出しごとに新しい接続が必要な場合は、そうすることもできます。硬いのではなく、柔軟性があります。

中括弧を含む 16 行のコード。これにより、将来的に不気味なほど似たものをリファクタリングする時間を何時間も節約できます。

最初の段階では機能の実装を行っていないため、この「機能のクリープ」は考慮されていないことに注意してください。「Future Creep」のボーダーラインだけど、いつしか「明日のコーディングを今日する」という考え方が いつも 悪いことは私には関係ありません。

他のヒント

あなたの具体的な質問に答えることができるかどうかはわかりませんが、Web ベースのシステムの場合、グローバル/シングルトン接続オブジェクトは最良のアイデアではない可能性があることを示唆したいと思います。DBMS は通常、多数の一意の接続を効率的な方法で管理するように設計されています。グローバル接続オブジェクトを使用している場合は、次のことをいくつか行います。

  1. ページにすべてのデータベース接続を順番に実行するように強制し、無おそらくページのロードでの試みを殺します。

  2. データベース要素のオープンロックを必要以上に長く保持する可能性があり、データベース全体のパフォーマンスが遅くなります。

  3. データベースがサポートできる同時接続の総数を最大化して、新しいユーザーがリソースにアクセスするのをブロックします。

他にも潜在的な影響があると確信しています。このメソッドは、サイトにアクセスするすべてのユーザーのデータベース接続を維持しようとすることに注意してください。ユーザーが 1 人か 2 人だけの場合は問題ありません。これが公開 Web サイトでトラフィックが必要な場合、スケーラビリティが問題になります。

[編集]

大規模な状況では、データにアクセスするたびに新しい接続を作成するのは問題が生じる可能性があります。ただし、その答えは、グローバル接続を作成して、それをあらゆるものに再利用することではありません。答えは接続プーリングです。

接続プーリングを使用すると、多数の個別の接続が維持されます。アプリケーションで接続が必要な場合、プールから最初に使用可能な接続が取得され、ジョブが完了するとプールに返されます。接続が要求されても利用可能な接続がない場合は、次の 2 つのいずれかが起こります。a) 許可された接続の最大数に達していない場合は、新しい接続が開かれます。または、b) アプリケーションは接続が使用可能になるまで強制的に待機します。

注記: .Net 言語では、接続プーリングはデフォルトで ADO.Net オブジェクトによって処理されます (接続文字列によって必要な情報がすべて設定されます)。

これについてコメントしてくれた Crad に感謝します。

シングルトン メソッドは、クラスのインスタンスが 1 つだけ存在するようにするために作成されました。しかし、人々はこれをグローバリゼーションをショートカットする方法として使用するため、怠惰なプログラミングや不適切なプログラミングとして知られるようになりました。

したがって、グローバルとシングルトンは両方とも実際には OOP ではないため、無視します。

あなたが探していたものは 依存性注入.

依存関係注入に関連する読みやすい PHP ベースの情報 (例付き) を次の場所で確認できます。 http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection

どちらのパターンでも最終的には同じ効果が得られ、データベース呼び出しに単一のアクセス ポイントが提供されます。

具体的な実装に関して言えば、シングルトンには、他のメソッドの少なくとも 1 つがデータベース接続を要求するまでデータベース接続を開始しないという小さな利点があります。実際、私が作成したほとんどのアプリケーションでは、これは大きな違いはありませんが、データベース呼び出しをまったく行わないページ/実行パスがある場合、それらのページは呼び出しを行わないため、潜在的な利点になります。データベースへの接続を要求することはありません。

もう 1 つの小さな違いは、グローバル実装がアプリケーション内の他の変数名を意図せずに踏みにじる可能性があることです。別のグローバル $db 参照を誤って宣言する可能性はほとんどありませんが、誤って上書きしてしまう可能性はあります (たとえば、if($db == null) を書くつもりで if($db = null) を書いた場合などです。シングルトン オブジェクトはそれを防ぎます。

永続的な接続を使用する予定がなく、使用しない場合もある場合、OO 設計ではグローバルよりもシングルトンの方が概念的に使いやすいと思います。

真の OO アーキテクチャでは、オブジェクトの新しいインスタンスを毎回作成するよりもシングルトンの方が効率的です。

与えられた例では、シングルトンを使用する理由は見当たりません。経験則として、オブジェクトの単一インスタンスを許可することのみを考慮している場合、言語で許可されている場合は、グローバルを使用することを好みます。

一般に、データベース接続にはシングルトンを使用します...データベースと対話する必要があるたびに新しい接続を作成する必要はありません...これにより、ネットワークのパフォーマンスと帯域幅に悪影響を及ぼす可能性があります...利用可能なものがあるのに、なぜ新しいものを作成する必要があるのでしょうか...私の2セントだけ…

Rウェンディ

とてもシンプルです。グローバル OR シングルトンは決して使用しないでください。

どちらもアドバイスとしては シングルトン そして グローバル 有効であり、同じ内で結合できます システム、プロジェクト、プラグイン、製品など ...私の場合はWeb向けのデジタルプロダクト(プラグイン)を作っています。

私はのみを使用します シングルトン メインクラスで使用し、原則としてそれを使用します。メインクラスが再度インスタンス化しないことがわかっているため、ほとんど使用しません

<?php // file0.php

final class Main_Class
{
    private static $instance;
    private $time;

    private final function __construct()
    {
        $this->time = 0;
    }
    public final static function getInstance() : self
    {
        if (self::$instance instanceof self) {
            return self::$instance;
        }

        return self::$instance = new self();
    }
    public final function __clone()
    {
        throw new LogicException("Cloning timer is prohibited");
    }
    public final function __sleep()
    {
        throw new LogicException("Serializing timer is prohibited");
    }
    public final function __wakeup()
    {
        throw new LogicException("UnSerializing timer is prohibited");
    }
}

グローバル ほぼすべての 2 次クラスに使用します。例:

<?php // file1.php
global $YUZO;
$YUZO = new YUZO; // YUZO is name class

実行時に使用できるのは グローバル メインの製品クラスの別のインスタンスが必要ないため、同じインスタンスでメソッドと属性を呼び出すことができます。

<?php // file2.php
global $YUZO;
$YUZO->method1()->run();
$YUZO->method2( 'parameter' )->html()->print();

同じクラスのインスタンスにファクトリは必要ないため、グローバルとは、製品を機能させるために同じインスタンスを使用することです。通常、インスタンスファクトリは大規模なシステムまたは非常にまれな目的に使用されます。

In conclusion:, すでによく理解している場合は、それがアンチパターンである必要があります。 シングルトン そしてそれを理解する グローバル, 、2 つのオプションのいずれかを使用することも、それらを組み合わせて使用​​することもできますが、非常に例外的でプログラミング OOP に忠実なプログラマが多いため、乱用しないことをお勧めする場合は、実行内で頻繁に使用するメイン クラスとセカンダリ クラスに使用してください。時間。(CPU を大幅に節約できます)。😉

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top