尝试在两个表as I've done before之间建立hasMany()
和hasOne()
关系。
我有一个Account
模型,该模型同时具有users()
(一对多)和superUser()
(一对一),两者均存储在内部-在User
模型中。与普通的一对多关系一样,“许多”表(users
)将关系存储为与“一个”关系,但是对于一对一关系,我将关联存储在{ {1}}表。
帐户:
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');
});
}
创建用户:
/* 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();
});
}
使用>>> $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,
}
作为超级用户创建一个帐户:
$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
与$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},
},
}
我认为这是由于每个模型都指向另一个模型:>>> $account->toArray()
^C
的超级用户加载了Account
,而后者又无限加载了User
广告。这是Account
中的错误,还是我必须提防的正常行为?还是我做错了?
答案 0 :(得分:0)
在Laravel代码库中,toArray()
是一个便捷函数,它将attributesToArray()
和relationsToArray()
的结果合并到single merged array中:
public function toArray()
{
return array_merge($this->attributesToArray(), $this->relationsToArray());
}
我怀疑,relationsToArray()
在每个可排列的关系causing the infinite recursion上调用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
}
...
如果仅需要属性(如我的情况),则在模型上调用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,
]
编辑:此行为也是设计使然,因为文档明确states递归:
此方法是递归的,因此所有属性和所有关系(包括关系的关联)都将转换为数组(强调我的意思)