14

私はPHP+MySQLで小さなアプリケーションを作成していて、それに関連付けられたフラグが2つ(これまでのところ8つありますが、増えるとは予想されていません)のオブジェクトが存在するようになりました。意味をなさないいくつかの組み合わせがありますが、フラグはほとんど無関係です。オブジェクトはDB内の行を表します(それを保存/ロードするためのいくつかのメソッドもあります)ので、質問はストレージメソッドの選択にも当てはまります。

問題は、コードとDBの両方でそれらを最もよく表現する方法です。私はいくつかの方法を考えることができます:

それらをDBに格納する1つの方法は、ビット単位のフラグとして単一の整数フィールドに格納することです。PHP側では、それらを表現するいくつかの方法を想像できます。

  • 整数値をエクスポートして、いくつかのフラグ定数を定義するだけです。フラグが必要なすべての場所に独自のビット単位の魔法を実行させます。
  • クラスメソッドを定義GetFlag()SetFlag()ますUnsetFlag()。これは、プライベート整数変数に対してビット単位の魔法を実行します。これらのメソッドには、フラグ定数の1つがパラメーターとして渡されます。
  • メソッドなどを定義GetFlagA()しますGetFlagB()(対応するSetおよびUnsetとともに)。
  • それぞれが1つのフラグを表す一連のメンバー変数を定義します。DBからのロード時にそれらを設定し、保存時にそれらを収集します。
  • すべてのフラグ値の配列であるメンバー変数を作成します。各フラグにアクセスするための配列インデックスとして事前定義された定数を使用します。また、ロード/保存時にアレイを埋める/収集します。

もう1つの方法は、それらを個別のBITフィールドとしてDBに格納することです。PHPでは、これはいくつかのメンバー変数に変換されます。私見これはクエリを複雑にします。

そして最後の方法は、すべてのフラグに別のテーブルを定義し、フラグと元のオブジェクト間の多対多の関係に中間テーブルを定義することです。私見は、他の方法では3つのテーブルしかないことを考えると、すべてのソリューションの中で最も厄介です。

私はPHPの開発をあまり行っていないので、ベストプラクティスがどうなるかわかりません。C#では、おそらくそれらをビット単位のフラグとして格納し、プライベート整数に対してビット単位の魔法を実行するプロパティを作成します。しかし、PHPにはプロパティがありません(私は最新の安定バージョンを使用しています)...

4

7 に答える 7

36

あなたのモデルでは、オブジェクトには 8 つのブール値のプロパティがあります。これは、データベース テーブルに 8 つのブール値 (MySQL の場合は TINYINT) 列があり、オブジェクトに 8 つの getter/setter メソッドがあることを意味します。シンプルで従来型。

現在のアプローチを再考してください。このことを維持しなければならない次の人が何を言うか想像してみてください.

CREATE TABLE mytable (myfield BIT(8));

OK、ここでバイナリ データが発生するようです。

INSERT INTO mytable VALUES (b'00101000');

待って、誰かもう一度 1 と 0 の意味を教えてくれ。

SELECT * FROM mytable;
+------------+
| mybitfield |
+------------+
| (          | 
+------------+

何?

SELECT * FROM mytable WHERE myfield & b'00101000' = b'00100000';

なんと!? なんと!?

自分の顔を刺す


-- 一方、妖精がユニコーンと戯れ、プログラマーが DBA を嫌わない別の世界では... --

SELECT * FROM mytable WHERE field3 = 1 AND field5 = 0;

幸福と太陽の光!

于 2009-01-10T02:43:17.747 に答える
2

本当にビット フラグを使用する必要がある場合は、SET 列を使用してそれらを DB に格納し、コードで連想配列を使用し、フラグをオン/オフするメソッドを使用します。その形式で配列が必要な場合は、配列を単一の整数との間で変換する別のメソッドを追加します。

低レベルのビット演算子を使用しても何も得られないため、コードを読みやすくすることもできます。

于 2009-01-09T18:46:25.463 に答える
1

PHPとMySQLENUMの間のギャップを埋めるために、この単純な関数をコーディングしました。

function Enum($id)
{
    static $enum = array();

    if (func_num_args() > 1)
    {
        $result = 0;

        if (empty($enum[$id]) === true)
        {
            $enum[$id] = array();
        }

        foreach (array_unique(array_map('strtoupper', array_slice(func_get_args(), 1))) as $argument)
        {
            if (empty($enum[$id][$argument]) === true)
            {
                $enum[$id][$argument] = pow(2, count($enum[$id]));
            }

            $result += $enum[$id][$argument];
        }

        return $result;
    }

    return false;
}

使用法:

// sets the bit flags for the "user" namespace and returns the sum of all flags (15)
Enum('user', 'anonymous', 'registed', 'active', 'banned');

Enum('user', 'anonymous'); // 1
Enum('user', 'registed', 'active'); // 2 + 4 = 6
Enum('user', 'registed', 'active', 'banned'); // 2 + 4 + 8 = 14
Enum('user', 'registed', 'banned'); // 2 + 8 = 10

列挙リストをMySQLENUMと同じ順序で定義していることを確認する必要があります。

于 2010-06-23T22:49:59.780 に答える
0

5.0.5以降のバージョンのMySQLを使用していると仮定すると、列をBIT[ここのビット数]として定義できます。PHP側に関しては、おそらくGet / SetFlagA、Get / SetFlagBアプローチを使用しますが、setメソッドにブール値を取り込むだけなので、unsetメソッドは必要ありません。

于 2009-01-09T18:23:57.380 に答える
0

OK、それについてもう少し考えた後、フラグごとに1つのメンバー変数を使用することにしました。ゲッター/セッターメソッドのアプローチを使用することもできましたが、コード内の他の場所では使用しないため、これは時代遅れになります。さらに、この方法でDBストレージ方式を抽象化し、後で必要に応じて簡単に変更できます。

DBに関しては、今のところビット単位の整数のままにしておきます。これは主に、ソフトウェアがほぼ完成していて、それを変更したくないためです。読みやすさはまったく変わりません。

于 2009-01-09T21:35:40.097 に答える
0

データベースを見るだけでは、どのフラグが設定されているかを知るのが非常に難しくなるため、ビット単位の操作には近づきません (何らかの理由で非常に効率的にしようとしている場合を除きます)。他の 2 つのオプションの間では、これらのフラグのそれぞれが持つ意味に依存すると思います。それらがすでに 8 つあることを考えると、それらの間に多対多の関係がある別のテーブルに傾倒します (最も気に入らないものを選んで申し訳ありません)。

于 2009-01-09T18:27:09.947 に答える
0

それらを DB に格納する 1 つの方法は、ビットごとのフラグとして単一の整数フィールドに格納することです。

これを行う場合は、__get および __setオーバーロード メソッドを使用して、単純にフィールドを取得し、必要に応じてビット演算を実行できます。

于 2009-01-09T19:28:14.613 に答える