[英]Laravel non-recursive toArray()
Attempting to do both hasMany()
and hasOne()
relationships between the two tables as I've done before . 正如我之前所做的那样,尝试在两个表之间执行
hasMany()
和hasOne()
关系。
I have an Account
model which has both users()
(one-to-many) and a superUser()
(one-to-one), both of which are stored in the built-in User
model. 我有一个
Account
模型,它包含users()
(一对多)和superUser()
(一对一),两者都存储在内置的User
模型中。 As with normal one-to-many relationships, the "many" table ( users
) stores the relationship to the "one", but for the one-to-one relationship, I'm storing the association in the accounts
table. 与正常的一对多关系一样,“many”表(
users
)将关系存储到“one”,但对于一对一关系,我将关联存储在accounts
表中。
Accounts: 帐户:
/* model */
public function superUser()
{
return $this->hasOne(User::class, 'id', 'superuser_id');
}
public function users()
{
return $this->hasMany(User::class);
}
/* migration */
public function up()
{
Schema::create('accounts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('superuser_id')->unsigned();
$table->string('name');
$table->timestamps();
$table->foreign('superuser_id')
->references('id')
->on('users')
->onDelete('cascade');
});
}
Users 用户
/* model */
public function account()
{
return $this->belongsTo(Account::class);
}
/* migration */
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('account_id')->unsigned()->index()->nullable();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
Create a user: 创建用户:
>>> $user = factory(App\User::class)->create()
=> App\User {#3014
name: "Rose Grant II",
email: "ernser.thomas@example.com",
email_verified_at: "2019-05-31 15:38:32",
updated_at: "2019-05-31 15:38:32",
created_at: "2019-05-31 15:38:32",
id: 23,
}
Create an account with $user
as superuser: 使用
$user
以超级$user
身份创建帐户:
>>> $account = factory(App\Account::class)->create(['superuser_id' => $user]);
=> App\Account {#3024
name: "Kuhic-Price",
superuser_id: 23,
updated_at: "2019-05-31 15:39:11",
created_at: "2019-05-31 15:39:11",
id: 17,
}
>>> $account->superUser
=> App\User {#3011
id: 23,
account_id: null,
name: "Rose Grant II",
email: "ernser.thomas@example.com",
email_verified_at: "2019-05-31 15:38:32",
api_token: null,
created_at: "2019-05-31 15:38:32",
updated_at: "2019-05-31 15:38:32",
}
account_id
is null because we haven't yet associated $user
to the Account
: account_id
为null,因为我们尚未将$user
与Account
相关联:
>>> $account->superUser->account()->associate($account)->save()
=> true
>>> $account->superUser
=> App\User {#3011
id: 23,
account_id: 17,
name: "Rose Grant II",
email: "ernser.thomas@example.com",
email_verified_at: "2019-05-31 15:38:32",
api_token: null,
created_at: "2019-05-31 15:38:32",
updated_at: "2019-05-31 15:43:55",
account: App\Account {#3024
name: "Kuhic-Price",
superuser_id: 23,
updated_at: "2019-05-31 15:39:11",
created_at: "2019-05-31 15:39:11",
id: 17,
superUser: App\User {#3011},
},
}
But once we do this, it hangs: 但是一旦我们这样做,它就会挂起:
>>> $account->toArray()
^C
I'm thinking that this is due to each model pointing towards the other: the superuser of the Account
loads the User
which loads the Account
ad infinitum. 我认为这是由于每个模型都指向另一个模型:
Account
的超级User
加载了无限加载Account
的User
。 Is this a bug in toArray()
or simply normal behavior that I have to watch out for? 这是
toArray()
的错误还是我必须注意的正常行为? Or am I doing it wrong? 或者我做错了吗?
In the Laravel codebase, toArray()
is a convenience function merging the results of attributesToArray()
and relationsToArray()
into a single merged array : 在Laravel代码库中,
toArray()
是一个便利函数,它将attributesToArray()
和relationsToArray()
的结果合并为一个合并的数组 :
public function toArray()
{
return array_merge($this->attributesToArray(), $this->relationsToArray());
}
As I suspected, relationsToArray()
calls toArray()
on every arrayable relationship, causing the infinite recursion : 我怀疑,
relationsToArray()
在每个可数组关系上调用toArray()
, 导致无限递归 :
public function relationsToArray()
{
$attributes = [];
foreach ($this->getArrayableRelations() as $key => $value) {
// If the values implements the Arrayable interface we can just call this
// toArray method on the instances which will convert both models and
// collections to their proper array form and we'll set the values.
if ($value instanceof Arrayable) {
$relation = $value->toArray(); // <-- here's the recursive call
}
...
If all that is needed is the attributes (as in my case), calling attributesToArray()
on the model is a good workaround: 如果只需要属性(如我的情况),在模型上调用
attributesToArray()
是一个很好的解决方法:
>>> $account->attributesToArray()
=> [
"name" => "Kuhic-Price",
"superuser_id" => 23,
"updated_at" => "2019-05-31 15:39:11",
"created_at" => "2019-05-31 15:39:11",
"id" => 17,
]
EDIT: Also this behavior is by design, as the documentation explicitly states recursion: 编辑:此行为也是设计,因为文档明确说明了递归:
This method is recursive , so all attributes and all relations ( including the relations of relations ) will be converted to arrays (emphasis mine)
这个方法是递归的 ,所以所有属性和所有关系( 包括关系关系 )都将被转换为数组(强调我的)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.