Installation:
composer require imanghafoori/laravel-nullable
No publisher or service provider needed—automatically registered via package discovery.
First Use Case:
Replace null checks with expressive Nullable methods. Example:
use Imanghafoori\Nullable\Nullable;
$value = Nullable::from($user->profile)->get('email');
// Equivalent to: $user->profile ? $user->profile->email : null
Key Entry Points:
Nullable::from($value) – Wrap any value (objects, arrays, scalars).get(), when(), or(), or tap() for functional workflows.Defensive Data Access:
$user = User::find(1);
$email = Nullable::from($user)
->get('profile.email') // Nested access
->or('default@example.com'); // Fallback
Conditional Logic:
Nullable::from($request->input('active'))
->when(true, fn() => $this->activateUser())
->when(false, fn() => $this->deactivateUser());
Collection/Array Handling:
$prices = Nullable::from($products)
->map(fn($p) => $p['price'])
->filter(fn($p) => $p > 100)
->toArray();
Integration with Eloquent:
$user = User::whereHas('nullable->profile', fn($q) => $q->where('active', true))->get();
// Uses `nullable` global helper for query scopes.
$value = Nullable::from($user->settings)
->get('theme')
->or(fn() => Theme::default());
Nullable::from($order->items)
->tap(fn($items) => $this->logItems($items))
->sum('price');
$input = Nullable::from($request->all())
->validate(['email' => 'required|email']);
Overuse of get():
get('a.b.c.d'))—use intermediate variables for readability.// Bad
Nullable::from($user)->get('profile.address.city');
// Good
$city = Nullable::from($user)->get('profile.address')->get('city');
Performance with Large Collections:
filter() or map() create new collections. Use toArray() early if memory is a concern.Global Helper Conflicts:
nullable() helper may clash with Laravel’s nullable() cast. Explicitly use Imanghafoori\Nullable\Nullable to avoid ambiguity.Null Checks:
Use ->isNull() or ->isNotNull() for explicit debugging:
if (Nullable::from($value)->isNull()) {
logger()->debug('Value was null');
}
Method Chaining:
If a chain fails silently, add ->then(fn($v) => logger()->debug($v)) to inspect intermediate values.
Custom Methods:
Extend the Nullable class by creating a trait or subclass:
use Imanghafoori\Nullable\Nullable;
class ExtendedNullable extends Nullable {
public function isEmpty(): bool {
return $this->value === null || ($this->value instanceof Collection && $this->value->isEmpty());
}
}
Query Builder Integration:
Override the nullable global helper in your AppServiceProvider:
use Imanghafoori\Nullable\Facades\Nullable;
Nullable::extend('custom', function ($query, $relation) {
return $query->whereHas($relation, fn($q) => $q->where('custom_field', '>', 0));
});
Testing:
Mock Nullable in tests using partial mocks:
$nullable = $this->partialMock(Nullable::class, ['get']);
$nullable->method('get')->willReturn('mocked_value');
How can I help you explore Laravel packages today?