Laravel Eloquent ORM โดยที่ผ่านตาราง

สวัสดี ฉันมีปัญหากับ Laravel บนไซต์ของฉัน การค้นหาหมายเลขโทรศัพท์ ผมพยายามเลือกสถานที่ที่มีเมืองที่ผมเลือกผ่านตารางการติดต่อ

คลาสโมเดลของฉัน: คลาสสถานที่:

class Places extends Eloquent {
    public function contacts()
    {
        return $this->hasOne('Contacts');
    }
     public function clubs()
     {
        return $this->hasOne('Clubs');
     }    
}

คลาสผู้ติดต่อ:

 class Contacts extends Eloquent {
     public function cities()
     {
         return $this->hasOne('Cities');
     }
   }

ระดับเมือง:

 class Cities extends Eloquent {

 }

คำถามของฉัน:

$view->clubs = Places::whereHas('contacts',function ($q) use($city_id){
           $q->where('contacts', function ($q) use($city_id){
               $q->where('id', $city_id);
            });
        })->get();

ข้อความแสดงข้อผิดพลาด:

เวอร์ชันเซิร์ฟเวอร์ MySQL สำหรับไวยากรณ์ที่ถูกต้องเพื่อใช้ใกล้ 'โดยที่ id = ?)) >= 1' ที่บรรทัด 1 (SQL: เลือก * จาก places โดยที่ (เลือกจำนวน (*) จาก contacts โดยที่ contacts.places_id = places.id และ contacts = (เลือก * โดยที่ id = 2223)) >= 1)

ฉันรู้ว่ามันหายไป "จาก" citites แต่ฉันไม่รู้ว่าจะต้องทำอย่างไร ความสัมพันธ์ของโมเดล


person Piotr Suchanek    schedule 07.08.2014    source แหล่งที่มา
comment
สถานที่มีผู้ติดต่อเพียงรายเดียวและผู้ติดต่อมีเมืองเดียวเท่านั้น ดังนั้นสถานที่จะมีเพียงเมืองเดียว ถูกต้องหรือไม่?   -  person RMcLeod    schedule 07.08.2014


คำตอบ (3)


คุณมี 3 ตัวเลือกโดยใช้ความสัมพันธ์:

1 วิธีแก้ปัญหาที่ตรงไปตรงมาที่สุด:

Places::whereHas('contacts',function ($q) use ($city_id){
       $q->whereHas('cities', function ($q) use ($city_id){
           $q->where('id', $city_id);
        });
    })->get();

2 เช่นเดียวกับด้านบน แต่ใช้ PR นี้: https://github.com/laravel/framework/pull/4954

Places::whereHas('contacts.cities', function ($q) use ($city_id){
        $q->where('id', $city_id);   
    })->get();

3 การใช้ความสัมพันธ์ hasManyThrough:

// Place model
public function cities()
{
  return $this->hasManyThrough('City', 'Contact');
}

// then
Places::whereHas('cities',function ($q) use ($city_id){
   $q->where('cities.id', $city_id);
})->get();

แก้ไข

การมีสคีมาของคุณเห็นได้ชัดว่าไม่มีคำแนะนำหรือการตั้งค่าดั้งเดิมของคุณที่สามารถใช้งานได้

นี่เป็นความสัมพันธ์แบบกลุ่มต่อกลุ่มซึ่งในภาษา Eloquent คือ belongsToMany:

// Places model
public function cities()
{
  return $this->belongsToMany('Cities', 'contacts', 'places_id', 'cities_id')
    ->withPivot( .. contacts table fields that you need go here.. );
}

// Cities model
public function places()
{
  return $this->belongsToMany('Places', 'contacts', 'cities_id', 'places_id')
    ->withPivot( .. contacts table fields that you need go here.. );
}

จากนั้นคุณสามารถเรียกความสัมพันธ์ได้ดังนี้:

$city = Cities::first();
$city->places; // collection of Places models

// contacts data for a single city-place pair
$city->places->first()->pivot->open_hours; // or whatever you include in withPivot above

ตอนนี้มีวิธีการตั้งค่าอีกวิธีหนึ่ง ในกรณีที่คุณต้องการโมเดล Contacts ด้วย:

// Places model
public function contact()
{
  return $this->hasOne('Contacts', 'places_id');
}

// Contacts model
public function city()
{
  return $this->belongsTo('Cities', 'cities_id');
}

public function place()
{
  return $this->belongsTo('Places', 'places_id');
}

// Cities model
public function contact()
{
  return $this->hasOne('Contacts', 'cities_id');
}

แล้ว:

$city = Cities::first();
$city->contact; // Contacts model
$city->contact->place; // Places model

hasManyThrough จะไม่ทำงานที่นี่เลย

person Jarek Tkaczyk    schedule 07.08.2014
comment
ฉันพยายามทำตั้งแต่ต้นเหมือนตัวเลือก 2 แต่ฉันได้รับข้อผิดพลาดนี้: การเรียกไปยังวิธีการที่ไม่ได้กำหนด Illuminate \ Database \ Query \ Builder :: contacts.cities () แม้ว่าฉันจะมีในฟังก์ชั่นผู้ติดต่อของคลาส: เมืองฟังก์ชั่นสาธารณะ () ทำไม - person Piotr Suchanek; 07.08.2014
comment
@PiotrSuchanek อย่างที่ฉันเขียนสามารถทำได้ด้วยการประชาสัมพันธ์ที่ฉันเชื่อมโยง ขณะนี้ยังไม่รองรับใน Eloquent คุณสามารถใช้ที่ 1 แทนได้ในขณะนี้ หรือดึง PR นั้นของฉันก็ได้ - person Jarek Tkaczyk; 07.08.2014
comment
สวัสดี ฉันลองทั้งสองวิธีแล้วได้รับข้อผิดพลาดที่คล้ายกัน: คอลัมน์ที่ไม่รู้จัก 'citys.contacts_id' ใน 'on clause' (SQL: select * from places โดยที่ (select count(*) from cities inner join contacts on contacts.id = cities .contacts_id โดยที่ places.id = contacts.places_id และ cities.id = 2223) ›= 1) Table Cities ไม่มีคอลัมน์ contacts_id ตารางสถานที่ก็มี มีวิธีแก้ปัญหาอะไรบ้าง? - person Piotr Suchanek; 08.08.2014
comment
ชื่อคีย์ต่างประเทศคืออะไร? คุณมีชื่อรุ่นพหูพจน์ซึ่งไม่ใช่สิ่งที่ Eloquent คาดหวัง นั่นเป็นเหตุผลที่มันพยายามเดาคีย์ (เนื่องจากคุณไม่ได้ระบุมันในความสัมพันธ์) และค้นหา contacts_id ในขณะที่ฉันคิดว่ามันคือ contact_id - person Jarek Tkaczyk; 08.08.2014
comment
ฉันเพิ่มสิ่งนี้: return $this-›hasManyThrough('Cities', 'Contacts', 'cities_id','contacts_id'); และยังคงได้รับข้อผิดพลาดเดิม ฉันยังเพิ่มรูปภาพในคำถามซึ่งสามารถช่วยได้ - person Piotr Suchanek; 08.08.2014
comment
เพื่อน คุณมีความสัมพันธ์แบบ M-M ที่นั่น! นี่คือ belongsToMany หรือ hasOne+belongsTo หากคุณต้องการโมเดลเดือย ตรวจสอบการแก้ไขในอีกสักครู่ - person Jarek Tkaczyk; 08.08.2014
comment
ขอบคุณคนที่คุณช่วยชีวิตพื้นที่ ดีแล้วทำต่อไป - person ahmednawazbutt; 25.03.2021

เมื่อคุณทราบรหัสเมืองแล้ว และจากนี้ คุณต้องการค้นหาสถานที่ที่เกี่ยวข้อง คุณสามารถเริ่มต้นที่เมืองและทำงานกลับไปยังสถานที่นั้นได้ เพื่อจะทำสิ่งนี้ คุณจะต้องนิยามความสัมพันธ์แบบผกผัน

// Add this function to your Cities Model
public function contact()
{
    return $this->belongsTo('Contact');
}


// Add this function to your Contacts Model
public function place()
{
     return $this->belongsTo('Places');
}

ตอนนี้คุณสามารถสอบถามเมืองและค้นหาสถานที่ได้

$place = Cities::find($city_id)->contact->place;

แก้ไข: เพิ่มการส่งคืนที่ขาดหายไปในฟังก์ชัน

person RMcLeod    schedule 07.08.2014
comment
ฉันลองสิ่งนี้และได้รับข้อผิดพลาดนี้: วิธีความสัมพันธ์ต้องส่งคืนออบเจ็กต์ประเภท Illuminate\Database\Eloquent\Relations\Relation - person Piotr Suchanek; 07.08.2014
comment
สิ่งนี้จะใช้ได้ในกรณีของคุณเช่นกัน แต่มี return หายไปในตัวอย่าง @RMcLeod เพียงเพิ่มคำสั่ง return ให้กับทั้งสองวิธีและมันจะใช้งานได้ - person Jarek Tkaczyk; 07.08.2014

person    schedule
comment
คำตอบนี้จะได้รับการปรับปรุงอย่างมากหากคุณสามารถอธิบายวิธีการแก้ปัญหาได้ :) - person geisterfurz007; 10.07.2019