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

pharmonie's avatar

How to use api routes with inertia securely?

I have the scenerio, where I have an user profile page. Inertia makes it very seamless, to send the user from the controller to the vue frontend.

In the user view, I want to display the 3 most recent purchases (of the auth user) as a MostRecentPurchases vue component and I want the component to be standalone, independed from the user's profile view, so that it is easily re-usable.

Now I'm wondering, how I am shipping the data to the component. One solution would be, to send the $user->load('purchases', function ($q) {$q->latest()->take(3);}) to the profile view and pass the purchases as a prop to the component. But this would make the component depended from the parent.

Second, I thought about making a dedicated controller and use axios.get() the fetch the data:

class MostRecentPurchasesController
{
    public function __invoke(Request $request): JsonResponse
    {
        return response()->json([
            'purchases' => $request->user()->purchases()->latest()->limit(3)->get()
        ]);
    }
}

and implement a route in the routes/api.php file.

Seems like a valuable solution, but now I want to know:

  1. is this the way to go?
  2. if yes, how to handle security here?

With

Route::middleware('auth:sanctum')
    ->get('/most-recent-purchases', MostRecentPurchasesController::class)
    ->name('api.most-recent-purchases');

I get a 401 response.

0 likes
2 replies
martinbean's avatar

@pharmonie You should be passing the data components need as props. That’s the purpose of them. It then makes your components more reusable.

So, if you pass purchase data to your MostRecentPurchases component via a prop, then your component doesn’t care where the data is coming from, just that it does get that data, so you can re-use that component where ever you need: on the user’s page, in an admin panel, inside an Inertia page, in a non-Inertia page, etc. It doesn’t care and just renders what it’s given.

<script lang="ts" setup>
type Purchase = {
    id: string;
    // Declare other purchase fields and their types here...
};

defineProps<{
    purchases: Purchase[],
}>();
</script>

<template>
  <ul>
    <li v-bind:key="purchase.id" v-for="purchase in purchases">
      <!-- Render purchase information here -->
    </li>
  </ul>
</template>
pharmonie's avatar

@martinbean Thank you for your quick reply.

What I want, is a re-usable component, that does not need parental adjustments. I want to place it, whereever I need it, without modifying the parents controllers or logic outside the component, if that makes sence.

Please or to participate in this conversation.