Heim  >  Fragen und Antworten  >  Hauptteil

Optimieren Sie Laravel Join, um alle Daten in einer einzelnen Zeile abzurufen, ohne Tabellen zu duplizieren

Ich habe 4 MySQL-Tabellen und verwende PHP und Laravel 7

  1. Mitglieder
  2. Abzug
  3. Zahlung
  4. Zahlungsabzüge

Jetzt möchte ich die Einzelzahlung und alle anderen Abzüge jedes Mitglieds fortlaufend anzeigen. (Angenommen, eine Person hat nur eine Zahlung)

Die Datenbankstruktur ist wie folgt

Dies ist die HTML-Tabelle, die ich anzeigen möchte

Dies ist die Abfrage, die ich verwende, aber sie dupliziert die Daten.

$payments = Payment::leftJoin('members', 'payments.member_id', '=', 'members.id')
        ->leftJoin('payment_deductions', 'payments.id', '=', 'payment_deductions.payment_id')
        ->leftJoin('deductions', 'payment_deductions.deduction_id', '=', 'deductions.id')
        ->select(
            'members.*',
            'payment_deductions.*',
        )
        ->orderBy("member_id", "ASC")
        ->get()->toArray();

Das resultierende Array wiederholt jedes Mitglied basierend auf seiner Ableitung.

Gibt es eine Möglichkeit, diese Daten zu verbessern? So etwas wie eine verschachtelte Reihe von Abzügen für jedes Mitglied?

Das ist das Modell

Mitglied

namespace App;

    use IlluminateDatabaseEloquentModel;
    use CarbonCarbon;

    class Member extends Model
    {
        protected $fillable = [
            'full_name',
            'email',
            'created_by',
        ];
    }

Zahlung

namespace App;

    use IlluminateDatabaseEloquentModel;

    class Payment extends Model
    {
        protected $fillable = [
            'member_id',
            'total_amount',
            'payable_amount',
            'created_by',
        ];

        public function deductions() {
           return $this->belongsToMany(Deduction::class,'payment_deductions')->withTimestamps();
        }
    }

Abzug

namespace App;

    use IlluminateDatabaseEloquentModel;

    class Deduction extends Model
    {
        protected $fillable = [
        'title',
        'priority',
        'created_by',
        ];
    }


P粉410239819P粉410239819251 Tage vor415

Antworte allen(1)Ich werde antworten

  • P粉239089443

    P粉2390894432024-01-17 09:20:05

    在构建模型时,您非常接近并且处于正确的轨道上,您缺少的是如何在不创建另一个查询的情况下加载关系,如果您查看控制器,您将看到加载内部关系的标准方法。希望这是一个更好的概念来解决您的担忧。

    供参考:https://laravel.com/ docs/9.x/eloquent-relationships#lazy-eager-loading

    这样做也可以避免将来的 N+1 问题,请参阅什么是 ORM(对象关系映射)中的“N+1 选择问题”? 有关 N+1 的详细信息< /p>

    会员模型

    public class Member extends Model
    {
        protected $fillable = [
           'full_name',
           'email',
           'created_by',
        ];
            
        public function payments(){
            return $this->hasMany(Payment::class);
        }
    }

    支付模式

    public class Payment extends Model
    {
        protected $fillable = [
           'member_id',
           'total_amount',
           'payable_amount',
           'created_by',
        ];
            
        public function member(){
            return $this->belongsTo(Member::class);
        }
    
        public function deductions() {
            return $this->belongsToMany(Deduction::class,'payment_deductions')->withTimestamps();
        }
    }

    推演模型

    public class Deduction extends Model
    {
        protected $fillable = [
           'title',
           'priority',
           'created_by',
        ];
            
        public function payments() {
            return $this->belongsToMany(Payment::class,'payment_deductions')->withTimestamps();
        }
    }

    成员控制器:

    /**
     * Show the specified model.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  Member $member
     * @return \Illuminate\Http\Response
     */
    public function show(Request $request, Member $member){
        // This will load all of the inner relationships in a single query.
        $member->load('payments.deductions');
            
        //Assign the loaded payments to be used
        $payments = $member->payments;
            
        /* 
            You can acess the payments -> deductions in a foreach loop, in php or blade
            foreach($payments->deductions as $deduction){
               //$deduction->id   
            }
        */  
            
        return view('sampleView', compact('member', 'payments'));
    }

    Antwort
    0
  • StornierenAntwort