Kontynuacja lekcji poprzednich, poznajemy kolejne możliwości Laravela, rozbudowujemy swoją wiedzę nt. zagadnień bazodanowych. Do dzieła.

W jednej z poprzednich lekcji napisaliśmy coś takiego:

Artisan::command('get-doe', function () {
    $does = Person::where("firstName", "John")
    ->orWhere("firstName", "Jane")
    ->where("lastName", "Doe")
    ->select("firstName", "lastName")
    ->get();

    foreach($does as $person){
        $this->comment("{$person->firstName} {$person->lastName}");
    }
});

//Jane Doe
// John Doe
// John Fillable

Niestety logika była nieprawidłowa i John Fillable się prześlizgnął, choć nie o to chodziło. Napisaliśmy wtedy taką komendę:

Artisan::command('get-does', function () {
    $does = Person::where(function(Builder $query){
        $query->where('firstName', 'John')
        ->orWhere('firstName', 'Jane');
    })
    ->where('lastName', 'Doe')
    ->select("firstName", "lastName")
    ->get();
    

    foreach($does as $person){
        $this->comment("{$person->firstName} {$person->lastName}");
    }
});

// Jane Doe
// John Doe

Prawda jest taka, że mogliśmy ten sam efekt osiągnąć inaczej. Oto komenda:

Artisan::command('whereIn', function () {
    $does = Person::whereIn('firstName', ["Jane", "John"])
    ->where('lastName', 'Doe')
    ->select("firstName", "lastName")
    ->get();
    

    foreach($does as $person){
        $this->comment("{$person->firstName} {$person->lastName}");
    }
});

// Jane Doe
// John Doe

Tych pomocniczych funkcji where jest trochę. Z whereNull już mieliśmy do czynienia:

Artisan::command('update-created-at', function () {
    $affectedRows = Person::whereNull('created_at')
    ->update(['created_at' => \Carbon\Carbon::now()]);
    
    $this->comment($affectedRows);
    
});

Kilka przykładów (akurat z DB zamiast ORMa, ale te nazwy i działanie jest takie samo) z dokumentacji Laravela. Not null:

$users = DB::table('users')
                ->whereNotNull('updated_at')
                ->get();

Kilka do pracy z datami:

$users = DB::table('users')
                ->whereDate('created_at', '2016-12-31')
                ->get();

$users = DB::table('users')
                ->whereMonth('created_at', '12')
                ->get();

$users = DB::table('users')
                ->whereDay('created_at', '31')
                ->get();

$users = DB::table('users')
                ->whereYear('created_at', '2016')
                ->get();

Ok, wyciągnijmy takie rekordy, gdzie imię i nazwisko jest takie samo:

$users = DB::table('users')
                ->whereColumn('first_name', 'last_name')
                ->get();

Wyciągnijmy te, które były updatowane (czyli dostały updated at i created at, ale updated at jest później, znaczy był update):

$users = DB::table('users')
                ->whereColumn('updated_at', '>', 'created_at')
                ->get();

Jeszcze bardziej zaawansowane zabawy z kolumnami:

users = DB::table('users')
                ->whereColumn([
                    ['first_name', '=', 'last_name'],
                    ['updated_at', '>', 'created_at'],
                ])->get();

Sprawdzanie kolumn „pomiędzy”:

$patients = DB::table('patients')
                       ->whereBetweenColumns('weight', ['minimum_allowed_weight', 'maximum_allowed_weight'])
                       ->get();

$patients = DB::table('patients')
                       ->whereNotBetweenColumns('weight', ['minimum_allowed_weight', 'maximum_allowed_weight'])
                       ->get();

Sprawdzanie pomiędzy i nie pomiędzy jakimiś wartościami:

$users = DB::table('users')
           ->whereBetween('votes', [1, 100])
           ->get();

$users = DB::table('users')
                    ->whereNotBetween('votes', [1, 100])
                    ->get();

W dokumentacji Laravela mamy całą masę innych ciekawych metod, polecam czytać. Podam tylko jeden przykład moim zdaniem też użyteczny:

$posts = DB::table('albums')
            ->where('published', true)
            ->whereNone([
                'title',
                'lyrics',
                'tags',
            ], 'like', '%explicit%')
            ->get();

A teraz jak to wygląda w SQL:

SELECT *
FROM albums
WHERE published = true AND NOT (
    title LIKE '%explicit%' OR
    lyrics LIKE '%explicit%' OR
    tags LIKE '%explicit%'
)

Ok, na razie wystarczy.