Search code examples
phplaraveleloquentlaravel-livewire

Why query result suddenly changed after called from other medthod in Laravel


I have problem here with query result from Eloquent, I tried to query from DB and put in variable $contractList in my mount() method and the result as expected. But when I tried to retrieve specific data from $contractList with $contractList->find($id), the result not same as in mount() method.

Here is query from mount():

public function mount(){
$contractList = Kontrak::select(['id', 'mou_id'])->with(['order:id,kontrak_id', 'order.worklist:id', 'order.worklist.khs:id,mou_id,worklist_id,khs', 'amdNilai:id,kontrak_id,tgl_surat'])->withCount('amdNilai')->get()
}

Here the result: enter image description here

But when I tried to find specific data from $contractList, properties that shown not same as in mount:

    public function itemSelected($id)
    {
        //amd_nilai_count not showing
        $kontrak = $this->contractList->find($id);
        if ($kontrak->amd_nilai_count == 1) {
            $this->nilai_amd = $this->calculateNilai($id);
        }
    }

Here is the result called from itemSelected(): enter image description here

I have tried use get() but the result still problem, how to get same properties same as in mount().By the way im use laravel & livewire.


Solution

  • As i read your comments you seem to mix up ActiveRecords ORM with an Data Mapper ORM. Laravel uses active records.

    Laravel will always fetch models on every data operation.

    Kontrak::select('name')->find(1); // select name from kontraks where id = 1;
    
    Kontrak::find(1); // select * from kontraks where id = 1;
    

    This will always execute two SQL calls no matter what and the objects on the heap will not be the same. If you worked with Doctrine or similar, this would be different.

    To combat this you would often put your logic in services or similar.

    class KontrakService
    {
        public function find(int $id) {
            return Kontrak::select(['id', 'mou_id'])->find($id);
        }
    }
    

    Whenever you want the same logic, use that service.

    resolve(KontrakService::class)->find(1);
    

    However, many relationship operations is hard to do with this and then it is fine to just fetch the model with all the attributes.