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

stigo-rigo's avatar

LARAVEL API PAGINATION & FILTER WITH THE SAME END POINT

I'm using laravel for my api and vue 3 for frontend. I want to display the paginated results on a table, and filter the table column by type, phone , date and status. I am currently getting the paginated Data results on my table, but I want to get both paginatedData and search results with one api endpoint... This is my controller:

public function paginatedData(Request $request)
    {
        return NewsRequest::paginate($request->page_size);
    }

public function search(Request $request)
    {
        $query = NewsRequest::query();

        if ($res = $request->input(key:'s')) {
            $query->where('phone', 'LIKE', '%' . $res . '%')
            ->orwhere('type', 'LIKE', '%' . $res . '%');
        }
        return $query->get();
    }

In my vue js, I have this:

<template>
  <div class="w-full">
    <div class="flex justify-end mb-5">
      <button type="button" class="text-white bg-green-500 hover:bg-green-400 font-medium rounded-sm text-sm px-10 py-2.5 text-center mr-5 inline-flex items-center"><fa icon="file-excel" class="mr-2" />Export to .csv</button>
    </div>
  </div>

  <div class="grid grid-cols-5 gap-8 text-gray-500 items-center px-5 mb-8">
    <div>
      <label for="">Phone</label>
      <input type="text" class="form-input block p-2 w-full text-gray-700 bg-gray-50 rounded-sm border border-gray-300 sm:text-sm" 
        v-model="filters.phone" @change="index"
      />
    </div>
    <div>
      <label for="">Type</label>
      <input type="text" class="form-input block p-2 w-full text-gray-700 bg-gray-50 rounded-sm border border-gray-300 sm:text-sm" 
        v-model="filters.type" @change="index"
      />
    </div>
    <div>
      <label for="">Status</label>
      <input type="text" class="block p-2 w-full text-gray-700 bg-gray-50 rounded-sm border border-gray-300 sm:text-sm" 
        v-model="filters.status" @change="index"
      />
    </div>
    <div>
      <label for="">From</label>
      <input type="date" class="block p-2 w-full text-gray-700 bg-gray-50 rounded-sm border border-gray-300 sm:text-sm" 
        v-model="filters.from" @change="index"
      />
    </div>
    <div>
      <label for="">To</label>
      <input type="date" class="block p-2 w-full text-gray-700 bg-gray-50 rounded-sm border border-gray-300 sm:text-sm" 
        v-model="filters.to" @change="index"
      />
    </div>
  </div>

  <!-- table -->
  <div class="min-w-full px-5">
    <table class="divide-gray-200 divide-y border w-full">
      <thead class="bg-gray-50">
        <tr>
          <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-600 uppercase tracking-wider">#</th>
          <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-600 uppercase tracking-wider">phone</th>
          <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-600 uppercase tracking-wider">type</th>
          <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-600 uppercase tracking-wider">status</th>
          <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-600 uppercase tracking-wider">date</th>
        </tr>
      </thead>
      <tbody class="bg-white divide-y divide-gray-200">
        <tr v-for="(value, key) in response.data" :key="key">
          <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ (response.current_page - 1) * 10 + key + 1 }}</td>
          <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ value.phone }}</td>
          <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ value.type }}</td>
          <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ value.status }}</td>
          <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ value.created_at }}</td>
        </tr>
      </tbody>
    </table>
  </div>

  <div class="mb-10">
  </div>
</template>

<script>
import axios from "axios"

export default {
  name: "TheData",

  data() {
    return {
      filters: {
        phone: '',
        type: '',
        status: '',
        from: '',
        to: '',
      },
      response: {
        data: [],
        current_page: 1
      }
    }
  },

  mounted() {
    let today = new Date()
    let tomorrow = new Date(today)
    tomorrow.setDate(tomorrow.getDate() + 1)
    this.filters.from = today.toJSON().slice(0, 10)
    this.filters.to = tomorrow.toJSON().slice(0, 10)

    this.index()
  },

  methods: {
    async index() {
      const { data } = await axios.get(process.env.VUE_APP_API_URL + 'data/table?page_size=10&page=' + this.response.current_page,
        {
          params: this.filters
        }
      )

      this.response = data
      console.log('response', this.response)
    },

  },
}
</script>

<style></style>

0 likes
5 replies
jlrdw's avatar

Paginate at final, not get().

MohamedTammam's avatar

@stigo-rigo He means to replace that line

return $query->get();

With that

return $query->paginate();
1 like
jlrdw's avatar

@stigo-rigo

Sorry, I don't understand.

$query->get()

Does not paginate results. Do a query with search and paginate. At end, I meant end where your final code get() is.

1 like

Please or to participate in this conversation.