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

richard's avatar

No worries, you can ask as many questions. :)

An invoice belongs to an order. (as we defined above)

So you need to make an order before creating an invoice (even in real world), not vice versa.

So you should create order

$order = Order::create($your_order_data);

$order->invoice()->create($your_invoice_data); // It will automatically fill order_id = $order->id
yansusanto's avatar

Sorry I don't get it sir. I already have an order saved (created) with an id

$order = Order::create($your_order_data); // what does $your_order_data means?
richard's avatar

Do you have the invoice for that order too? or you need to create one?

yansusanto's avatar

I have a form to send an invoice to an existing order. So I'm trying to save those details in the invoice table.

richard's avatar

Ah ok. When you submit the form, find the order using the id


$order = Order::find($request->get('order_id')); // I hope you have this $request->get('order_id') from the form.

$order->invoice()->create($request->all()); 

or you can do this old school way

$data = [
    'order_id' => $request->get('order_id')
    'amount' => $request->get('amount')
    etc
];

$invoice = Invoice::create($data);
yansusanto's avatar

While this starts to make sense to me, I'm having the idea that eloquent will automatically attach the id to database as I'm able to view {{ $order->details }} on the form. That was my limited knowledge of Eloquent.

That's why I having using this earlier

$invoice->order()->create($request->all()); 

OK back to your suggestion above

$order = Order::find($request->get('order_id')); 

Are you saying I need to have a form field with the order_id first?

richard's avatar

First of all, this $invoice->order()->create($request->all()); will attempt to create an order and not an invoice. We are interested in creating an invoice here.

<input type="hidden" name="order_id" value="{{ order->id }}">

When you are well acquainted will Laravel, you will learn about Form Model Binding will take care of this scenario

yansusanto's avatar
    public function sendInvoice(Request $request)
    {

        $order = Order::find($request->get('order_id')); 

        $order->invoice()->create($request->all()); 

        return view('admin.admin');

    }

OK, using the above function, I'm able to save the data with an order id but it throws an error

Undefined variable: orders

geowrgetudor's avatar

do you have any $orders variable in your admin/admin.blade.php ?

yansusanto's avatar

@geowrge yes I have a list of all the orders with $orders variable in the admin page so when I click the order, I will bring me to a form populated with order details (I don't use form binding here) that will send invoice to THAT order.

geowrgetudor's avatar

Well, you are returning that view without orders.

Maybe you should use redirect back instead of return view.

yansusanto's avatar

gosh, always making this kind of mistake. yes, it's redirecting properly now....

Thanks @geowrge

And @richard thank so much for guiding me along. you're awesome ;)

1 like
yansusanto's avatar

Hi guys,

It's me again. Now that I have another issue (as always) of displaying data from two tables.

In my controller

    public function show($id)
    {

    // how do I reference the Invoice table here?

        $order = auth()->user()->orders()->find($id); 

        return view('invoice')->withOrder($order);

    }

This is where user can view his invoice: name, address, his order details, etc...

Now how do I call up data from the invoice table such as amount payable, due date, etc.

Many thanks!

willvincent's avatar

Are you passing in an order id there? Why are you could through the auth user/etc chain to get that order?

Why not just this?

public function show ($id) {
  $order = Order::with('invoice')->findOrFail($id);

  return view('invoice')->with(compact('order'));
}

or if you don't care about the order at this point, but that's still an order ID being passed in..

public function show ($id) {
  $invoice = Invoice::where('order_id', $id)->first();

  return view('invoice')->with(compact('invoice'));
}

In any case, it would be helpful if you were more explicit. It's entirely unclear what the point of that show method is, what's being passed in, etc.

1 like
yansusanto's avatar

@willvincent

Are you passing in an order id there? YES

Why are you could through the auth user/etc chain to get that order? It's the relationship between user & order.

Which fine until now. I could show an invoice that belongs to that user and all the necessary details except those from the 'invoice' table.

I just fail to call $orders->invoice->amount.

Here are the relationship

User Model

    public function orders()
    {
        return $this->hasMany(Order::class);
    }

Order Model

    public function user()
    {
        return $this->belongsTo(User::class);
    }
 

    public function invoice()
    {
        return $this->hasOne(Invoice::class);
    }

Invoice Model

    public function orders()
    {
        return $this->belongsTo(Order::class);
    }
yansusanto's avatar

It turns out that I need to declare the $order & invoice var separately.

    public function show($id)
    {

        $order = auth()->user()->orders()->find($id); 
            if (! $order) return redirect('dashboard');
            
        $invoice = Invoice::with('orders')->get();

        return view('invoice')->withOrder($order);

    }

Not sure if there is a better (or cleaner) way of doing it.

willvincent's avatar

The auth->user->... chain is still weird, and seems unnecessary... and your invoice query doesn't specify any particular invoice, that's just going to get all invoices with their related order.

You're passing in an order id to this method.. right?

public function show ($id) {
  $order = Order::with('invoice')->findOrFail($id);

  return view('invoice', compact('order'));
}

Invoice will be attached to $order in the template, access it as $order->invoice

What am I missing here?

yansusanto's avatar

@willvincent

No, you're not missing anything here. Your code actually works. Thanks ;)

At the initial stage, I had

        $order = auth()->user()->orders()->find($id); 
            if (! $order) return redirect('dashboard');

So that only user can access his/her invoice and redirect when is not. For example, www.domain.com/dashboard/1/invoice where 1 is the order_id.

And thereafter I add another relationship between Order & Invoice so I can access $order->invoice->whatever.

public function show ($id) {
  $order = Order::with('invoice')->findOrFail($id);

  return view('invoice', compact('order'));
}

Now with your code (yes, it's working), I need to redirect the user to /dashboard if the user try to access www.domain.com/dashboard/2/invoice where 2 is not his order_id.

At the moment, it just gives the error not 'redirecting'.

richard's avatar

For this scenario

I need to redirect the user to /dashboard if the user try to access www.domain.com/dashboard/2/invoice where 2 is not his order_id.

You need to write a logic inside the User Model to check if a user owns an order.

User.php

public function ownsOrder($order)
{
    return order->user_id === $this->id // Returns true is he owns it.
}

And then in your controller, you can check if a user owns the order by doing this.

if( ! $auth()->user()->ownsOrder($order) ) {
    return redirect('dashboard')
}

// The rest of your logic goes here.
willvincent's avatar

You could also use try / catch to catch the exception thrown by findOrFail and do the direct instead of showing the error message.

Previous

Please or to participate in this conversation.