-2

Hello i am using the Eloquent many to many method to get values from 2 tables and show its values.

This is the Order model code:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    use HasFactory;

    public $timestamps = true;

    protected $fillable = [
        'order_number',
        'client',
        'description',
    ];

    public function clients()
    {
        return $this->belongsToMany(Client::class); 
    }
}

Here is the controller code to open a new window with all the values from table B

 public function index()
    {
        $orders = Order::all();
        return view('orders/index',compact('orders'))
            ->with('i', (request()->input('page', 1) - 1) * 5);
    }

Then this is what i am doin in the view:

@foreach($orders as $order)
{{$order->name}}
@endforeach
 //this works

but if i do

@foreach($orders->clients as $client)
{{$client->name}}
@endforeach
//i get the error

Property [clients] does not exist on this collection instance. Even though is declared in the model Order

laraCoder
  • 261
  • 15
  • Try `dd($orders);` in your view to see what `$orders` actually looks like. It is a *Collection* of individual orders - think of that as an array. An array has no relationships. It is a group of objects which have relationships. `@foreach($orders as $order) {{ $order->name}}, @foreach($order->clients as $client) {{ $client->name }} @endforeach @endforeach` – Don't Panic Jan 28 '23 at 21:14
  • 1
    There are plenty of questions on Stackoverflow for this error: https://stackoverflow.com/questions/70030106/property-id-does-not-exist-on-this-collection-instance, https://stackoverflow.com/questions/63219872/property-role-does-not-exist-on-this-collection-instance, https://stackoverflow.com/questions/41366092/property-title-does-not-exist-on-this-collection-instance, etc. `$orders` is a Collection, not a single `Order` instance, so your code doesn't know what `->clients` is supposed to be. `$orders as $order`, _then_ `$order->clients`, or read any of the linked questions for more details. – Tim Lewis Jan 28 '23 at 21:29

2 Answers2

0

Your error is that you are assuming you are getting clients, that is true, but you are not getting them as a property like $orders->clients, $orders is a Collection, that is what BelongsToMany returns.

So, your code should be:

@foreach($orders as $order)
    {{ $order->name }}
@endforeach

Due to each entry on a Collection is going to be an Order object, that is why $order->name works ($order is literally an Order).

The only time $orders->clients is going to work for you, is when $order is an Order:

$order1 = Order::find(1);

// Or

$order2 = new Order;

// Then you have ->clients available

$clients1 = $order1->clients();
// This returns a Collection with Client if you have a relationship with $order1

$clients2 = $order2->clients();
// This return an EMPTY Collection as you have no relation at all on the pivot table with this new, non-saved $order2 object

// Now you can iterate $clients1 assuming you got data back
foreach ($clients1 as $client) {
    // $client is a normal Client object, you have all the properties and methods available
    // Do whatever you need here
}

So, when you have a Collection in $orders, there is no "property" (related to the relationship, clients in this case), remember that a Collection is an array with steroids, so the Collection does not know anything about what it has inside of itself.

matiaslauriti
  • 7,065
  • 4
  • 31
  • 43
  • So how can i fetch the name from table `Clients` when the `$order->client` just gives me the `id` of the `client` from table `Client` – laraCoder Jan 28 '23 at 21:11
  • `$order->client` does not give you the ID, it is `$order->clients` (see the `s` at the end). As I said in my explanation, `->clients` is going to return a `Collection` (it can be empty or not, depends if it found any relationship). So you have to iterate the `Collection` and you can access the normal properties your `Client` has. I have added more code to the explanation – matiaslauriti Jan 28 '23 at 21:14
-1

can you try to include the model in the Order class as you have not defined it. Check below

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    use HasFactory;

    public $timestamps = true;

    protected $fillable = [
        'order_number',
        'client',
        'description',
    ];

    public function clients()
    {
        return $this->belongsToMany('App\Models\Client'); 
    }
}

Alternatively

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Models\Client;

class Order extends Model
{
    use HasFactory;

    public $timestamps = true;

    protected $fillable = [
        'order_number',
        'client',
        'description',
    ];

    public function clients()
    {
        return $this->belongsToMany(Client::class); 
    }
}

both above would then make you able to reference the relationship.

All the best.

matiaslauriti
  • 7,065
  • 4
  • 31
  • 43
Charles
  • 349
  • 3
  • 9
  • 1
    The user has the `clients` relationship defined, what am I missing on your answer? – matiaslauriti Jan 28 '23 at 21:01
  • I just properly namespaced the Models in the file. By simply calling Client::class, the relationship will not pick up. You need to explicitly call it as App\Models\Client. That's what I just picked up from the posted code. If not above, maybe a different solution might work. – Charles Jan 28 '23 at 21:43
  • 1
    That is not true, `App\Models\Client` is exactly the same as `Client::class`. The error is that the user gets a `Collection` and is trying to get properties from it – matiaslauriti Jan 28 '23 at 21:47
  • `Client::class` is the correct syntax. Also, since `Client` and `Order` have the same namespace `namespace App\Models;`, you don't need to add `use App\Models\Client;`. You only need to import the class via that `use` statement if they have different namespaces, or an ambiguous resolution (i.e. two classes with the same name, you need to import to specify which one to use). This is not the correct answer, sorry. – Tim Lewis Jan 30 '23 at 20:48
  • Thanks @Tim. I was made aware of my error. I believe in a older version of Laravel you had to explicitly call the model. – Charles Jan 30 '23 at 21:19
  • You're correct there; in earlier versions of Laravel, you'd use the `belongsToMany('App\Models\Client')` syntax, but more recent versions use the `belongsToMany(Client::class)` syntax. Both are still valid, but the 2nd approach is what is preferred, and what you'll see in the Documentation. – Tim Lewis Jan 31 '23 at 14:58