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

rjruiz's avatar

Query eloquent belongsTo and hasMany (laravel-datatables)

Well, I'm having trouble showing data about my relationship with datatables. The information I want to visualize is related in the following way: I have the table customers, orders and details: a customer can have 1 to N orders. An order belongs to a customer. An order can have 1 to N details. A detail belongs to an order. Here my relationships in the requested model:


class OrderNote extends Model
{
    protected $fillable = [ 'num_order', 'status', 'date', 'finished_date'];

    public $timestamps = true;  

    protected $dates = ['date', 'finished_date'];    

    public function client()
    {
        return $this->belongsTo(Client::class);
    }  

    public function details()
    {
        return $this->hasMany(OrderDetail::class);
    } 

through this query:

$ordenes =Client::with (['orders, orders.details'])->get(); 

My OrderNote controller:

<?php

namespace App\Http\Controllers;

use App\OrderNote;
use App\Client;
use App\OrderDetail;
use DataTables;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use Illuminate\Support\Facades\DB;

use Illuminate\Http\Request;

class OrderNoteController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {

        return view('admin.orders.index');
    }

    public function dataTable()
    {
    $ordenes =Client::with (['orders, orders.details'])->get(); 

         // $ordenes = OrderNote::with('client', 'details')->get();
        // $ordenes = OrderNote::with('client')->select('clients.*');       
        // $ordenes = Client::first()->orders()->with('client');


        return dataTables::of($ordenes)
                ->addColumn('id', function ($ordenes){
                    return $ordenes->id;
                })  
                ->addColumn('fecha', function ($ordenes){
                    return $ordenes->date->format('d-m-y');
                })
                ->addColumn('cliente', function ($ordenes){
                    return
                        '<i class="fa fa-user"></i>'.' '.$ordenes->client->name_client."<br>".
                        '<i class="fa fa-phone"></i>'.' '.$ordenes->client->phone_client;                       
                }) 
                ->addColumn('producto', function ($ordenes){
                    return 
                            '<i class="fa fa-industry"></i>'.' '.$ordenes->details->name."<br>".
                            '<i class="fa fa-phone"></i>'.' '.$ordenes->details->code."<br>".
                            '<i class="fa fa-globe"></i>'.' '.$ordenes->details->description;

                })
                ->addColumn('estado', function ($ordenes){
                    return $ordenes->status;
                })                                              
                ->addColumn('accion', function ($ordenes) {
                    return view('admin.orders.partials._action', [
                        'clientes' => $ordenes,
                        'url_show' => route('admin.orders.show', $ordenes->id),
                        'url_edit' => route('admin.orders.edit', $ordenes->id),
                        'url_destroy' => route('admin.orders.destroy', $ordenes->id)
                    ]);
                })

                ->addIndexColumn()   
                ->rawColumns(['fecha', 'cliente', 'producto', 'estado', 'accion'])                
                ->make(true);          
    }

Finally my script in my index view:

<script>
        $('#datatable').DataTable({
            responsive: true,
            processing: true,
            serverSide: true,
            ajax: "{{ route('orders.table') }}",
            columns: [
                {data: 'id', name: 'id'},
                {data: 'fecha', name: 'fecha'},
                {data: 'cliente', name: 'cliente'},
                {data: 'producto', name: 'producto'},
                {data: 'estado', name: 'estado'},               
                {data: 'accion', name: 'accion'}                
            ]
        });
    </script>

details is a collection, not an object. How to access each detail in the collection to obtain its attributes. How to tour the collection with eloquent and show them in my datatables?

0 likes
7 replies
Snapey's avatar

If you are having problems with this

$ordenes =Client::with (['orders, orders.details'])->get(); 

then you need to show the Client model so we can see the orders relationship

Ideally also, your migrations.

Snapey's avatar

You also need to name your variables correctly

this

$ordenes->details->name. 

is expecting $ordenes to be an order, but its not, its a collection of clients.

rjruiz's avatar

Model client:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Client extends Model
{
    protected $fillable = [
        'name_client','lastname','address','city','province','postal_code','country','phone_client','email'
    ];

    public $timestamps = true;

    public function company()
    {
        return $this->hasOne(Company::class);
    }    

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

migrations clients:

    public function up()
    {
        Schema::create('clients', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name_client', 80);
            $table->string('lastname', 80);
            $table->string('address', 80)->nullable();
            $table->string('city', 80)->nullable();
            $table->string('province', 80)->nullable();
            $table->string('postal_code', 30)->nullable();
            $table->string('country', 60)->nullable();
            $table->string('phone_client', 30);
            $table->string('email', 100)->unique()->nullable();
            $table->timestamps();                      
        });
    }

migrations order_notes:

public function up()
    {
        Schema::create('order_notes', function (Blueprint $table) {
            $table->increments('id');

            $table->integer('client_id')->unsigned();          

            $table->integer('num_order')->unique();
            $table->enum('status', ['EN PROCESO', 'TERMINADO', 'NO TERMINADO'])->default('EN PROCESO');
            $table->timestamp('date')->nullable();
            $table->timestamp('finished_date')->nullable();

            $table->foreign('client_id')->references('id')->on('clients')
            ->onDelete('cascade')
            ->onUpdate('cascade');           
          
            $table->timestamps();
        });
    }

migrations order_details:

public function up()
    {
        Schema::create('order_details', function (Blueprint $table) {
            $table->increments('id');
            
            $table->integer('order_note_id')->unsigned();

            $table->integer('code')->unique();
            $table->string('name', 80);
            $table->integer('quantity');
            $table->mediumText('description')->nullable();

            $table->foreign('order_note_id')->references('id')->on('order_notes')
            ->onDelete('cascade')
            ->onUpdate('cascade'); 
            
           
            $table->timestamps();
        });
    }

How to access each detail in the collection to obtain its attributes. ? I modify my query?

Snapey's avatar

You are going to have to be explicit about the key names since you don't follow convention.

Add the local and foreign keys to each relationship.

Also in your controller, did you mean to get all orders for all clients?

rjruiz's avatar

I was reviewing the relationships: model client:

   public function ordernotes()
    {
        return $this->hasMany(OrderNote::class);
    } 

model ordernote

public function client()
    {
        return $this->belongsTo(Client::class);
    }   

    public function orderdetails()
    {
        return $this->hasMany(OrderDetail::class, 'id', 'order_detail_id');
    } 

model orderdetail

  public function ordernote()
    {
        return $this->belongsTo(OrderNote::class, 'id' ,'order_note_id');
    }  

I still can't show the detail of each order that belongs to you to a client. What I want to show in my datatables are the orders with their details from all customers

I have problems with the product column I can not access the detail right here name and code:


    public function dataTable()
    {
        $clientes = OrderNote::with(['client', 'orderdetails'])->get();             
        return dataTables::of($clientes)
                ->addColumn('id', function ($clientes){
                    return $clientes->id;
                })  
                ->addColumn('fecha', function ($clientes){                 
                    
                    return $clientes->created_at->format('d-m-y');
                })
                ->addColumn('cliente', function ($clientes){

                    return
                        '<i class="fa fa-user"></i>'.' '.$clientes->client->name_client."<br>".
                        '<i class="fa fa-phone"></i>'.' '.$clientes->client->phone_client;
                                   
                }) 
              **  ->addColumn('producto', function ($clientes){
                    
                    return 
                    '<i class="fa fa-industry"></i>'.' '.$clientes->orderdetails->name."<br>".
                    '<i class="fa fa-phone"></i>'.' '.$clientes->orderdetails->code."<br>".
                  
                })**
                ->addColumn('estado', function ($clientes){
                    return $clientes->status;
                })                                              
                ->addColumn('accion', function ($clientes) {
                    return view('admin.orders.partials._action', [
                        'clientes' => $clientes,
                        'url_show' => route('admin.orders.show', $clientes->id),
                        'url_edit' => route('admin.orders.edit', $clientes->id),
                        'url_destroy' => route('admin.orders.destroy', $clientes->id)
                    ]);
                })
               
                ->addIndexColumn()   
                ->rawColumns(['fecha', 'cliente', 'producto', 'estado', 'accion'])                
                ->make(true);          
    }
rjruiz's avatar

I receive this error: Property [name] does not exist on this collection instance.

Snapey's avatar

perhaps you have an order with no order details?

Edit

Actually, no, this is not going to work. You have MANY order details per order. You cannot list order and order details on the same row of a table due to the 1:many relationship

$clientes->orderdetails is a collection of orderdetails linked to order. You cannot pluck out a single 'name' since that would require it be a 1:1 relationship

Please or to participate in this conversation.