A short & sweet overview of get()
, cursor()
, chunk()
, and lazy()
to retrieve models from the database. It's a tradeoff between speed and memory usage.
At Laracon US we announced we're working on a new course at Spatie: Full Stack Artisan.
In Full Stack Artisan, we'll dive into building Laravel applications with Inertia, React, TypeScript, view models, our Laravel Data package, and more.
Last week I took a break from working on course content to set up branding and a landing page.
Read more
Today I was looking for a way to create a custom Laravel validation rule without the overhead of a new class. The rule I needed would only be used in one place, so wanted to keep it close to (or in) the request class.
Upon re-reading the validation docs, I learned that Laravel supports closures as rules.
class JournalEntryRequest extends Request
{
public function rules(): array
{
return [
// …
'lines' => [
function (string $attribute, mixed $value, Closure $fail) {
$debit = collect($value)->where('type', 'debit')->sum('amount');
$credit = collect($value)->where('type', 'credit')->sum('amount');
if ($debit !== $credit) {
$fail("Debit and credit don't match.");
}
if ($debit !== 0) {
$fail("Amount must be greater than 0.");
}
},
]
];
}
}
Just what I needed!
When you want to compare two database columns in Laravel, you can't use where
because it treats the argument you're comparing to as a value.
Instead, Laravel has a whereColumn
method you can use to compare a value to another column's value.
// Retrieve posts that were updated after
// they were published.
Post::query()
->whereColumn('updated_at', '>', 'published_at')
->get();
When using whereHas
in Laravel, it's not uncommon to also eager load the relation using with
.
$posts = Post::query()
->with('author')
->whereHas('author', function (Builder $query) {
$query->where('name', 'Seb');
})
->get();
Laravel also has a more succinct method that combines the two: withWhereHas
.
$posts = Post::query()
->withWhereHas('author', function (Builder $query) {
$query->where('name', 'Seb');
})
->get();
Putting this in a blog post because I always forget.
To view PHP logs from Laravel Valet:
open ~/.config/valet/Log/php-fpm.log
To view NGINX logs from Laravel Valet:
open ~/.config/valet/Log/nginx-error.log
In Laravel, you can register a class as a singleton to always resolve the same object.
However, you might want to build another instance of the class. You could manually construct the class without Laravel's container, but if it has a bunch of dependencies it can be tedious.
With the build
method, Laravel won't resolve a registered instance of the class, but build a new one with the container.
// AppServiceProvider::register()
$this->app->singleton(MastodonClient::class);
// Resolve the singleton instance from the container
$mastodon = resolve(MastodonClient::class);
// Build a new instance
$anotherMastodon = app()->build(MastodonClient::class);
This can be useful when a Laravel package registers a class as a singleton but you need another instance.
Freek shares a few patterns we employ to let developers override behaviour in our packages.
One of the ways we keep maintenance burden low is by making our packages customizable. In this blog post, I'd like to cover some of our best tips to make a Laravel package easy to customize. Some of these tips will apply to regular projects as well.
Laravel 9 is fresh out the door, and it contains a small contribution of mine: a new callOnce
method for database seeders.
Read more
An overview on view models in Laravel
Read more
The other day I needed to sort a dataset in MySQL and ensure one value was always at the end. I never fully understood how order by
works, so I did some research on how to solve my problem and how order by
behaves.
Read more
I use Model::findOrFail
a lot in Laravel. Recently, I realized it's not always the best option.
Read more
Our Blink package is marketed as a caching solution to memoize data for the duration of a web request. Recently, we came upon another use case for the package: to execute something once and only once.
Read more
Today, we're launching a new Spatie package: Laravel Google Fonts. I've written about Google Fonts before. It's a great font catalog, but the service has it's downsides. First, fonts are hosted on a different domain than your app, so the browser needs to do an additional DNS lookup. Second, it's Google. Privacy-minded visitors might not appreciate the trip to Silicon Valley.
Read more
I've used HasOne
relationships for 1:1
relationships, but those are rare. I haven't considered using them to scope down relationships, like having one default payment method in a set of n
methods.
<?php
class User extends Model
{
public function paymentMethods(): HasMany
{
return $this->hasMany(PaymentMethod::class);
}
public function defaultPaymentMethod(): ?HasOne
{
return $this->hasOne(PaymentMethod::class)
->whereDefault();
}
}
$user->defaultPaymentMethod;
After reading Tim's post, I have a feeling there are some places where I needed this but didn't think of it at the time…