我正在使用php.activerecord,我正在尝试将表格链接在一起。我没有使用他们的结构,但php.activerecord假设我,所以它并不总是有用。我正在尝试在已经制作的应用程序上使用它,因此我无法更改数据库。
我从上一个问题中了解到 - Model association with custom table and key names - 我需要尽可能明确地使用primary_key
和foreign_key
字段。
我现在使用has_many through遇到问题。我一直在NULL
,我不明白为什么。
所以,这是一个场景:我有3个表,contacts
,contactPrefs
和preferences
。这些表格如下
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'
)
);
}
根据the docs,我现在应该能够做到以下几点:
<?php
var_dump(Contact::find(1234)->preference);
我做不到。我得到NULL
。奇怪的是,我可以这样做:
<?php
var_dump(Contact::find(1234)->prefs[0]->preference);
这是正常的。但是,我不应该能够通过preference
对象直接访问contact
对象吗?我是否误解了文档(在我看来,它们不是最好的)?我做错了吗?
答案 0 :(得分: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
其次,你真正想要的是未定义。 Contact::find(1234)->preference
实际上应该做什么?返回第一个 ContactPref 的首选项?返回首选项对象的数组?
我想提供两者:
<?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 的函数strong> _ $ name ,其中 $ name 是首选项(对于第一个结果)和首选项(适用于整个系列)。这意味着您可以Contact::find(1234)->preference
执行与Contact::find(1234)->prefs[0]->preference
相同(但由于检查更安全)和Contact::find(1234)->preferences
以获取整个首选项集合。
这可以通过多种方式改进或优化,所以请不要按原样使用,但请尝试根据您的具体情况进行调整。 例如,您可以使用首选项的id作为数组中的索引,或者不强制加载来自 ContactPrefs 的更多数据而不是您要使用的数据,并尝试更复杂的查询获取您特别需要的首选项对象。
如果我通过通过在关系定义中工作找到更好的实现,我将返回。但是看到Unit Tests的活跃记录,我持怀疑态度。
答案 1 :(得分:0)
有几件事情看起来很奇怪,所以要找到“这会解决它”并不容易,但至少这是一个问题:
在phpactiverecord中,字段名应始终为小写。 SQL无论如何都不介意(不是表名是区分大小写的,而是列名不是)。所以说:
static $primary_key = 'contactID';
到
static $primary_key = 'contactid';
连接// find命令可以在SQL中使用,在这种情况下,你的key-string是如何'cased'并不重要,所以有些东西可以工作。但是,如果连接通过phpmyadmin的内部工作,它将失败。请查看此contactID
以及prefID
。
同样,这仅适用于COLUMN名称,因此不要将类名或表名更改为小写。
(额外的一点:phpmyadmin组合主键有问题。所以虽然它可能很难看,你可以在你的contactprefs表中添加一个额外的行(如果你还没有它),称为{{1} ,使该表实际上有一些工作。它不会给你带来太多麻烦,它会帮助activerecord库很多)
答案 2 :(得分: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对象,该对象具有多个contactPref及其每个Preference。此外,在联系人模型中,您将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')
);
}