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

james1232's avatar

Passing Data in Laravel with Inertia: Controller vs. API Calls in Vue Components – Which is Better Design?

Is it better design to pass data through a Laravel index method like this:

public function index()
{
    $events = Event::paginate(10);
    return Inertia::render('Event/Index', [
        'events' => $events,
    ]);
}

Or should the web EventController index method look like this:

public function index()
{
    return Inertia::render('Event/Index');
}

and call the API from the Vue component like this:

<script setup>
import { ref, onMounted } from 'vue';
import axios from 'axios';

const events = ref([]);
const pagination = ref({});

const fetchEvents = async (page = 1) => {
  try {
    const response = await axios.get(`/api/events?page=${page}`);
    events.value = response.data.data;
    pagination.value = response.data;
  } catch (err) {
    console.error('Error fetching events:', err);
  }
};
onMounted(fetchEvents);
</script>

<template>
  <div>
    <ul>
      <li v-for="event in events" :key="event.id">{{ event.name }}</li>
    </ul>
  </div>
</template>

Controller\Api\EventController.php:

    public function index()
    {
        $events = Event::paginate(10);
        return response()->json($events);
    }
0 likes
5 replies
LaryAI's avatar
Level 58

When deciding between passing data directly from a Laravel controller to an Inertia component or fetching it via an API call in a Vue component, consider the following factors:

1. Data Fetching Strategy

  • Controller Method:

    • Pros:
      • Simplicity: Directly passing data from the controller to the component is straightforward and requires less boilerplate.
      • Performance: Reduces the number of HTTP requests since data is fetched server-side and passed directly to the view.
    • Cons:
      • Less dynamic: If you need to update the data without a full page reload, you'll need additional logic.
  • API Call in Vue Component:

    • Pros:
      • Flexibility: Allows for more dynamic data fetching and updating without reloading the page.
      • Reusability: The API can be reused across different components or even different applications.
    • Cons:
      • Complexity: Requires setting up an API endpoint and handling asynchronous data fetching in the component.
      • Performance: Involves an additional HTTP request, which might impact performance.

2. Use Case Considerations

  • If your application requires real-time updates or frequent data changes without reloading the page, using an API call in the Vue component might be more appropriate.
  • For simpler applications or pages where data doesn't change often, fetching data in the controller and passing it directly to the component can be more efficient.

3. Example Implementation

Controller Method:

public function index()
{
    $events = Event::paginate(10);
    return Inertia::render('Event/Index', [
        'events' => $events,
    ]);
}

API Call in Vue Component:

  1. Controller Method:
public function index()
{
    return Inertia::render('Event/Index');
}
  1. API Endpoint:
public function apiIndex()
{
    return Event::paginate(10);
}
  1. Vue Component:
<script setup>
import { ref, onMounted } from 'vue';
import axios from 'axios';

const events = ref([]);
const pagination = ref({});

const fetchEvents = async (page = 1) => {
  try {
    const response = await axios.get(`/api/events?page=${page}`);
    events.value = response.data.data;
    pagination.value = response.data;
  } catch (err) {
    console.error('Error fetching events:', err);
  }
};
onMounted(fetchEvents);
</script>

<template>
  <div>
    <ul>
      <li v-for="event in events" :key="event.id">{{ event.name }}</li>
    </ul>
  </div>
</template>

Conclusion

Choose the approach that best fits your application's needs. For static or less frequently changing data, the controller method is efficient. For dynamic, frequently updated data, consider using an API call in the Vue component.

james1232's avatar

Followup question: How would I test using the component with the internal API call with my feature test? When I pass the data via props the test I use to assertsee the generate event works but when I use the internal API call to get the data it doesn't pass. Would I need to call the API in the test itself to get the fake event or is there a function to run the test with the API call used in the component? If I call the API endpoint in the test then wouldn't this not show the true outcome since I'm not actually testing the call in the component?

martinbean's avatar

@james1232 The entire point of Inertia is to use it as per your first example, so you don’t have to build a client-rendered app that makes API calls to get data.

Either use Inertia as intended, or build a SPA if you prefer to have JavaScript make API calls to get data for components.

1 like
james1232's avatar

@martinbean So what I'm reading is that I'm making the mistake of combining the two approaches and not using Inertia for what it's intended to do.

What I wanted was to have my EventsController to only be responsible for rendering the view and an endpoint to be responsible for providing the data. But if I am reading your response correctly the thing I'm describing is a SPA application and I'm trying to shoehorn that approach into an inertia application which is not what its intended use is?

martinbean's avatar

@james1232 Correct. The entire point of Inertia is to avoid having to create API endpoints to make JavaScript-powered front-ends. That’s why you pass view data in the Inertia::render method call. That data is then passed to a page component as component props.

If you’re going to make Inertia pages, but not pass data to those page components and instead have those page components make API requests to get their data, then that’s just building a traditional SPA and forego using Inertia.

1 like

Please or to participate in this conversation.