Laravel Eloquent LEFT JOIN WHERE NULL

eCo*_*Evo 32 php mysql laravel eloquent laravel-4

我正在尝试使用Eloquent在数据库种子期间执行以下查询:

SELECT
    *
FROM
    customers
LEFT JOIN
    orders
    ON customers.id = orders.customer_id
WHERE
    orders.customer_id IS NULL
Run Code Online (Sandbox Code Playgroud)

这是我在Eloquent中的实现:

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

虽然第一个查询总是返回完整的结果,但Eloquent等效项总是返回除表emailphone字段之外的所有内容的空元素customers.我在无法解释这一点,因为在CustomersOrders模特都是工匠产生的骨架.

例如:

class Customer extends \Eloquent {

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

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

}
Run Code Online (Sandbox Code Playgroud)

这是我在dd()种子上的第一个Eloquent查询(最初由Faker生成)时输出的数组:

protected $original =>
  array(25) {
    'id' =>
    NULL
    'first_name' =>
    NULL
    'last_name' =>
    NULL
    'email' =>
    string(24) "luther.braun@example.org"
    '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
}
Run Code Online (Sandbox Code Playgroud)

eCo*_*Evo 46

这可以通过指定特定表所需的特定列名来解决,如下所示:

$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'
    ]);
Run Code Online (Sandbox Code Playgroud)

  • 您还可以指定获取所有列,例如 `customers.*` (2认同)

Har*_*hil 10

尽管其他答案效果很好,但我想为您提供我经常使用的备用简短版本

Customer::select('customers.*')
        ->leftJoin('orders', 'customers.id', '=', 'orders.customer_id')
        ->whereNull('orders.customer_id')->first();
Run Code Online (Sandbox Code Playgroud)

laravel version 5.3添加了一项功能,这将使您的工作更加简单,例如:

Customer::doesntHave('orders')->get();
Run Code Online (Sandbox Code Playgroud)


Mat*_*aly 6

I would dump your query so you can take a look at the SQL that was actually executed and see how that differs from what you wrote.

You should be able to do that with the following code:

$queries = DB::getQueryLog();
$last_query = end($queries);
var_dump($last_query);
die();
Run Code Online (Sandbox Code Playgroud)

Hopefully that should give you enough information to allow you to figure out what's gone wrong.


Ioa*_*zan 6

您还可以像这样在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();
Run Code Online (Sandbox Code Playgroud)