0

Table.linkedIndexはLinkedIndex.IDに関連しています。フィールドLinkedIndex.TableNameの値はLinked1またはLinked2のいずれかであり、これらのテーブルのどれがTableの行に関連付けられているかを定義します。

ここで、テーブル行から対応するLinked1またはLinked2行に簡単に取得できるように、Yii モデルとの動的リンクを作成したいと考えています。

Table.linkedID = [LinkedIndex.TableName].ID

DB図


の値:

ここに画像の説明を入力

LinkedIndex値:

ここに画像の説明を入力

これで、 Linked2からID=2の行を取得する必要があります。

$model = Table::model()->findByPk(0);
$row = $model->linked;

モデル

モデルTableで、 linkedIndex.TableNameの値の名前を持つテーブルとの関係を作成しようとしました。

public function relations()
{
    return array(
        'linkedIndex' => array(self::HAS_ONE, 'LinkedIndex', array('ID' => 'linkedIndex')),
        'linked' => array(
            self::HAS_ONE,
            'linkedIndex.TableName',
            array('ID' => 'linkedID'),
        )
    )
}

しかし、その後、エラーが発生します:

include(linkedIndex.TableName.php) [function.include]: ストリームを開けませんでした: そのようなファイルまたはディレクトリはありません


Yii モデルで動的リレーションTable.linkedID -> [LinkedIndex.TableName].IDを作成する方法はありますか?

4

2 に答える 2

1

ここのYiiドキュメントによると:

http://www.yiiframework.com/doc/api/1.1/CActiveRecord#relations-detail

代わりに self::HAS_ONE を使用することをお勧めします (ただし、LinkedIndex に同じ ID を持つ複数の行が存在する可能性がある場合を除きます。ただし、上記の外観からは、そうであるとは思えません)。

スキーマに従って、異なるキーを持つテーブルをリンクできます。

外部キー => 主キー

カスタム PK->FK 関連付けを指定する必要がある場合は、それを array('fk'=>'pk') として定義できます。複合キーの場合は、array('fk_c1'=>'pk_с1','fk_c2'=>'pk_c2') になります。

だからあなたの場合:

public function relations(){
    return array(
        'linkedIndex' => array(self::HAS_ONE, 'LinkedIndex', array('ID' => 'linkedIndex')),
    );
}

ここLinkedIndexで、Linkeddex モデルのクラス名 (テーブル モデルに相対的 - つまり、同じフォルダー。もちろん変更できます) でありarray('ID' => 'linkedIndex')、関係を として指定しますLinkedIndex.ID = Table.linkedIndex

編集

更新された例を見ると、関係関数の仕組みを誤解していると思います。エラーが発生しています

include(linkedIndex.TableName.php) [function.include]: ストリームを開けませんでした: そのようなファイルまたはディレクトリはありません

ここで別のリレーションを作成しようとしているためです。

'linked' => array(
    self::BELONGS_TO,
    'linkedIndex.TableName',
    array('ID' => 'linkedID'),
)

この部分:linkedIndex.TableName新しいモデル クラスを参照するlinkedIndex.TableNameため、Yii はそのクラスのファイルをロードしようとしますがlinkedIndex.TableName.php、存在しないためエラーをスローします。

あなたが探しているのはTableName、テーブル内の値にアクセスできることだと思いますよねLinkedIndexTableその場合、次の方法でモデル内からアクセスできます。

$this->linkedIndex->TableName

これは、上で設定した関係によって可能になります。 モデルを$this参照し、上で作成した関係を参照し、そのモデルの属性です。TablelinkedIndexLinkedIndexTableNameLinkedIndex

編集 2

あなたのコメントによると、あなたはより複雑な関係を作ろうとしているようです。正直なところ、これは実際にはリンク テーブルを使用する方法ではありません (理想的には、どの 3 番目のテーブルにリンクするかを示すリンク テーブルではなく、2 つのテーブル間にリンク テーブルが必要です)。 Yii 内でできる限りあなたの質問に答えてください。

理想的には、この関係はLinkedIndexモデル内から作成する必要があります。モデル内に関係があるからです。

テーブル名をリンク要素として使用しているため、レコードが見つかった後に使用するテーブルを動的に渡す方法を作成する必要があります。

Yii 内でモデルが作成された後、LinkedIndexモデルの afterFind 関数を使用して 2 次リンクを作成し、そこで新しいリンクされたモデルをインスタンス化することができます。

LinkedIndex モデルは次のようになります。

class LinkedIndex extends CActiveRecord{
    public $linked;

    public static function model($className = __CLASS__){
        return parent::model($className);
    }

    public function tableName(){
        return 'LinkedIndex';
    }

    public function afterFind(){
        $this->linked = new Linked($this->TableName);

        parent::afterFind();
    }

    //...etc.
}

afterFind新しいLinkedモデルをインスタンス化し、使用するテーブル名を渡します。Linkedこれにより、モデル内から次のようなことができます。

class Linked extends CActiveRecord{
    private $table_name;

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

    public static function model($className = __CLASS__){
        return parent::model($className);
    }

    public function tableName(){
        return $this->table_name;
    }

    //...etc.
}

これが、交換可能なテーブル名を持つクラスを動的に作成する方法です。もちろん、これはクラスがメソッドごとに個別の操作を実行する必要があるため失敗しますが、それが何であるかを確認し、table_nameそれに応じて行動することができます (これはかなり厄介ですが、うまくいきます)。

これはすべて、(モデルlinked内から)次の方法でテーブルのプロパティにアクセスすることになります。Table

$this->linkedIndex->linked->foo;
于 2013-07-30T13:42:59.080 に答える
0

Because the value of LinkedIndex.TableName and Table.linkedID is needed to get the values, I moved the afterFind, suggested by M Sost, directly into the Table-Class and changed its content accordingly. No more need for a virtual model.

class Table extends CActiveRecord {
    public $linked; // Needs to be public, to be accessible
    // ...etc.
    public function afterFind() {
        $model = new $this->linkedIndex->TableName;
        $this->linked = $model::model()->findByPk( $this->linkedID );
        parent::afterFind();
    }
    // ...
}

Now I get the row from Linked2 where ID=2:

$model = Table::model()->findByPk(0);
$row = $model->linked;
于 2013-07-31T12:55:47.617 に答える