web-dev-qa-db-fra.com

Laravel Eloquent LEFT JOIN WHERE NULL

J'essaie d'utiliser Eloquent pour exécuter la requête suivante lors de l'ensemencement d'une base de données:

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

Et voici mon implémentation dans Eloquent:

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

Alors que la première requête renvoie toujours les résultats complets, l'équivalent Eloquent renvoie toujours les éléments vides pour tout sauf les champs email et phone de la table customers. Je n'arrive pas à expliquer cela puisque les modèles Customers et Orders sont tous deux des squelettes générés de manière artisanale.

Ex:

class Customer extends \Eloquent {

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

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

}

Voici le tableau qui est affiché lorsque je dd () la première requête Eloquent sur une graine (générée à l'origine par 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
}
29
eComEvo

Cela peut être résolu en spécifiant les noms de colonne spécifiques souhaités à partir de la table spécifique, de la manière suivante:

$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'
    ]);
43
eComEvo

Vous pouvez également spécifier les colonnes dans une sélection comme ceci:

$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();
5
Ioana Cucuruzan

Je viderais votre requête pour que vous puissiez jeter un coup d'œil au code SQL qui a été réellement exécuté et voir en quoi cela diffère de ce que vous avez écrit.

Vous devriez pouvoir le faire avec le code suivant:

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

J'espère que cela devrait vous donner suffisamment d'informations pour vous permettre de comprendre ce qui ne va pas.

4
Matthew Daly

Je voudrais utiliser laravel whereDoesntHave pour y parvenir.

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