Laravel 保存一对多关系
Laravel save one to many relationship
我在 Laravel 中设置了以下关系:
OrderStatus Model
- hasMany('Order')
Order Model
- 'belongsTo('OrderStatus');
数据库设置有 orders
table 和 order_statuses
table。 orders
table 有一个字段用于 order_status_id
。
当我保存订单时,我通过获取适当的订单状态模型手动设置 order_status_id
,如下所示:
$status = OrderStatus::where(['name'=>'sample_status'])->firstOrFail();
$order->order_status_id = $status->id;
$order->save();
我想知道是否有内置函数可以执行此操作而不是手动设置 order_status_id
。我在 Laravel 文档中阅读了 "Attaching a related model" 和 "Associating Models",但我无法确定这些是否适合我的用例。我认为我遇到的问题是我直接使用子模型(订单),并试图设置它的父模型。有这个功能吗?
当然可以:
$status = OrderStatus::where(['name'=>'sample_status'])->firstOrFail();
$order = new Order;
$order->status()->associate($status);
$order->save();
(status()
是 belongsTo 关系。您可能需要调整该名称)
为新的相关模型保存关系的正确方法如下:
$status = OrderStatus::where(['name'=>'sample_status'])->firstOrFail();
$order = new Order;
$status->order()->save($order);
文档 link:http://laravel.com/docs/4.2/eloquent#inserting-related-models
您可以使用自定义解决方案。
我正在解释一个例子,刚刚编码并且与您的问题非常相似,希望它能有所帮助。
我有一个 问题模型 和 AnswerOption 模型,如下所示。
问题模型
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Question extends Model
{
protected $table = 'questions';
protected $fillable = [
'title',
'created_at',
'updated_at'
];
/**
* Get the answer options for the question.
*/
public function answerOptions()
{
return $this->hasMany('App\Models\AnswerOption');
}
/**
* @param array $answerOptions
*/
public function syncAnswerOptions(array $answerOptions)
{
$children = $this->answerOptions;
$answerOptions = collect($answerOptions);
$deleted_ids = $children->filter(
function ($child) use ($answerOptions) {
return empty(
$answerOptions->where('id', $child->id)->first()
);
}
)->map(function ($child) {
$id = $child->id;
$child->delete();
return $id;
}
);
$attachments = $answerOptions->filter(
function ($answerOption) {
// Old entry (you can add your custom code here)
return empty($answerOption['id']);
}
)->map(function ($answerOption) use ($deleted_ids) {
// New entry (you can add your custom code here)
$answerOption['id'] = $deleted_ids->pop();
return new AnswerOption($answerOption);
});
$this->answerOptions()->saveMany($attachments);
}
}
AnswerOption 模型
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class AnswerOption extends Model
{
protected $table = 'answer_options';
protected $fillable = [
'question_id',
'title',
'ord',
'created_at',
'updated_at'
];
/**
* Get the question that owns the answer.
*/
public function question()
{
return $this->belongsTo('App\Models\Question');
}
}
在这里你可以看到一个问题有很多答案选项,你可以看到我在模型中使用了 BelongsTo , hasMany 关系
现在在 QuestionController 中保存和更新问题时,您还可以保存答案选项。
为此,我在问题模型中编写了syncAnswerOptions方法。
您只需要传递带有 id 的选项数组,如果 id 已经存在于数据库中,那么它将更新,如果 id 为空,它将添加一条新记录,如果 id 存在但不在您的新记录中数组,则该记录将被删除。
/**
* If you are attaching AnswerOption(s) for the first time, then pass
* in just the array of attributes:
* [
* [
* // answer option attributes...
* ],
* [
* // answer option attributes...
* ],
* ]
*//**
* If you are attaching new AnswerOption(s) along with existing
* options, then you need to pass the `id` attribute as well.
* [
* [
* 'id' => 24
* ],
* [
* // new answer option attributes...
* ],
* ]
*/
在问题控制器的存储和更新方法中,在问题添加和更新调用之后调用此方法。
$question->syncAnswerOptions($data['answerOptions']);
$data['answerOptions'] 是答案选项数组,就像评论中描述的那样。
我在 Laravel 中设置了以下关系:
OrderStatus Model
- hasMany('Order')
Order Model
- 'belongsTo('OrderStatus');
数据库设置有 orders
table 和 order_statuses
table。 orders
table 有一个字段用于 order_status_id
。
当我保存订单时,我通过获取适当的订单状态模型手动设置 order_status_id
,如下所示:
$status = OrderStatus::where(['name'=>'sample_status'])->firstOrFail();
$order->order_status_id = $status->id;
$order->save();
我想知道是否有内置函数可以执行此操作而不是手动设置 order_status_id
。我在 Laravel 文档中阅读了 "Attaching a related model" 和 "Associating Models",但我无法确定这些是否适合我的用例。我认为我遇到的问题是我直接使用子模型(订单),并试图设置它的父模型。有这个功能吗?
当然可以:
$status = OrderStatus::where(['name'=>'sample_status'])->firstOrFail();
$order = new Order;
$order->status()->associate($status);
$order->save();
(status()
是 belongsTo 关系。您可能需要调整该名称)
为新的相关模型保存关系的正确方法如下:
$status = OrderStatus::where(['name'=>'sample_status'])->firstOrFail();
$order = new Order;
$status->order()->save($order);
文档 link:http://laravel.com/docs/4.2/eloquent#inserting-related-models
您可以使用自定义解决方案。
我正在解释一个例子,刚刚编码并且与您的问题非常相似,希望它能有所帮助。 我有一个 问题模型 和 AnswerOption 模型,如下所示。
问题模型
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Question extends Model
{
protected $table = 'questions';
protected $fillable = [
'title',
'created_at',
'updated_at'
];
/**
* Get the answer options for the question.
*/
public function answerOptions()
{
return $this->hasMany('App\Models\AnswerOption');
}
/**
* @param array $answerOptions
*/
public function syncAnswerOptions(array $answerOptions)
{
$children = $this->answerOptions;
$answerOptions = collect($answerOptions);
$deleted_ids = $children->filter(
function ($child) use ($answerOptions) {
return empty(
$answerOptions->where('id', $child->id)->first()
);
}
)->map(function ($child) {
$id = $child->id;
$child->delete();
return $id;
}
);
$attachments = $answerOptions->filter(
function ($answerOption) {
// Old entry (you can add your custom code here)
return empty($answerOption['id']);
}
)->map(function ($answerOption) use ($deleted_ids) {
// New entry (you can add your custom code here)
$answerOption['id'] = $deleted_ids->pop();
return new AnswerOption($answerOption);
});
$this->answerOptions()->saveMany($attachments);
}
}
AnswerOption 模型
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class AnswerOption extends Model
{
protected $table = 'answer_options';
protected $fillable = [
'question_id',
'title',
'ord',
'created_at',
'updated_at'
];
/**
* Get the question that owns the answer.
*/
public function question()
{
return $this->belongsTo('App\Models\Question');
}
}
在这里你可以看到一个问题有很多答案选项,你可以看到我在模型中使用了 BelongsTo , hasMany 关系
现在在 QuestionController 中保存和更新问题时,您还可以保存答案选项。
为此,我在问题模型中编写了syncAnswerOptions方法。
您只需要传递带有 id 的选项数组,如果 id 已经存在于数据库中,那么它将更新,如果 id 为空,它将添加一条新记录,如果 id 存在但不在您的新记录中数组,则该记录将被删除。
/**
* If you are attaching AnswerOption(s) for the first time, then pass
* in just the array of attributes:
* [
* [
* // answer option attributes...
* ],
* [
* // answer option attributes...
* ],
* ]
*//**
* If you are attaching new AnswerOption(s) along with existing
* options, then you need to pass the `id` attribute as well.
* [
* [
* 'id' => 24
* ],
* [
* // new answer option attributes...
* ],
* ]
*/
在问题控制器的存储和更新方法中,在问题添加和更新调用之后调用此方法。
$question->syncAnswerOptions($data['answerOptions']);
$data['answerOptions'] 是答案选项数组,就像评论中描述的那样。