【问题标题】:Laravel save one to many relationshipLaravel 保存一对多关系
【发布时间】:2015-03-05 21:07:15
【问题描述】:

我在 Laravel 中建立了以下关系:

OrderStatus Model
  - hasMany('Order')

 Order Model
  - 'belongsTo('OrderStatus');

数据库设置有orders 表和order_statuses 表。 orders 表有一个字段为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 文档中阅读了有关“附加相关模型”和“关联模型”的信息,但我无法确定这些是否适合我的用例。我认为我遇到的问题是我直接使用子模型(订单),并试图将其设置为父模型。有这个功能吗?

【问题讨论】:

    标签: php laravel laravel-4 eloquent


    【解决方案1】:

    您可以使用自定义解决方案。

    我正在解释一个示例,只是编码并且与您的问题非常相似,希望对您有所帮助。 我有一个 Question ModelAnswerOption Model,如下所示。

    问题模型

    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 中保存和更新问题时,您还可以保存答案选项。

    为此,我在 Question Model 中编写了 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'] 是答案选项数组,就像 cmets 中描述的那样。

    【讨论】:

      【解决方案2】:

      为新的相关模型保存关系的正确方法如下:

      $status = OrderStatus::where(['name'=>'sample_status'])->firstOrFail();
      $order = new Order;
      $status->order()->save($order);
      

      文档链接:http://laravel.com/docs/4.2/eloquent#inserting-related-models

      【讨论】:

        【解决方案3】:

        当然可以:

        $status = OrderStatus::where(['name'=>'sample_status'])->firstOrFail();
        $order = new Order;
        $order->status()->associate($status);
        $order->save();
        

        status() 是 belongsTo 关系。您可能需要调整该名称)

        【讨论】:

        • 哦,哇,看起来确实有效。我的问题是我没有在associate() 之后调用save()。所以associate() 只是更新$order 上的order_status_id 字段的值,但实际上并没有触及数据库?
        • 正是它的作用:)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-09-02
        • 2011-07-12
        • 2017-07-17
        • 2017-05-09
        • 2017-08-20
        • 1970-01-01
        • 2015-12-06
        相关资源
        最近更新 更多