2

我正在使用php.activerecord,我正在尝试将表链接在一起。我没有使用他们的结构,但 php.activerecord 假设我是,所以它并不总是有效。我正在尝试在已经制作的应用程序上使用它,所以我无法更改数据库。

我从上一个问题中了解到 -与自定义表和键名的模型关联- 我需要尽可能明确地使用primary_keyandforeign_key字段。

我现在在使用has_many through时遇到问题。我不断得到NULL,我不知道为什么。

所以,这是一个场景:我有 3 个表,contactscontactPrefspreferences。这些表如下

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

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

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

每个contact都有多个contactPrefs. 每个contactPrefs人都有一个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'
        )
    );
}

根据文档,我现在应该能够执行以下操作:

<?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

其次,你真正想要的是undefinedContact::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)->preference与执行相同的操作Contact::find(1234)->prefs[0]->preference(但由于检查而更安全)并Contact::find(1234)->preferences获得整个偏好集合。

这可以通过多种方式变得更好或优化,因此请不要照原样接受,但请尝试使其适应您的具体情况。例如,您可以使用首选项的 id 作为数组中的索引,或者不强制从ContactPrefs 加载比您要使用的数据更多的数据,并尝试更复杂的查询来获取您特别指定的首选项对象需要。

如果我通过处理关系定义找到更好的实现,我会回来的。但是看到活动记录的单元测试,我持怀疑态度。

于 2013-01-04T16:56:04.967 回答
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 回答
0

尝试以下操作:

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

该文档说,对于 has_many 关系,它应该由复数引用(http://www.phpactiverecord.org/projects/main/wiki/Associations#has_many_through)。Contact::find(1234) 返回一个 Contact 对象,该对象具有多个 contactPrefs 及其每个 Preference。此外,在您的 Contact 模型中,您将 has_many 指定为preferences

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 回答