يقوم الجدول المحوري Laravel بإنشاء الارتباط مرة واحدة، ثم التحديث

StackOverflow https://stackoverflow.com//questions/23019239

  •  21-12-2019
  •  | 
  •  

سؤال

لدي الجداول التالية:

مستخدم:

userID
...

درس:

lessonID
...

Users_Lessons_Status (الذي يعمل كجدول محوري ويحمل معلومات أخرى):

userID references User.userID
lessonID references Lessons.lessonID
latestSectionID
percentComplete

ما أريد القيام به هو أنه، لكل مستخدم، لكل درس، يجب أن يكون هناك صف في الجدول المحوري يوضح مقدار ما أكمله المستخدم في هذا الدرس وما هو معرف القسم الأخير الخاص به.وهذا يعني أنه يجب أن يكون هناك زوج فريد من نوعه userID و lessonID (المفاتيح الأساسية؟).

لقد قمت بإعداد نماذجي مثل هذا:

<?php

class User extends Eloquent implements UserInterface, RemindableInterface {

...


    public function lessonStatuses() 
    {
        return $this->belongsToMany('Lesson', 'users_lessons_status', 'lessonID', 'userID')->withPivot('latestSectionID', 'percentComplete');
    }

}

<?

class Lesson extends Eloquent {

protected $table = 'lessons';
protected $primaryKey = 'lessonID';

public function userStatuses()
{
    return $this->belongsToMany('User', 'users_lessons_status', 'userID', 'lessonID');
}


}

?>

يبدو طريقي الحالي كما يلي:

Route::post('dbm/users/setLatestSectionID', function() {
    if(Auth::check()) {
        $user = User::find(Input::get('userID'));
        $lesson = Lesson::find(Input::get('lessonID'));
        $us = $user->lessonStatuses(); 
        $us->attach($lesson->lessonID, 
            ["latestSectionID" => Input::get('latestSectionID'), "percentComplete" => Input::get('percentComplete')] );
    }
});

يعمل هذا، ولكنه يقوم بإنشاء صف جديد في كل مرة أقوم بتحديثه لنفسه userID و lessonID, ، لذلك لم يعد الزوج فريدًا.ما هي الأساليب التي يجب أن أستخدمها لهذا الغرض؟حاولت كلاهما save(), attach() و push() في الوثائق ولكني لست متأكدًا من أي منها سأستخدمه هنا.

يحرر:للتوضيح، يجب أن يبدو الجدول الناتج كما يلي:

id|userID|lessonID|latestSectionID|percentComplete
1    1      1             X             Y
2    1      2        
3    1      3         
4    2      1          
5    3      1
6    3      2
....

تحرير 2:تم إصلاح User->belongsToMany() الطريقة وأضفت withPivot يتصل.

هل كانت مفيدة؟

المحلول

يبدو الأمر وكأنه خطأ، ومع ذلك يمكنك القيام بذلك:

...->sync([$id], false); // detaching set to false, so it will only insert new rows, skip existing and won't detach anything

يحرر:كما قيل في التعليق - لن ينجح الأمر معك، لأنك تريد تعيين البيانات المحورية.لذلك لا توجد طريقة للقيام بذلك في الوقت الحالي، ولكن يجب القيام بشيء مثل هذا:

// belongsToMany.php
public function attachOrUpdate($id, array $attributes = array(), $touch = true)
{
    if ($id instanceof Model) $id = $id->getKey();

    if ( ! $this->allRelatedIds()->contains($id)) // getRelatedIds() in prior to v5.4
    {
        return $this->attach($id, $attributes, $touch); 
    }
    else if ( ! empty($attributes))
    {
        return $this->updateExistingPivot($id, $attributes, $touch);
    }
}

سأقوم باختباره، وإذا نجح، أرسل طلب سحب إلى 4.1

نصائح أخرى

لقد واجهت هذا مؤخرًا وقمت بإصلاحه بهذه الطريقة:

يستخدم updateExistingPivot أولا والتحقق من النتيجة، إذا كانت النتيجة 1 فهذا يعني أنه كان هناك صف مع نفسه userID و lessonID وتم تحديثه بنجاح، وإلا إذا كانت النتيجة 0 فهذا يعني أنه لم تكن هناك صفوف مع هذا userID و lessonID, ، حتى تتمكن من إرفاقه لإنشاء صف جديد

    $update_result = $us->updateExistingPivot($lesson->lessonID, 
            ["latestSectionID" => Input::get('latestSectionID'), "percentComplete" => Input::get('percentComplete')] );
    if($update_result == 0) {
        $us->attach($lesson->lessonID, 
            ["latestSectionID" => Input::get('latestSectionID'), "percentComplete" => Input::get('percentComplete')] );
    }

يجب أن تستخدم updateExistingPivot().

قم بتحديث الكود الخاص بك للاستخدام

    $us->updateExistingPivot($lesson->lessonID, 
        ["latestSectionID" => Input::get('latestSectionID'), "percentComplete" => Input::get('percentComplete')], true );

ستقوم المعلمة الأخيرة بتحديث الطوابع الزمنية لجميع النماذج ذات الصلة.إذا لم يكن الأمر كذلك، فيمكنك الإزالة أو التعيين على "خطأ".

إذا كنت تريد الإرفاق فقط في حالة عدم وجود سجل، فيمكنك القيام بشيء مثل هذا...

Route::post('dbm/users/setLatestSectionID', function() {
    if(Auth::check()) {
        $user = User::find(Input::get('userID'));

        $lesson = [
            "latestSectionID" => Input::get('latestSectionID'), 
            "percentComplete" => Input::get('percentComplete')
        ];

        $num_lessons = $user->lessonStatuses()->where('id', Input::get('lessonID'))->count();

        if($num_lessons == 0) {
            $user->attach($lesson->lessonID, $lesson);
        } else {
            $user->updateExistingPivot($lesson->lessonID, $lesson);

        }
    }
});
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top