0

Table.linkedIndexLinkedIndex.ID相关。LinkedIndex.TableName字段的值是Linked1Linked2并定义这些表中的哪些与Table中的行相关。

现在我想与 Yii 模型建立动态链接,以便我可以轻松地从Table行获取到相应的Linked1Linked2行:

Table.linkedID = [LinkedIndex.TableName].ID

数据库图


例子

值:

在此处输入图像描述

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'),
        )
    )
}

但后来我得到了错误:

包括(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 - 尽管从上面的外观来看,我怀疑是这种情况)。

您可以按照架构将具有不同键的表链接在一起:

foreign_key => 主键

如果您需要指定自定义 PK->FK 关联,您可以将其定义为 array('fk'=>'pk')。对于复合键,它将是数组('fk_c1'=>'pk_с1','fk_c2'=>'pk_c2')。

所以在你的情况下:

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

LinkedIndex 模型的类名在哪里LinkedIndex(相对于您的 Table 模型 - 即相同的文件夹。您当然可以更改它)并将array('ID' => 'linkedIndex')关系指定为LinkedIndex.ID = Table.linkedIndex.

编辑

查看您更新的示例,我认为您误解了关系功能的工作原理。你得到了错误

包括(linkedIndex.TableName.php)[function.include]:无法打开流:没有这样的文件或目录

因为你试图在这里创建另一个关系:

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

这部分:linkedIndex.TableName引用了一个新的模型类linkedIndex.TableName,因此 Yii 尝试加载该类的文件linkedIndex.TableName.php并抛出错误,因为它不存在。

我认为您正在寻找的是能够访问TableNametable 中的值,对LinkedIndex吗?如果是这样,可以Table通过以下方式从模型内部访问:

$this->linkedIndex->TableName

这可以通过我们上面建立的关系来实现。 $thisTable模型,linkedIndexLinkedIndex我们上面建立的关系,TableName是该模型的一个属性LinkedIndex

编辑 2

根据您的评论,您似乎正在尝试建立更复杂的关系。老实说,这不是你应该使用链接表的方式(理想情况下,你应该在两个表之间有一个链接表,而不是一个链接表,说明要链接到哪个第三个表),但我会尝试和在 Yii 中尽可能地回答你的问题。

理想情况下,这种关系应该在LinkedIndex模型内部建立,因为这就是关系所在。

由于您使用表名作为链接因素,因此您需要创建一种方法来在找到记录后动态传递要使用的表。

在 Yii 中创建模型后,您可以使用LinkedIndex模型的 afterFind 函数创建二级链接,并在那里实例化新的链接模型。

您的 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

因为获取值需要 LinkedIndex.TableName 和 Table.linkedID 的值,所以我将M Sost建议的afterFind直接移动到Table -Class 并相应地更改了其内容。不再需要虚拟模型。

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();
    }
    // ...
}

现在我从Linked2得到ID=2 的行:

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