我有一个小练习会计应用程序,我正在使用Laravel来提供REST api。我试图使用雄辩的关系来处理交付对象,包括他们的关系。
现在我有一个“交易”模型,如下所示。
class Transaction extends Model
{
protected $table = "transaction";
protected $fillable = [
"transaction_type_id",
"account_id",
"description",
"amount",
"comments",
"transaction_status_id",
"posting_date"
];
protected $guarded = [
"id"
];
public static function create(array $attributes = Array()) {
$account = BankAccount::find($attributes["account_id"]);
if ($attributes["transaction_type_id"] == 1) {
//Credit
$account["balance"] += $attributes["amount"];
} else if ($attributes["transaction_type_id"] == 2) {
//Debit
$account["balance"] -= $attributes["amount"];
}
$account->save();
parent::create($attributes);
}
public function transactionType() {
return $this->hasOne("App\Model\TransactionType", "id");
}
public function transactionStatus() {
return $this->hasOne("App\Model\TransactionStatus", "id");
}
}
TransactionStatus模型如下所示
class TransactionStatus extends Model
{
protected $table = "transaction_status";
protected $guarded = [
"id", "description"
];
}
TransactionType模型如下所示
class TransactionType extends Model
{
protected $table = "transaction_type";
protected $guarded = [
"id", "description"
];
}
我的控制器中有以下内容
return Transaction::with("TransactionType", "TransactionStatus")
->where("account_id", $accountId)
->get()
->toJson();
此查询返回如下所示的结果,其中第一个结果返回关系,但每个后续记录都为null。
{
"id": 1,
"transaction_type_id": 1,
"account_id": 1,
"description": "Morbi metus. Vivamus euismod urna.",
"amount": "4179.00",
"comments": "ullamcorper, nisl arcu iaculis enim,",
"transaction_status_id": 1,
"posting_date": "2016-12-10 21:24:25",
"created_at": "2016-12-10 00:00:00",
"updated_at": "2016-12-10 00:00:00",
"transaction_type": {
"id": 1,
"description": "Credit",
"created_at": "2016-12-09 13:37:00",
"updated_at": "2016-12-09 13:37:00"
},
"transaction_status": {
"id": 1,
"description": "Pending",
"created_at": "2016-12-09 13:37:00",
"updated_at": "2016-12-09 13:37:00"
}
},
{
"id": 3,
"transaction_type_id": 1,
"account_id": 1,
"description": "lorem ut aliquam iaculis, lacus",
"amount": "2710.00",
"comments": "ac, eleifend vitae, erat. Vivamus",
"transaction_status_id": 1,
"posting_date": "2016-07-16 04:23:34",
"created_at": "2016-12-10 00:00:00",
"updated_at": "2016-12-10 00:00:00",
"transaction_type": null,
"transaction_status": null
}
上面的结果对我没有意义,因为事务表中的所有记录都有transaction_type_id和transaction_status_id,所以这些记录根本不应该为null。
我试图理解为什么会发生这种情况,我看起来很高低,但我找不到解释。我在下面列出了一个屏幕截图,指出了MySQL中表格的记录。
我找到了问题的解决方案,它与IzzEps指出的方向相同。
我最初建立关系的方式是这样的。
public function transactionType() {
return $this->hasOne("App\Model\TransactionType", "id");
}
public function transactionStatus() {
return $this->hasOne("App\Model\TransactionStatus", "id");
}
我又看了一眼eloquent relationship docs,发现了这个:
此外,Eloquent假定外键应具有与父级的id(或自定义$ primaryKey)列匹配的值。换句话说,Eloquent将在电话记录的user_id列中查找用户id列的值。如果您希望关系使用id以外的值,则可以将第三个参数传递给指定自定义键的hasOne方法:
return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
当我改变关系时:
public function transactionType() {
return $this->hasOne("App\Model\TransactionType", "id", "transaction_type_id");
}
public function transactionStatus() {
return $this->hasOne("App\Model\TransactionStatus", "id", "transaction_status_id");
}
我得到了我期待的结果。在这种情况下,“id”是存在于transaction_status或transaction_type表上的外键,“transaction_type_id”或“transaction_status_id”是“transaction”表的“本地”键或者“local_key”中的键。文档。
我没有完全指定如何定义关系以及关系应该使用哪些键。谢谢你指出我正确的方向,应该是第二性质,回到文档。
因此,一如既往,我应该更密切地RTM。
定义以下关系时
public function transactionType() {
return $this->hasOne("App\Model\TransactionType", "id");
}
public function transactionStatus() {
return $this->hasOne("App\Model\TransactionStatus", "id");
}
你指定id
模型表的Transaction
作为这两种关系的外键(分别与transaction_type_id
和transaction_status_id
的正确外键相对)。结果是,在调用Transaction::with("TransactionType", "TransactionStatus")
时,您将在错误的外键(transaction_type
)上加入transaction_status
和transaction.id
表。
修理:
只需更新您的关系以使用正确的外键,如下所示:
public function transactionType() {
return $this->hasOne("App\Model\TransactionType", "transaction_type_id");
}
public function transactionStatus() {
return $this->hasOne("App\Model\TransactionStatus", "transaction_status_id");
}
希望这可以帮助...
没有第一次看到它。实际上你在你的`交易模型上存储了transaction_type_id
和transaction_status_id
。这实质上意味着关系应该被定义为
Transaction belongsTo TransactionType & (Inverse) TransactionType hasMany Transaction
和
Transaction belongsTo TransactionStatus & (Inverse) TransactionStatus hasMany Transaction
hasOne
,belongsTo
和hasMany
的签名非常不同。
所以应该定义关系(根据您当前的代码)
class Transaction extends Model
{
protected $table = "transaction";
protected $fillable = [
"transaction_type_id",
"account_id",
"description",
"amount",
"comments",
"transaction_status_id",
"posting_date"
];
public function transactionType()
{
return $this->belongsTo('App\Model\TransactionType');
}
public function transactionStatus()
{
return $this->belongsTo('App\Model\TransactionStatus');
}
}
class TransactionType extends Model
{
protected $table = "transaction_types";
protected $fillable = [ /* mass assignable fields */];
public function transactions()
{
return $this->hasMany('App\Model\Transaction');
}
}
class TransactionStatus
{
protected $table = "transaction_statuses";
protected $fillable = [ /* mass assignable fields */];
public function transactions()
{
return $this->hasMany('App\Model\Transaction');
}
}
根据Laravel文档,Eloquent根据模型名称确定关系的外键。
由于您遵循命名与模型名称对应的外键的所需约定
transaction_type_id <=> TransactionType and transaction_status_id <=> TransactionStatus
您可以省略指定外键作为关系函数的第二个参数。
在定义上述关系之后
return Transaction::with('transactionType', 'transactionStatus')
->where("account_id", $accountId)
->get()
->toJson();
应该为您返回所需的输出。没有测试过,但绝对应该工作。
希望这可以帮助。如果不是,请告诉我。
public function dispute() {
return $this->hasOne('App\PaypalDispute', 'transaction_id', 'transaction_id');
}
我设法得到这样的。我们应该使用local_key作为列名来工作。