Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jimb814's avatar

Query Builder quandary in livewire component

Problem: how to get results from a query and then search only those results

I have a treatments table but want to display only the treatments assigned to a particular dentist.

I am using mount() to bring in the logged in dentist's user ID like this:

public function mount()
{
    $this->dentist_id = Auth::id();
}

I verified that the ID is being passed successfully.

This works:

public function render()
{
        $query = '%'.$this->search.'%';

        return view('livewire.treatments-table', [
            'treatments' => DB::table('treatments')
                ->join('users', 'users.id', 'treatments.patient_user_id')
                ->join('patients', 'patients.user_id', 'treatments.patient_user_id')
                ->join('dentists', 'dentists.user_id', 'treatments.dentist_user_id')
                ->select(
                    .....
                )
		->where('treatments.dentist_user_id', $this->dentist_id)
                ->where('treatments.status', 'like', $query)
                ->orWhere('patients.first_name', 'like', $query)
                ->orWhere('patients.last_name', 'like', $query)
                ->orWhere('dentists.name', 'like', $query)
                ->orWhere('users.email', 'like', $query)
                ->orWhere('patients.state', 'like', $query)
                ->orderBy($this->orderBy, $this->orderDirection ? 'DESC' : 'ASC')
                ->paginate($this->perPage)
        ]);
}

Except, when I hard-code a different dentist ID in the first where clause like this:

public function render()
{
        $query = '%'.$this->search.'%';

        return view('livewire.treatments-table', [
            'treatments' => DB::table('treatments')
                ->join('users', 'users.id', 'treatments.patient_user_id')
                ->join('patients', 'patients.user_id', 'treatments.patient_user_id')
                ->join('dentists', 'dentists.user_id', 'treatments.dentist_user_id')
                ->select(
                    .....
                )
                ->where('treatments.dentist_user_id', 34)
                ->where('treatments.status', 'like', $query)
                ->orWhere('patients.first_name', 'like', $query)
                ->orWhere('patients.last_name', 'like', $query)
                ->orWhere('dentists.name', 'like', $query)
                ->orWhere('users.email', 'like', $query)
                ->orWhere('patients.state', 'like', $query)
                ->orderBy($this->orderBy, $this->orderDirection ? 'DESC' : 'ASC')
                ->paginate($this->perPage)
        ]);
}

it returns all records instead of only the records of the dentist where ID == 34.

When I remove the additional where clauses like this:

public function render()
{
        $query = '%'.$this->search.'%';

        return view('livewire.treatments-table', [
            'treatments' => DB::table('treatments')
                ->join('users', 'users.id', 'treatments.patient_user_id')
                ->join('patients', 'patients.user_id', 'treatments.patient_user_id')
                ->join('dentists', 'dentists.user_id', 'treatments.dentist_user_id')
                ->select(
                    .....
                )
                ->where('treatments.dentist_user_id', 34)
                ->orderBy($this->orderBy, $this->orderDirection ? 'DESC' : 'ASC')
                ->paginate($this->perPage)
        ]);
}

it correctly returns the records for Dentist where ID = 34.

I have attempted a number of query variations with no success.

In SQL, I am trying something like this:

SELECT * 
FROM `treatments` 
JOIN()
JOIN()
JOIN()
WHERE treatments.dentist_user_id = 1
AND patients.first_name LIKE %$query%
OR patients.last_name LIKE %$query%
OR
OR
etc
. . . .

If anyone can help me understand where my error(s) are, I would greatly appreciate it!

For reference, here's the entire component:

<?php

namespace App\Http\Livewire;

use App\Models\Treatment;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Livewire\Component;
use Livewire\WithPagination;

class TreatmentsTable extends Component
{
    use WithPagination;
    
    public $search = '';
    public $perPage = 10;
    public $orderDirection = true;  // DESC = true
    public $orderBy = 'treatments.id';
    public $dentist_id;
    public $status;

    public function mount()
    {
        $this->dentist_id = Auth::id();
    }

    public function updatingSearch()
    {
        $this->resetPage();
    }
    
    public function render()
    {
        $query = '%'.$this->search.'%';

        return view('livewire.treatments-table', [
            'treatments' => DB::table('treatments')
                ->join('users', 'users.id', 'treatments.patient_user_id')
                ->join('patients', 'patients.user_id', 'treatments.patient_user_id')
                ->join('dentists', 'dentists.user_id', 'treatments.dentist_user_id')
                ->select(
                    'treatments.dentist_user_id AS dentist_user_id', 
                    'dentists.id AS dental_practice_id', 
                    'dentists.name AS dental_practice_name', 
                    'dentists.phone AS dental_practice_phone', 
                    'dentists.dentist AS dentist_name',
                    'dentists.address1 AS dental_address1', 
                    'dentists.address2 AS dental_address2', 
                    'dentists.city AS dental_city', 
                    'dentists.state AS dental_state', 
                    'dentists.zip AS dental_zip',

                    'patients.user_id AS patient_user_id', 
                    'patients.first_name AS patient_first_name', 
                    'patients.last_name AS patient_last_name', 
                    'patients.phone AS patient_phone', 
                    'users.email AS patient_email', 
                    'patients.address1 AS patient_address1', 
                    'patients.address2 AS patient_address2', 
                    'patients.city AS patient_city', 
                    'patients.state AS patient_state', 
                    'patients.zip AS patient_zip', 

                    'treatments.id AS treatment_id', 
                    'treatments.status', 
                    'treatments.treatment', 
                    'treatments.amt_presented', 
                    'treatments.amt_accepted',
                    'treatments.created_at AS treatment_date'
                )
                ->where('treatments.dentist_user_id', $this->dentist_id)
                ->where('treatments.status', 'like', $query)
                ->orWhere('patients.first_name', 'like', $query)
                ->orWhere('patients.last_name', 'like', $query)
                ->orWhere('dentists.name', 'like', $query)
                ->orWhere('users.email', 'like', $query)
                ->orWhere('patients.state', 'like', $query)
                ->orderBy($this->orderBy, $this->orderDirection ? 'DESC' : 'ASC')
                ->paginate($this->perPage)
        ]);
    }
}
0 likes
3 replies
CorvS's avatar

@jimb814 The issue with your query is that you are not grouping your where clauses correctly. You want all treatments from a given dentist (id) AND other conditions, so just group the other conditions:

...
->where('treatments.dentist_user_id', $this->dentist_id)
->where(function($q) use ($query) {
    $q->where('treatments.status', 'like', $query);
    $q->orWhere('patients.first_name', 'like', $query);
    ...
})
...

Otherwise you are querying for a dentist that matches the given id OR any of the other conditions.

jimb814's avatar

@nimrod Thanks, I think our queries match. I did not see your post before posting my update. The functionality is now working properly. Only the treatment records of the logged in dentist display and the records are searchable by the listed fields.

jimb814's avatar

UPDATE

This query works with the search functionality.

 ->where('treatments.dentist_user_id', $this->dentist_id)
            ->where(function ($q) use ($query) {
                $q->where('treatments.status', 'like', $query)
                    ->orWhere('patients.first_name', 'like', $query)
                    ->orWhere('patients.last_name', 'like', $query)
                    ->orWhere('dentists.name', 'like', $query)
                    ->orWhere('users.email', 'like', $query)
                    ->orWhere('patients.state', 'like', $query);
 })
    ->orderBy($this->orderBy, $this->orderDirection ? 'DESC' : 'ASC')
    ->paginate($this->perPage)

The search functionality sees the dentist's ID and returns the correct data, but the problem is that all treatment records display @ /treatments.

I want to display only the records for the logged in dentist.

I want to fetch the treatment records for the logged in dentist and then use livewire's search functionality on those records.

Please or to participate in this conversation.