2

私はphp.activerecordを使用しており、テーブルをリンクしようとしています。私はそれらの構造を使用していませんが、php.activerecord は私が使用していると想定しているため、常に機能するとは限りません。既に作ったアプリで使おうとしているので、データベースを変更できません。

以前の質問 -カスタム テーブルおよびキー名とのモデルの関連付けprimary_key- から、 フィールドとフィールドをできるだけ明示する必要があることを学びましたforeign_key

has_many を介して使用する際に問題が発生しています。を取得し続けてNULLいますが、その理由がわかりません。

ここにシナリオがあります: contactscontactPrefs、およびの 3 つのテーブルがありpreferencesます。それらのテーブルは次のとおりです

contacts
--------
contactID
name
status

contactPrefs
------------
contactID
prefID
prefValue

preferences
-----------
prefID
name
description

それぞれcontactに複数ありcontactPrefsます。それぞれcontactPrefsに 1 つありpreferencesます。これを機能させるために使用しようとしましhas_manyたが、そうではありません。ここに私のモデルがあります:

Contacts.php:

<?php
class Contact extends ActiveRecord\Model {
    static $primary_key = 'contactID';

    static $has_many = array(
        array(
            'prefs',
            'foreign_key' => 'contactid',
            'primary_key' => 'contactid',
            'class_name' => 'ContactPref'
        ),
        array(
            'preferences',
            'foreign_key' => 'prefid',
            'primary_key' => 'prefid',
            'through' => 'prefs',
            'class_name' => 'Preference'
        )
    );
}

ContactPref.php:

<?php
class ContactPref extends ActiveRecord\Model {
    static $table_name = 'contactPrefs';

    static $belongs_to = array(
        array(
            'contact',
            'foreign_key' => 'contactid',
            'primary_key' => 'contactid'
        ),
        array(
            'preference',
            'foreign_key' => 'prefid',
            'primary_key' => 'prefid'
        )
    );
}

Preference.php:

<?php
class Preference extends ActiveRecord\Model {
    static $primary_key = 'prefID';

    static $has_many = array(
        array(
            'prefs',
            'foreign_key' => 'prefid',
            'primary_key' => 'prefid',
            'class_name' => 'ContactPref'
        )
    );
}

docsによると、次のことができるようになりました。

<?php
var_dump(Contact::find(1234)->preference);

私はできません。私は得るNULL。奇妙なことに、私はこれを行うことができます:

<?php
var_dump(Contact::find(1234)->prefs[0]->preference);

それは正しく動作します。しかし、オブジェクトを介してpreferenceオブジェクトに直接アクセスできるべきではありませんcontactか? ドキュメントを誤解していますか (私の意見では、それらは最高ではありません)。私は何か間違ったことをしていますか?

4

3 に答える 3

1

まず、小さな欠陥のあるドキュメントを読んでいます。あなたが示されているドキュメントでは:

$order = Order::first();
# direct access to users
print_r($order->users); # will print an array of User object

を介してすでに行っていることContact::find(1234)->prefs。少し煮詰めさせてください

$contact = Contact::find(1234);
# direct access to prefs
print_r($contact->prefs); # will print an array of ContactPref object

次に、実際に必要なのはundefinedです。Contact::find(1234)->preference実際に何をすべきですか?最初のContactPrefの設定を返しますか? Preferenceオブジェクトの配列を返す

私は両方を提供したいと思います:

<?php
class Contact extends ActiveRecord\Model {
    static $primary_key = 'contactID';

    static $has_many = array(
        array(
            'prefs',
            'foreign_key' => 'contactid',
            'primary_key' => 'contactid',
            'class_name' => 'ContactPref'
        ),
        array(
            'preferences',
            'foreign_key' => 'prefid',
            'primary_key' => 'prefid',
            'through' => 'prefs',
            'class_name' => 'Preference'
        )
    );

    public function get_preference() {
        return isset($this->prefs[0])
            ? $this->prefs[0]->preference
            : null
        ;
    }
    public function get_preferences() {
        $preference=array();
        foreach($this->prefs as $pref) {
            $preference[]=$pref;
        }
        return $preference;
    }
}

私が行ったことを少し説明させてください。ActiveRecord\Modelクラスには__ get ($name)関数があり、 get _$nameという別の関数を探します。ここで、$name優先度(最初の結果の場合) と優先度(コレクション全体の場合) です。これは、実行するのと同じことを実行して(ただし、チェックがあるため、より安全です)、設定のコレクション全体を取得できることを意味します。Contact::find(1234)->preferenceContact::find(1234)->prefs[0]->preferenceContact::find(1234)->preferences

これはさまざまな方法で改善または最適化できるため、そのままではなく、特定の状況に合わせて調整してください。たとえば、設定の ID を配列のインデックスとして使用するか、使用するデータよりも多くのデータをContactPrefsから強制的にロードせず、より複雑なクエリを試行して、具体的に設定した設定オブジェクトを取得することができます。必要。

リレーションシップの定義で作業を進めて、より良い実装を見つけたら、戻ってきます。しかし、アクティブ レコードの単体テストを見て、私は懐疑的です。

于 2013-01-04T16:56:04.967 に答える
0

次のことを試してください。

<?php 
var_dump(Contact::find(1234)->preferences);

ドキュメントには、has_many関係では、複数形で参照する必要があると記載されています(http://www.phpactiverecord.org/projects/main/wiki/Associations#has_many_through)。Contact :: find(1234)は、各プリファレンスを持つ複数のcontactPrefsを持つContactオブジェクトを返します。さらに、連絡先モデルで、has_manyを設定として指定します。

static $has_many = array(
    array(
        'prefs',
        'foreign_key' => 'contactid',
        'primary_key' => 'contactid',
        'class_name' => 'ContactPref'
    ),
    array(
        'preferences',
        'foreign_key' => 'prefid',
        'primary_key' => 'prefid',
        'through' => 'prefs',
        'class_name' => 'Preference'
    )
);

変更による編集:

次の連絡先モデルを試してください

<?php
class Contact extends ActiveRecord\Model {
static $primary_key = 'contactID';

static $has_many = array(
    array(
        'prefs',
        'foreign_key' => 'contactid',
        'class_name' => 'ContactPref'
    ),
    array('preferences', 
          'through' => 'prefs', 
          'class_name' => 'Preference',
          'primary_key' => 'prefID')
);
}
于 2013-01-03T18:37:04.807 に答える
0

奇妙に見える点がいくつかあるため、「これで直る」と判断するのは簡単ではありませんが、少なくとも問題は次のとおりです。

phpactiverecord では、フィールド名は常に小文字にする必要があります。SQL はどちらの方法でも気にしません (テーブル名は大文字と小文字を区別するわけではありませんが、列名は区別しません)。だからこれを作る:

static $primary_key = 'contactID';

の中へ

static $primary_key = 'contactid';

接続 // find コマンドは SQL で使用できます。その場合、キー文字列がどのように「大文字と小文字が区別される」かは問題ではないため、一部の機能は機能します。しかし、接続が phpmyadmin の内部構造を通過すると失敗します。これcontactIDだけでなく、prefID.

繰り返しますが、これは COLUMN 名にのみ適用されるため、クラス名またはテーブル名を小文字に変更しないでください。

(余分な点: phpmyadmin は結合された主キーに問題があります。したがって、見苦しいかもしれませんが、 contactprefs テーブルに (まだ持っていない場合) という行を追加してid、そのテーブルが実際に機能するようにすることができます)それはあなたに大きな問題を与えることはなく、activerecord ライブラリを大いに助けるでしょう)

于 2012-12-28T08:09:42.767 に答える