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

Shedman's avatar

Join tables without mixing variables

I have been following the Laravel from scratch and Jeffery creates a post table with an id. I have created a customer table with an id and a contracts table with an id, but the user table also has an id. So when I request a customer with hasMany contracts I need to include the customer with the query. I use this;

return $this->hasMany(Contracts::class)->leftJoin('customers','customers.id','=','customers_id');

After joining, I DD the results the id is now the customer id and there is no contract id. Normally I would alias the ids so they would not get mixed up. So my question is should I not use the generic id for each table? Or is there a nice way to Join tables in Eloquent without the id's being consolidated?

0 likes
6 replies
rodrigo.pedra's avatar

You can select only the columns you need:

return $this->hasMany(Contracts::class)
    ->selectRaw('contracts.*')
    ->leftJoin('customers','customers.id','=','customers_id');

Unfortunately when there are conflicting column names PDO (the underlying PHP classes Laravel Eloquent is built upon) will override conflicting columns.

MichalOravec's avatar

Don't mix relationships and joins together.

Also when you have to use join for join tables then everytime use select and for most case just for main table as select('main_table.*')

1 like
rodrigo.pedra's avatar

I commented on a GitHub issue yesterday about this PDO limitation:

https://github.com/laravel/framework/issues/35019#issuecomment-718804783

If you are running MySQL 8 locally you can try check this code:

<?php

$sql =<<<SQL
WITH `company` AS (
    SELECT 1 AS `companyID`, 'Company A' AS `alias`
    UNION
    SELECT 2, 'Company B'
    UNION
    SELECT 3, 'Company C'
),
`company_site` AS (
    SELECT 1 AS `companyID`, 'foo' AS `alias`
    UNION
    SELECT 2, 'bar'
    UNION
    SELECT 3, 'baz'
)
SELECT *
FROM
    company as c
    JOIN company_site as cs
        ON c.companyID = cs.companyID
WHERE cs.alias = 'foo'
SQL;

$pdo = new \PDO('mysql:host=127.0.0.1;dbname=dummy', 'root', '123456');

$statement = $pdo->query($sql, \PDO::FETCH_ASSOC);

\print_r($statement->fetchAll());

echo PHP_EOL;

The results will be

$ php scratch.php 
Array
(
    [0] => Array
        (
            [companyID] => 1
            [alias] => foo
        )

)

As you can see the alias column gets overriden.

Shedman's avatar

I am really sorry but this is all so new and hard to grasp. I have read and tried but I cannot get it to work.

Here is my model:

<?php

namespace App\Models;

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

class Customers extends Model
{
    use HasFactory;

    protected $guarded = [];

    public function  user() {

        return  $this->belongsTo(User::class);
    }

    public function contracts() {

        return $this->hasMany(Contracts::class);
    }
    
}

Here is the method in the Controller:

public function contracts(Customers $customer) {

        return view('contracts.index', ['contracts' =>  $customer->contracts]);
    }

The Route:

Route::get('/customers/{customer}/contracts', [CustomersController::class, 'contracts']);

This gets me all my contracts for a certain customer. Along with these contracts, I need the customer's info. They are connected by foreign keys Contracts/customer_id is associated with Customers/id.

Please or to participate in this conversation.