Подтвердить что ты не робот

Laravel Eloquent LEFT JOIN WHERE NULL

Я пытаюсь использовать Eloquent для выполнения следующего запроса во время семени базы данных:

SELECT
    *
FROM
    customers
LEFT JOIN
    orders
    ON customers.id = orders.customer_id
WHERE
    orders.customer_id IS NULL

И вот моя реализация в Eloquent:

$c = Customer::leftJoin('orders', function($join) {
      $join->on('customers.id', '=', 'orders.customer_id');
    })
    ->whereNull('orders.customer_id')
    ->first();

В то время как первый запрос всегда возвращает полные результаты, эквивалент Eloquent всегда возвращает пустые элементы для всех, кроме полей email и phone таблицы customers. Я затрудняюсь объяснить это, так как модели customers и Orders являются сгенерированными как сгенерированные ремесленником скелеты.

Пример:

class Customer extends \Eloquent {

    // Add your validation rules here
    public static $rules = [
        // 'title' => 'required'
    ];

    // Don't forget to fill this array
    protected $fillable = [];

}

Вот массив, который выводится, когда я dd() первый запрос Eloquent на семя (сгенерированный первоначально Faker):

protected $original =>
  array(25) {
    'id' =>
    NULL
    'first_name' =>
    NULL
    'last_name' =>
    NULL
    'email' =>
    string(24) "[email protected]"
    'phone' =>
    string(17) "642.150.9176x5684"
    'address1' =>
    NULL
    'address2' =>
    NULL
    'city' =>
    NULL
    'state' =>
    NULL
    'county' =>
    NULL
    'district' =>
    NULL
    'postal_code' =>
    NULL
    'country' =>
    NULL
    'notes' =>
    NULL
    'created_at' =>
    NULL
    'updated_at' =>
    NULL
    'customer_id' =>
    NULL
    'total' =>
    NULL
}
4b9b3361

Ответ 1

Это можно устранить, указав нужные имена столбцов из конкретной таблицы следующим образом:

$c = Customer::leftJoin('orders', function($join) {
      $join->on('customers.id', '=', 'orders.customer_id');
    })
    ->whereNull('orders.customer_id')
    ->first([
        'customers.id',
        'customers.first_name',
        'customers.last_name',
        'customers.email',
        'customers.phone',
        'customers.address1',
        'customers.address2',
        'customers.city',
        'customers.state',
        'customers.county',
        'customers.district',
        'customers.postal_code',
        'customers.country'
    ]);

Ответ 2

Я бы сбросил ваш запрос, чтобы вы могли взглянуть на фактически выполненный SQL и посмотреть, как это отличается от того, что вы написали.

Вы можете сделать это со следующим кодом:

$queries = DB::getQueryLog();
$last_query = end($queries);
var_dump($last_query);
die();

Надеюсь, это должно дать вам достаточно информации, чтобы вы могли понять, что пошло не так.

Ответ 3

Вы также можете указать столбцы в select так:

$c = Customer::select('*', DB::raw('customers.id AS id, customers.first_name AS first_name, customers.last_name AS last_name'))
->leftJoin('orders', function($join) {
  $join->on('customers.id', '=', 'orders.customer_id') 
})->whereNull('orders.customer_id')->first();

Ответ 4

Я бы использовал laravel whereDoesntHave для достижения этой цели.

Customer::whereDoesntHave('orders')->get();